diff --git a/.appveyor.yml b/.appveyor.yml
index dc258ad061..8e6a2ba363 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -13,7 +13,9 @@ cache:
environment:
matrix:
- - php: 7.2
+ - php: 7.2.23
+ - php: 7.3.10
+ - php: 7.1.32
init:
- SET PATH=C:\Program Files\OpenSSL;c:\tools\php;C:\tools\composer;%PATH%
@@ -25,14 +27,15 @@ install:
- ps: |
# Check if installation is cached
if (!(Test-Path c:\tools\php)) {
- appveyor-retry cinst --params '""/InstallDir:C:\tools\php""' --ignore-checksums -y php --version ((choco search php --exact --all-versions -r | select-string -pattern $env:php | sort { [version]($_ -split '\|' | select -last 1) } -Descending | Select-Object -first 1) -replace '[php|]','')
+ appveyor-retry cinst --params '""/InstallDir:C:\tools\php""' --no-progress --ignore-checksums -y php --version $env:php
# install sqlite
- appveyor-retry cinst -y sqlite
+ appveyor-retry cinst -y sqlite --no-progress
Get-ChildItem -Path c:\tools\php
cd c:\tools\php
# Set PHP environment items that are always needed
copy php.ini-production php.ini
+
Add-Content php.ini "`n date.timezone=UTC"
Add-Content php.ini "`n extension_dir=ext"
Add-Content php.ini "`n memory_limit=1G"
diff --git a/.travis.yml b/.travis.yml
index 13470bc4f4..c3f620154e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -36,6 +36,7 @@ jobs:
- stage: Test
env: COVERAGE
+ php: 7.2
before_script:
- mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{.disabled,}
- if [[ ! $(php -m | grep -si xdebug) ]]; then echo "xdebug required for coverage"; exit 1; fi
@@ -47,10 +48,12 @@ jobs:
- stage: Code Quality
env: CODING_STANDARDS
+ php: 7.2
install: travis_retry composer install --prefer-dist
script: ./vendor/bin/phpcs
- stage: Code Quality
env: STATIC_ANALYSIS
+ php: 7.2
install: travis_retry composer install --prefer-dist
script: vendor/bin/phpstan analyse
diff --git a/UPGRADE.md b/UPGRADE.md
index 05503c7f90..42b84f516f 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -1,3 +1,73 @@
+# Upgrade to 3.0
+
+- The "version" is the FQCN of the migration class (existing entries in the migrations table will be automatically updated).
+- `MigrationsEventArgs` and `MigrationsVersionEventArgs` expose different API,
+please refer to the [Code BC breaks](#code-bc-breaks) section.
+
+## Console
+- Console output changed. The commands use a different output style. If you were relying on specific output,
+ please update your scripts.
+ Console output is not covered by the BC promise, so please try not to rely on specific a output.
+ Different levels of verbosity are available now (`-v`, `-vv` and `-vvv` ).
+
+## Migrations table
+
+- The migrations table now has a new column named `execution_time`.
+
+
+## Configuration files
+
+*migrations.php Before*
+```php
+ 'My Project Migrations',
+ 'migrations_namespace' => 'MyProject\Migrations',
+ 'table_name' => 'doctrine_migration_versions',
+ 'column_name' => 'version',
+ 'column_length' => 14,
+ 'executed_at_column_name' => 'executed_at',
+ 'migrations_directory' => '/data/doctrine/migrations-docs-example/lib/MyProject/Migrations',
+ 'all_or_nothing' => true,
+ 'check_database_platform' => true,
+];
+```
+*migrations.php After*
+
+```php
+ 'My Project Migrations',
+
+ 'table_storage' => [
+ 'table_name' => 'doctrine_migration_versions',
+ 'version_column_name' => 'version',
+ 'version_column_length' => 1024,
+ 'executed_at_column_name' => 'executed_at',
+ 'execution_time_column_name' => 'execution_time',
+ ],
+
+ 'migrations_paths' => [
+ 'MyProject\Migrations' => '/data/doctrine/migrations/lib/MyProject/Migrations',
+ 'MyProject\Component\Migrations' => './Component/MyProject/Migrations',
+ ],
+
+ 'all_or_nothing' => true,
+ 'check_database_platform' => true,
+];
+```
+
+Files in XML, YAML or JSON also changed in a similar way. Please refer to the official documentation for more details.
+
+## Code BC breaks
+
+Most of the code is protected by the `@internal` declaration and in a very rare cases you might have dealt with the
+internals of this library.
+You can use [Roave/BackwardCompatibilityCheck](https://github.com/Roave/BackwardCompatibilityCheck) and get a list of
+changed elements.
+
# Upgrade to 2.0
## BC Break: Moved `Doctrine\DBAL\Migrations` to `Doctrine\Migrations`
diff --git a/composer.json b/composer.json
index bae11be358..b2968ac745 100644
--- a/composer.json
+++ b/composer.json
@@ -23,11 +23,12 @@
"doctrine/coding-standard": "^6.0",
"doctrine/orm": "^2.6",
"jdorn/sql-formatter": "^1.1",
- "mikey179/vfsstream": "^1.6",
- "phpstan/phpstan": "^0.10",
- "phpstan/phpstan-deprecation-rules": "^0.10",
- "phpstan/phpstan-phpunit": "^0.10",
- "phpstan/phpstan-strict-rules": "^0.10",
+ "mikey179/vfsStream": "^1.6",
+ "phpstan/phpstan": "^0.11",
+ "phpstan/phpstan-deprecation-rules": "^0.11",
+ "phpstan/phpstan-phpunit": "^0.11",
+ "phpstan/phpstan-strict-rules": "^0.11",
+ "phpstan/phpstan-symfony": "^0.11.6",
"phpunit/phpunit": "^7.0",
"symfony/process": "^3.4||^4.0||^5.0",
"symfony/yaml": "^3.4||^4.0||^5.0"
@@ -51,7 +52,7 @@
},
"extra": {
"branch-alias": {
- "dev-master": "2.2.x-dev"
+ "dev-master": "3.0.x-dev"
}
},
"bin": [
diff --git a/composer.lock b/composer.lock
index d93197b282..e1f817c24f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1,23 +1,23 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "e970ed6b0b7248e533782fd05f3c826e",
+ "content-hash": "ac6d10e61fd24b634b7e7ea46fd61e48",
"packages": [
{
"name": "doctrine/cache",
- "version": "v1.7.1",
+ "version": "v1.8.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
- "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a"
+ "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/cache/zipball/b3217d58609e9c8e661cd41357a54d926c4a2a1a",
- "reference": "b3217d58609e9c8e661cd41357a54d926c4a2a1a",
+ "url": "https://api.github.com/repos/doctrine/cache/zipball/d768d58baee9a4862ca783840eca1b9add7a7f57",
+ "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57",
"shasum": ""
},
"require": {
@@ -28,8 +28,9 @@
},
"require-dev": {
"alcaeus/mongo-php-adapter": "^1.1",
+ "doctrine/coding-standard": "^4.0",
"mongodb/mongodb": "^1.1",
- "phpunit/phpunit": "^5.7",
+ "phpunit/phpunit": "^7.0",
"predis/predis": "~1.0"
},
"suggest": {
@@ -38,7 +39,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.7.x-dev"
+ "dev-master": "1.8.x-dev"
}
},
"autoload": {
@@ -73,12 +74,12 @@
}
],
"description": "Caching library offering an object-oriented API for many cache backends",
- "homepage": "http://www.doctrine-project.org",
+ "homepage": "https://www.doctrine-project.org",
"keywords": [
"cache",
"caching"
],
- "time": "2017-08-25T07:02:50+00:00"
+ "time": "2018-08-21T18:01:43+00:00"
},
{
"name": "doctrine/dbal",
@@ -238,16 +239,16 @@
},
{
"name": "ocramius/package-versions",
- "version": "1.3.0",
+ "version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/PackageVersions.git",
- "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f"
+ "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f",
- "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f",
+ "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb",
+ "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb",
"shasum": ""
},
"require": {
@@ -256,6 +257,7 @@
},
"require-dev": {
"composer/composer": "^1.6.3",
+ "doctrine/coding-standard": "^5.0.1",
"ext-zip": "*",
"infection/infection": "^0.7.1",
"phpunit/phpunit": "^7.0.0"
@@ -283,37 +285,38 @@
}
],
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
- "time": "2018-02-05T13:05:30+00:00"
+ "time": "2019-02-21T12:16:21+00:00"
},
{
"name": "ocramius/proxy-manager",
- "version": "2.1.1",
+ "version": "2.2.3",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/ProxyManager.git",
- "reference": "e18ac876b2e4819c76349de8f78ccc8ef1554cd7"
+ "reference": "4d154742e31c35137d5374c998e8f86b54db2e2f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/e18ac876b2e4819c76349de8f78ccc8ef1554cd7",
- "reference": "e18ac876b2e4819c76349de8f78ccc8ef1554cd7",
+ "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/4d154742e31c35137d5374c998e8f86b54db2e2f",
+ "reference": "4d154742e31c35137d5374c998e8f86b54db2e2f",
"shasum": ""
},
"require": {
- "ocramius/package-versions": "^1.1.1",
- "php": "^7.1.0",
- "zendframework/zend-code": "^3.1.0"
+ "ocramius/package-versions": "^1.1.3",
+ "php": "^7.2.0",
+ "zendframework/zend-code": "^3.3.0"
},
"require-dev": {
- "couscous/couscous": "^1.5.2",
+ "couscous/couscous": "^1.6.1",
"ext-phar": "*",
- "humbug/humbug": "dev-master@DEV",
- "nikic/php-parser": "^3.0.4",
+ "humbug/humbug": "1.0.0-RC.0@RC",
+ "nikic/php-parser": "^3.1.1",
+ "padraic/phpunit-accelerator": "dev-master@DEV",
"phpbench/phpbench": "^0.12.2",
- "phpstan/phpstan": "^0.6.4",
- "phpunit/phpunit": "^5.6.4",
- "phpunit/phpunit-mock-objects": "^3.4.1",
- "squizlabs/php_codesniffer": "^2.7.0"
+ "phpstan/phpstan": "dev-master#856eb10a81c1d27c701a83f167dc870fd8f4236a as 0.9.999",
+ "phpstan/phpstan-phpunit": "dev-master#5629c0a1f4a9c417cb1077cf6693ad9753895761",
+ "phpunit/phpunit": "^6.4.3",
+ "squizlabs/php_codesniffer": "^2.9.1"
},
"suggest": {
"ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects",
@@ -352,40 +355,96 @@
"proxy pattern",
"service proxies"
],
- "time": "2017-05-04T11:12:50+00:00"
+ "time": "2019-08-10T08:37:15+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "time": "2017-02-14T16:28:37+00:00"
},
{
"name": "symfony/console",
- "version": "v4.0.9",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae"
+ "reference": "929ddf360d401b958f611d44e726094ab46a7369"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
- "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
+ "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369",
+ "reference": "929ddf360d401b958f611d44e726094ab46a7369",
"shasum": ""
},
"require": {
"php": "^7.1.3",
- "symfony/polyfill-mbstring": "~1.0"
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php73": "^1.8",
+ "symfony/service-contracts": "^1.1"
},
"conflict": {
"symfony/dependency-injection": "<3.4",
+ "symfony/event-dispatcher": "<4.3",
"symfony/process": "<3.3"
},
+ "provide": {
+ "psr/log-implementation": "1.0"
+ },
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
- "symfony/event-dispatcher": "~3.4|~4.0",
+ "symfony/event-dispatcher": "^4.3",
"symfony/lock": "~3.4|~4.0",
- "symfony/process": "~3.4|~4.0"
+ "symfony/process": "~3.4|~4.0",
+ "symfony/var-dumper": "^4.3"
},
"suggest": {
- "psr/log-implementation": "For using the console logger",
+ "psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/lock": "",
"symfony/process": ""
@@ -393,7 +452,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -420,20 +479,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2018-04-30T01:23:47+00:00"
+ "time": "2019-10-07T12:36:49+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.8.0",
+ "version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "3296adf6a6454a050679cde90f95350ad604b171"
+ "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171",
- "reference": "3296adf6a6454a050679cde90f95350ad604b171",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17",
+ "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17",
"shasum": ""
},
"require": {
@@ -445,7 +504,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.8-dev"
+ "dev-master": "1.12-dev"
}
},
"autoload": {
@@ -479,29 +538,146 @@
"portable",
"shim"
],
- "time": "2018-04-26T10:06:28+00:00"
+ "time": "2019-08-06T08:03:45+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php73",
+ "version": "v1.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php73.git",
+ "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188",
+ "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.12-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php73\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ],
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2019-08-06T08:03:45+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v1.1.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0",
+ "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3",
+ "psr/container": "^1.0"
+ },
+ "suggest": {
+ "symfony/service-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "time": "2019-09-17T11:12:18+00:00"
},
{
"name": "symfony/stopwatch",
- "version": "v4.0.9",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
- "reference": "6795ffa2f8eebedac77f045aa62c0c10b2763042"
+ "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6795ffa2f8eebedac77f045aa62c0c10b2763042",
- "reference": "6795ffa2f8eebedac77f045aa62c0c10b2763042",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/1e4ff456bd625be5032fac9be4294e60442e9b71",
+ "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71",
"shasum": ""
},
"require": {
- "php": "^7.1.3"
+ "php": "^7.1.3",
+ "symfony/service-contracts": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -528,20 +704,20 @@
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
- "time": "2018-02-19T16:50:22+00:00"
+ "time": "2019-08-07T11:52:19+00:00"
},
{
"name": "zendframework/zend-code",
- "version": "3.3.0",
+ "version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-code.git",
- "reference": "6b1059db5b368db769e4392c6cb6cc139e56640d"
+ "reference": "46feaeecea14161734b56c1ace74f28cb329f194"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/zendframework/zend-code/zipball/6b1059db5b368db769e4392c6cb6cc139e56640d",
- "reference": "6b1059db5b368db769e4392c6cb6cc139e56640d",
+ "url": "https://api.github.com/repos/zendframework/zend-code/zipball/46feaeecea14161734b56c1ace74f28cb329f194",
+ "reference": "46feaeecea14161734b56c1ace74f28cb329f194",
"shasum": ""
},
"require": {
@@ -549,10 +725,10 @@
"zendframework/zend-eventmanager": "^2.6 || ^3.0"
},
"require-dev": {
- "doctrine/annotations": "~1.0",
+ "doctrine/annotations": "^1.0",
"ext-phar": "*",
- "phpunit/phpunit": "^6.2.3",
- "zendframework/zend-coding-standard": "^1.0.0",
+ "phpunit/phpunit": "^7.5.16 || ^8.4",
+ "zendframework/zend-coding-standard": "^1.0",
"zendframework/zend-stdlib": "^2.7 || ^3.0"
},
"suggest": {
@@ -562,8 +738,8 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev",
- "dev-develop": "3.3-dev"
+ "dev-master": "3.4.x-dev",
+ "dev-develop": "3.5.x-dev"
}
},
"autoload": {
@@ -575,13 +751,13 @@
"license": [
"BSD-3-Clause"
],
- "description": "provides facilities to generate arbitrary code using an object oriented interface",
- "homepage": "https://github.com/zendframework/zend-code",
+ "description": "Extensions to the PHP Reflection API, static code scanning, and code generation",
"keywords": [
+ "ZendFramework",
"code",
- "zf2"
+ "zf"
],
- "time": "2017-10-20T15:21:32+00:00"
+ "time": "2019-10-05T23:18:22+00:00"
},
{
"name": "zendframework/zend-eventmanager",
@@ -641,16 +817,16 @@
"packages-dev": [
{
"name": "composer/xdebug-handler",
- "version": "1.1.0",
+ "version": "1.3.3",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
- "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08"
+ "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/c919dc6c62e221fc6406f861ea13433c0aa24f08",
- "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f",
+ "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f",
"shasum": ""
},
"require": {
@@ -681,7 +857,7 @@
"Xdebug",
"performance"
],
- "time": "2018-04-11T15:42:36+00:00"
+ "time": "2019-05-27T17:52:04+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
@@ -751,16 +927,16 @@
},
{
"name": "doctrine/annotations",
- "version": "v1.6.0",
+ "version": "v1.8.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
- "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5"
+ "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5",
- "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc",
+ "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc",
"shasum": ""
},
"require": {
@@ -769,12 +945,12 @@
},
"require-dev": {
"doctrine/cache": "1.*",
- "phpunit/phpunit": "^6.4"
+ "phpunit/phpunit": "^7.5"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.6.x-dev"
+ "dev-master": "1.7.x-dev"
}
},
"autoload": {
@@ -787,6 +963,10 @@
"MIT"
],
"authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
@@ -795,10 +975,6 @@
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
- {
- "name": "Guilherme Blanco",
- "email": "guilhermeblanco@gmail.com"
- },
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
@@ -815,7 +991,7 @@
"docblock",
"parser"
],
- "time": "2017-12-06T07:11:42+00:00"
+ "time": "2019-10-01T18:55:10+00:00"
},
{
"name": "doctrine/coding-standard",
@@ -880,34 +1056,36 @@
},
{
"name": "doctrine/collections",
- "version": "v1.5.0",
+ "version": "v1.6.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
- "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf"
+ "reference": "c5e0bc17b1620e97c968ac409acbff28b8b850be"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf",
- "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/c5e0bc17b1620e97c968ac409acbff28b8b850be",
+ "reference": "c5e0bc17b1620e97c968ac409acbff28b8b850be",
"shasum": ""
},
"require": {
- "php": "^7.1"
+ "php": "^7.1.3"
},
"require-dev": {
- "doctrine/coding-standard": "~0.1@dev",
- "phpunit/phpunit": "^5.7"
+ "doctrine/coding-standard": "^6.0",
+ "phpstan/phpstan-shim": "^0.9.2",
+ "phpunit/phpunit": "^7.0",
+ "vimeo/psalm": "^3.2.2"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.3.x-dev"
+ "dev-master": "1.6.x-dev"
}
},
"autoload": {
- "psr-0": {
- "Doctrine\\Common\\Collections\\": "lib/"
+ "psr-4": {
+ "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -936,27 +1114,28 @@
"email": "schmittjoh@gmail.com"
}
],
- "description": "Collections Abstraction library",
- "homepage": "http://www.doctrine-project.org",
+ "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.",
+ "homepage": "https://www.doctrine-project.org/projects/collections.html",
"keywords": [
"array",
"collections",
- "iterator"
+ "iterators",
+ "php"
],
- "time": "2017-07-22T10:37:32+00:00"
+ "time": "2019-06-09T13:48:14+00:00"
},
{
"name": "doctrine/common",
- "version": "v2.10.0",
+ "version": "v2.11.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common.git",
- "reference": "30e33f60f64deec87df728c02b107f82cdafad9d"
+ "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/common/zipball/30e33f60f64deec87df728c02b107f82cdafad9d",
- "reference": "30e33f60f64deec87df728c02b107f82cdafad9d",
+ "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff",
+ "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff",
"shasum": ""
},
"require": {
@@ -972,14 +1151,16 @@
},
"require-dev": {
"doctrine/coding-standard": "^1.0",
- "phpunit/phpunit": "^6.3",
+ "phpstan/phpstan": "^0.11",
+ "phpstan/phpstan-phpunit": "^0.11",
+ "phpunit/phpunit": "^7.0",
"squizlabs/php_codesniffer": "^3.0",
"symfony/phpunit-bridge": "^4.0.5"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.10.x-dev"
+ "dev-master": "2.11.x-dev"
}
},
"autoload": {
@@ -992,6 +1173,10 @@
"MIT"
],
"authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
@@ -1000,10 +1185,6 @@
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
- {
- "name": "Guilherme Blanco",
- "email": "guilhermeblanco@gmail.com"
- },
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
@@ -1024,7 +1205,7 @@
"doctrine",
"php"
],
- "time": "2018-11-21T01:24:55+00:00"
+ "time": "2019-09-10T10:10:14+00:00"
},
{
"name": "doctrine/inflector",
@@ -1095,27 +1276,29 @@
},
{
"name": "doctrine/instantiator",
- "version": "1.1.0",
+ "version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
- "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda"
+ "reference": "a2c590166b2133a4633738648b6b064edae0814a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
- "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a",
+ "reference": "a2c590166b2133a4633738648b6b064edae0814a",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"require-dev": {
- "athletic/athletic": "~0.1.8",
+ "doctrine/coding-standard": "^6.0",
"ext-pdo": "*",
"ext-phar": "*",
- "phpunit/phpunit": "^6.2.3",
- "squizlabs/php_codesniffer": "^3.0.2"
+ "phpbench/phpbench": "^0.13",
+ "phpstan/phpstan-phpunit": "^0.11",
+ "phpstan/phpstan-shim": "^0.11",
+ "phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
@@ -1140,39 +1323,44 @@
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://github.com/doctrine/instantiator",
+ "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"constructor",
"instantiate"
],
- "time": "2017-07-22T11:58:36+00:00"
+ "time": "2019-03-17T17:37:11+00:00"
},
{
"name": "doctrine/lexer",
- "version": "v1.0.1",
+ "version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
- "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+ "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
- "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/e17f069ede36f7534b95adec71910ed1b49c74ea",
+ "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea",
"shasum": ""
},
"require": {
- "php": ">=5.3.2"
+ "php": "^7.2"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^6.0",
+ "phpstan/phpstan": "^0.11.8",
+ "phpunit/phpunit": "^8.2"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "1.1.x-dev"
}
},
"autoload": {
- "psr-0": {
- "Doctrine\\Common\\Lexer\\": "lib/"
+ "psr-4": {
+ "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1180,39 +1368,42 @@
"MIT"
],
"authors": [
- {
- "name": "Roman Borschel",
- "email": "roman@code-factory.org"
- },
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
- "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
- "homepage": "http://www.doctrine-project.org",
+ "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+ "homepage": "https://www.doctrine-project.org/projects/lexer.html",
"keywords": [
+ "annotations",
+ "docblock",
"lexer",
- "parser"
+ "parser",
+ "php"
],
- "time": "2014-09-09T13:34:57+00:00"
+ "time": "2019-07-30T19:33:28+00:00"
},
{
"name": "doctrine/orm",
- "version": "v2.6.1",
+ "version": "v2.6.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/orm.git",
- "reference": "87ee409783a4a322b5597ebaae558661404055a7"
+ "reference": "b52ef5a1002f99ab506a5a2d6dba5a2c236c5f43"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/orm/zipball/87ee409783a4a322b5597ebaae558661404055a7",
- "reference": "87ee409783a4a322b5597ebaae558661404055a7",
+ "url": "https://api.github.com/repos/doctrine/orm/zipball/b52ef5a1002f99ab506a5a2d6dba5a2c236c5f43",
+ "reference": "b52ef5a1002f99ab506a5a2d6dba5a2c236c5f43",
"shasum": ""
},
"require": {
@@ -1227,9 +1418,8 @@
"symfony/console": "~3.0|~4.0"
},
"require-dev": {
- "doctrine/coding-standard": "^1.0",
- "phpunit/phpunit": "^6.5",
- "squizlabs/php_codesniffer": "^3.2",
+ "doctrine/coding-standard": "^5.0",
+ "phpunit/phpunit": "^7.5",
"symfony/yaml": "~3.4|~4.0"
},
"suggest": {
@@ -1254,6 +1444,10 @@
"MIT"
],
"authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
@@ -1262,10 +1456,6 @@
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
- {
- "name": "Guilherme Blanco",
- "email": "guilhermeblanco@gmail.com"
- },
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
@@ -1281,7 +1471,7 @@
"database",
"orm"
],
- "time": "2018-02-27T07:30:56+00:00"
+ "time": "2019-09-20T14:30:26+00:00"
},
{
"name": "doctrine/persistence",
@@ -1543,23 +1733,23 @@
},
{
"name": "mikey179/vfsstream",
- "version": "v1.6.5",
+ "version": "v1.6.7",
"source": {
"type": "git",
"url": "https://github.com/bovigo/vfsStream.git",
- "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145"
+ "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145",
- "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145",
+ "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb",
+ "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.5"
+ "phpunit/phpunit": "^4.5|^5.0"
},
"type": "library",
"extra": {
@@ -1585,29 +1775,32 @@
],
"description": "Virtual file system to mock the real file system in unit tests.",
"homepage": "http://vfs.bovigo.org/",
- "time": "2017-08-01T08:02:14+00:00"
+ "time": "2019-08-01T01:38:37+00:00"
},
{
"name": "myclabs/deep-copy",
- "version": "1.7.0",
+ "version": "1.9.3",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e"
+ "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
- "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea",
+ "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea",
"shasum": ""
},
"require": {
- "php": "^5.6 || ^7.0"
+ "php": "^7.1"
+ },
+ "replace": {
+ "myclabs/deep-copy": "self.version"
},
"require-dev": {
"doctrine/collections": "^1.0",
"doctrine/common": "^2.6",
- "phpunit/phpunit": "^4.1"
+ "phpunit/phpunit": "^7.1"
},
"type": "library",
"autoload": {
@@ -1630,43 +1823,40 @@
"object",
"object graph"
],
- "time": "2017-10-19T19:58:43+00:00"
+ "time": "2019-08-09T12:45:53+00:00"
},
{
"name": "nette/bootstrap",
- "version": "v2.4.6",
+ "version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/nette/bootstrap.git",
- "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543"
+ "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/bootstrap/zipball/268816e3f1bb7426c3a4ceec2bd38a036b532543",
- "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543",
+ "url": "https://api.github.com/repos/nette/bootstrap/zipball/e1075af05c211915e03e0c86542f3ba5433df4a3",
+ "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3",
"shasum": ""
},
"require": {
- "nette/di": "~2.4.7",
- "nette/utils": "~2.4",
- "php": ">=5.6.0"
- },
- "conflict": {
- "nette/nette": "<2.2"
+ "nette/di": "^3.0",
+ "nette/utils": "^3.0",
+ "php": ">=7.1"
},
"require-dev": {
- "latte/latte": "~2.2",
- "nette/application": "~2.3",
- "nette/caching": "~2.3",
- "nette/database": "~2.3",
- "nette/forms": "~2.3",
- "nette/http": "~2.4.0",
- "nette/mail": "~2.3",
- "nette/robot-loader": "^2.4.2 || ^3.0",
- "nette/safe-stream": "~2.2",
- "nette/security": "~2.3",
- "nette/tester": "~2.0",
- "tracy/tracy": "^2.4.1"
+ "latte/latte": "^2.2",
+ "nette/application": "^3.0",
+ "nette/caching": "^3.0",
+ "nette/database": "^3.0",
+ "nette/forms": "^3.0",
+ "nette/http": "^3.0",
+ "nette/mail": "^3.0",
+ "nette/robot-loader": "^3.0",
+ "nette/safe-stream": "^2.2",
+ "nette/security": "^3.0",
+ "nette/tester": "^2.0",
+ "tracy/tracy": "^2.6"
},
"suggest": {
"nette/robot-loader": "to use Configurator::createRobotLoader()",
@@ -1675,7 +1865,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.4-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
@@ -1699,53 +1889,57 @@
"homepage": "https://nette.org/contributors"
}
],
- "description": "? Nette Bootstrap: the simple way to configure and bootstrap your Nette application.",
+ "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.",
"homepage": "https://nette.org",
"keywords": [
"bootstrapping",
"configurator",
"nette"
],
- "time": "2018-05-17T12:52:20+00:00"
+ "time": "2019-03-26T12:59:07+00:00"
},
{
"name": "nette/di",
- "version": "v2.4.12",
+ "version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/nette/di.git",
- "reference": "8e717aed2d182a26763be58c220eebaaa32917df"
+ "reference": "4aff517a1c6bb5c36fa09733d4cea089f529de6d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/di/zipball/8e717aed2d182a26763be58c220eebaaa32917df",
- "reference": "8e717aed2d182a26763be58c220eebaaa32917df",
+ "url": "https://api.github.com/repos/nette/di/zipball/4aff517a1c6bb5c36fa09733d4cea089f529de6d",
+ "reference": "4aff517a1c6bb5c36fa09733d4cea089f529de6d",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
- "nette/neon": "^2.3.3 || ~3.0.0",
- "nette/php-generator": "^2.6.1 || ~3.0.0",
- "nette/utils": "^2.4.3 || ~3.0.0",
- "php": ">=5.6.0"
+ "nette/neon": "^3.0",
+ "nette/php-generator": "^3.2.2",
+ "nette/robot-loader": "^3.2",
+ "nette/schema": "^1.0",
+ "nette/utils": "^3.0",
+ "php": ">=7.1"
},
"conflict": {
- "nette/bootstrap": "<2.4",
- "nette/nette": "<2.2"
+ "nette/bootstrap": "<3.0"
},
"require-dev": {
- "nette/tester": "^2.0",
+ "nette/tester": "^2.2",
"tracy/tracy": "^2.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.4-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
+ ],
+ "files": [
+ "src/compatibility.php"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -1764,7 +1958,7 @@
"homepage": "https://nette.org/contributors"
}
],
- "description": "? Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.",
+ "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.",
"homepage": "https://nette.org",
"keywords": [
"compiled",
@@ -1775,25 +1969,25 @@
"nette",
"static"
],
- "time": "2018-04-26T09:18:42+00:00"
+ "time": "2019-08-07T12:11:33+00:00"
},
{
"name": "nette/finder",
- "version": "v2.4.1",
+ "version": "v2.5.1",
"source": {
"type": "git",
"url": "https://github.com/nette/finder.git",
- "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547"
+ "reference": "14164e1ddd69e9c5f627ff82a10874b3f5bba5fe"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/finder/zipball/4d43a66d072c57d585bf08a3ef68d3587f7e9547",
- "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547",
+ "url": "https://api.github.com/repos/nette/finder/zipball/14164e1ddd69e9c5f627ff82a10874b3f5bba5fe",
+ "reference": "14164e1ddd69e9c5f627ff82a10874b3f5bba5fe",
"shasum": ""
},
"require": {
"nette/utils": "^2.4 || ~3.0.0",
- "php": ">=5.6.0"
+ "php": ">=7.1"
},
"conflict": {
"nette/nette": "<2.2"
@@ -1805,7 +1999,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.4-dev"
+ "dev-master": "2.5-dev"
}
},
"autoload": {
@@ -1829,37 +2023,43 @@
"homepage": "https://nette.org/contributors"
}
],
- "description": "Nette Finder: Files Searching",
+ "description": "🔍 Nette Finder: find files and directories with an intuitive API.",
"homepage": "https://nette.org",
- "time": "2017-07-10T23:47:08+00:00"
+ "keywords": [
+ "filesystem",
+ "glob",
+ "iterator",
+ "nette"
+ ],
+ "time": "2019-07-11T18:02:17+00:00"
},
{
"name": "nette/neon",
- "version": "v2.4.2",
+ "version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/nette/neon.git",
- "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622"
+ "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/neon/zipball/9eacd50553b26b53a3977bfb2fea2166d4331622",
- "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622",
+ "url": "https://api.github.com/repos/nette/neon/zipball/cbff32059cbdd8720deccf9e9eace6ee516f02eb",
+ "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"ext-json": "*",
- "php": ">=5.6.0"
+ "php": ">=7.0"
},
"require-dev": {
- "nette/tester": "~2.0",
+ "nette/tester": "^2.0",
"tracy/tracy": "^2.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.4-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
@@ -1883,30 +2083,34 @@
"homepage": "https://nette.org/contributors"
}
],
- "description": "Nette NEON: parser & generator for Nette Object Notation",
+ "description": "? Nette NEON: encodes and decodes NEON file format.",
"homepage": "http://ne-on.org",
- "time": "2017-07-11T18:29:08+00:00"
+ "keywords": [
+ "export",
+ "import",
+ "neon",
+ "nette",
+ "yaml"
+ ],
+ "time": "2019-02-05T21:30:40+00:00"
},
{
"name": "nette/php-generator",
- "version": "v3.0.4",
+ "version": "v3.2.3",
"source": {
"type": "git",
"url": "https://github.com/nette/php-generator.git",
- "reference": "b381ecacbf5a0b5f99cc0b303d5b0578d409f446"
+ "reference": "aea6e81437bb238e5f0e5b5ce06337433908e63b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/php-generator/zipball/b381ecacbf5a0b5f99cc0b303d5b0578d409f446",
- "reference": "b381ecacbf5a0b5f99cc0b303d5b0578d409f446",
+ "url": "https://api.github.com/repos/nette/php-generator/zipball/aea6e81437bb238e5f0e5b5ce06337433908e63b",
+ "reference": "aea6e81437bb238e5f0e5b5ce06337433908e63b",
"shasum": ""
},
"require": {
"nette/utils": "^2.4.2 || ~3.0.0",
- "php": ">=7.0"
- },
- "conflict": {
- "nette/nette": "<2.2"
+ "php": ">=7.1"
},
"require-dev": {
"nette/tester": "^2.0",
@@ -1915,7 +2119,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "3.2-dev"
}
},
"autoload": {
@@ -1939,7 +2143,7 @@
"homepage": "https://nette.org/contributors"
}
],
- "description": "? Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.2 features.",
+ "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.3 features.",
"homepage": "https://nette.org",
"keywords": [
"code",
@@ -1947,30 +2151,27 @@
"php",
"scaffolding"
],
- "time": "2018-04-26T16:48:20+00:00"
+ "time": "2019-07-05T13:01:56+00:00"
},
{
"name": "nette/robot-loader",
- "version": "v3.0.3",
+ "version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/nette/robot-loader.git",
- "reference": "92d4b40b49d5e2d9e37fc736bbcebe6da55fa44a"
+ "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/robot-loader/zipball/92d4b40b49d5e2d9e37fc736bbcebe6da55fa44a",
- "reference": "92d4b40b49d5e2d9e37fc736bbcebe6da55fa44a",
+ "url": "https://api.github.com/repos/nette/robot-loader/zipball/0712a0e39ae7956d6a94c0ab6ad41aa842544b5c",
+ "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
- "nette/finder": "^2.3 || ^3.0",
- "nette/utils": "^2.4 || ^3.0",
- "php": ">=5.6.0"
- },
- "conflict": {
- "nette/nette": "<2.2"
+ "nette/finder": "^2.5",
+ "nette/utils": "^3.0",
+ "php": ">=7.1"
},
"require-dev": {
"nette/tester": "^2.0",
@@ -1979,7 +2180,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "3.2-dev"
}
},
"autoload": {
@@ -2012,27 +2213,81 @@
"nette",
"trait"
],
- "time": "2017-09-26T13:42:21+00:00"
+ "time": "2019-03-08T21:57:24+00:00"
+ },
+ {
+ "name": "nette/schema",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/schema.git",
+ "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/schema/zipball/6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d",
+ "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^3.0.1",
+ "php": ">=7.1"
+ },
+ "require-dev": {
+ "nette/tester": "^2.2",
+ "tracy/tracy": "^2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "📐 Nette Schema: validating data structures against a given Schema.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "config",
+ "nette"
+ ],
+ "time": "2019-04-03T15:53:25+00:00"
},
{
"name": "nette/utils",
- "version": "v2.5.2",
+ "version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
- "reference": "183069866dc477fcfbac393ed486aaa6d93d19a5"
+ "reference": "bd961f49b211997202bda1d0fbc410905be370d4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/utils/zipball/183069866dc477fcfbac393ed486aaa6d93d19a5",
- "reference": "183069866dc477fcfbac393ed486aaa6d93d19a5",
+ "url": "https://api.github.com/repos/nette/utils/zipball/bd961f49b211997202bda1d0fbc410905be370d4",
+ "reference": "bd961f49b211997202bda1d0fbc410905be370d4",
"shasum": ""
},
"require": {
- "php": ">=5.6.0"
- },
- "conflict": {
- "nette/nette": "<2.2"
+ "php": ">=7.1"
},
"require-dev": {
"nette/tester": "~2.0",
@@ -2041,7 +2296,7 @@
"suggest": {
"ext-gd": "to use Image",
"ext-iconv": "to use Strings::webalize() and toAscii()",
- "ext-intl": "for script transliteration in Strings::webalize() and toAscii()",
+ "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
"ext-json": "to use Nette\\Utils\\Json",
"ext-mbstring": "to use Strings::lower() etc...",
"ext-xml": "to use Strings::length() etc. when mbstring is not available"
@@ -2049,15 +2304,12 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.5-dev"
+ "dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
- ],
- "files": [
- "src/loader.php"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -2076,7 +2328,7 @@
"homepage": "https://nette.org/contributors"
}
],
- "description": "? Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
+ "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
"homepage": "https://nette.org",
"keywords": [
"array",
@@ -2094,20 +2346,20 @@
"utility",
"validation"
],
- "time": "2018-05-02T17:16:08+00:00"
+ "time": "2019-03-22T01:00:30+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v4.0.2",
+ "version": "v4.2.4",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12"
+ "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/35b8caf75e791ba1b2d24fec1552168d72692b12",
- "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/97e59c7a16464196a8b9c77c47df68e4a39a45c4",
+ "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4",
"shasum": ""
},
"require": {
@@ -2115,7 +2367,7 @@
"php": ">=7.0"
},
"require-dev": {
- "phpunit/phpunit": "^6.5 || ^7.0"
+ "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0"
},
"bin": [
"bin/php-parse"
@@ -2123,7 +2375,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-master": "4.2-dev"
}
},
"autoload": {
@@ -2145,26 +2397,26 @@
"parser",
"php"
],
- "time": "2018-06-03T11:33:10+00:00"
+ "time": "2019-09-01T07:51:21+00:00"
},
{
"name": "phar-io/manifest",
- "version": "1.0.1",
+ "version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
- "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0"
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0",
- "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-phar": "*",
- "phar-io/version": "^1.0.1",
+ "phar-io/version": "^2.0",
"php": "^5.6 || ^7.0"
},
"type": "library",
@@ -2200,20 +2452,20 @@
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
- "time": "2017-03-05T18:14:27+00:00"
+ "time": "2018-07-08T19:23:20+00:00"
},
{
"name": "phar-io/version",
- "version": "1.0.1",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
- "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df"
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df",
- "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6",
"shasum": ""
},
"require": {
@@ -2247,39 +2499,37 @@
}
],
"description": "Library for handling version information and constraints",
- "time": "2017-03-05T17:38:23+00:00"
+ "time": "2018-07-08T19:19:57+00:00"
},
{
"name": "phpdocumentor/reflection-common",
- "version": "1.0.1",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
- "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
+ "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
- "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
+ "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
"shasum": ""
},
"require": {
- "php": ">=5.5"
+ "php": ">=7.1"
},
"require-dev": {
- "phpunit/phpunit": "^4.6"
+ "phpunit/phpunit": "~6"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
- "phpDocumentor\\Reflection\\": [
- "src"
- ]
+ "phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -2301,30 +2551,30 @@
"reflection",
"static analysis"
],
- "time": "2017-09-11T18:02:19+00:00"
+ "time": "2018-08-07T13:53:10+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
- "version": "4.3.0",
+ "version": "4.3.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "94fd0001232e47129dd3504189fa1c7225010d08"
+ "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08",
- "reference": "94fd0001232e47129dd3504189fa1c7225010d08",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e",
+ "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e",
"shasum": ""
},
"require": {
"php": "^7.0",
- "phpdocumentor/reflection-common": "^1.0.0",
- "phpdocumentor/type-resolver": "^0.4.0",
+ "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0",
+ "phpdocumentor/type-resolver": "~0.4 || ^1.0.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
- "doctrine/instantiator": "~1.0.5",
+ "doctrine/instantiator": "^1.0.5",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^6.4"
},
@@ -2352,41 +2602,40 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "time": "2017-11-30T07:14:17+00:00"
+ "time": "2019-09-12T14:27:41+00:00"
},
{
"name": "phpdocumentor/type-resolver",
- "version": "0.4.0",
+ "version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
+ "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
- "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9",
+ "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9",
"shasum": ""
},
"require": {
- "php": "^5.5 || ^7.0",
- "phpdocumentor/reflection-common": "^1.0"
+ "php": "^7.1",
+ "phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
- "mockery/mockery": "^0.9.4",
- "phpunit/phpunit": "^5.2||^4.8.24"
+ "ext-tokenizer": "^7.1",
+ "mockery/mockery": "~1",
+ "phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
- "phpDocumentor\\Reflection\\": [
- "src/"
- ]
+ "phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -2399,42 +2648,43 @@
"email": "me@mikevanriel.com"
}
],
- "time": "2017-07-14T14:27:02+00:00"
+ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
+ "time": "2019-08-22T18:11:29+00:00"
},
{
"name": "phpspec/prophecy",
- "version": "1.7.6",
+ "version": "1.9.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712"
+ "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712",
- "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203",
+ "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
- "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
"sebastian/comparator": "^1.1|^2.0|^3.0",
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
},
"require-dev": {
"phpspec/phpspec": "^2.5|^3.2",
- "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5"
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.7.x-dev"
+ "dev-master": "1.8.x-dev"
}
},
"autoload": {
- "psr-0": {
- "Prophecy\\": "src/"
+ "psr-4": {
+ "Prophecy\\": "src/Prophecy"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -2462,32 +2712,33 @@
"spy",
"stub"
],
- "time": "2018-04-18T13:57:24+00:00"
+ "time": "2019-10-03T11:07:50+00:00"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "0.3.1",
+ "version": "0.3.5",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74"
+ "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/2cc49f47c69b023eaf05b48e6529389893b13d74",
- "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/8c4ef2aefd9788238897b678a985e1d5c8df6db4",
+ "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4",
"shasum": ""
},
"require": {
"php": "~7.1"
},
"require-dev": {
- "consistence/coding-standard": "^2.0.0",
+ "consistence/coding-standard": "^3.5",
"jakub-onderka/php-parallel-lint": "^0.9.2",
"phing/phing": "^2.16.0",
"phpstan/phpstan": "^0.10",
"phpunit/phpunit": "^6.3",
- "slevomat/coding-standard": "^3.3.0",
+ "slevomat/coding-standard": "^4.7.2",
+ "squizlabs/php_codesniffer": "^3.3.2",
"symfony/process": "^3.4 || ^4.0"
},
"type": "library",
@@ -2508,50 +2759,58 @@
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
- "time": "2019-01-14T12:26:23+00:00"
+ "time": "2019-06-07T19:13:52+00:00"
},
{
"name": "phpstan/phpstan",
- "version": "0.10",
+ "version": "0.11.16",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "86b9f9a4421d282f3c18e0d4d1426f330c1ef21d"
+ "reference": "635cf20f3b92ce34ee94a8d2f282d62eb9dc6e1b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/86b9f9a4421d282f3c18e0d4d1426f330c1ef21d",
- "reference": "86b9f9a4421d282f3c18e0d4d1426f330c1ef21d",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/635cf20f3b92ce34ee94a8d2f282d62eb9dc6e1b",
+ "reference": "635cf20f3b92ce34ee94a8d2f282d62eb9dc6e1b",
"shasum": ""
},
"require": {
- "composer/xdebug-handler": "^1.0",
+ "composer/xdebug-handler": "^1.3.0",
"jean85/pretty-package-versions": "^1.0.3",
"nette/bootstrap": "^2.4 || ^3.0",
"nette/di": "^2.4.7 || ^3.0",
"nette/robot-loader": "^3.0.1",
+ "nette/schema": "^1.0",
"nette/utils": "^2.4.5 || ^3.0",
- "nikic/php-parser": "^4.0.2",
+ "nikic/php-parser": "^4.2.3",
"php": "~7.1",
- "phpstan/phpdoc-parser": "^0.3",
+ "phpstan/phpdoc-parser": "^0.3.5",
"symfony/console": "~3.2 || ~4.0",
"symfony/finder": "~3.2 || ~4.0"
},
+ "conflict": {
+ "symfony/console": "3.4.16 || 4.1.5"
+ },
"require-dev": {
- "brianium/paratest": "^2.0",
- "consistence/coding-standard": "^3.3",
+ "brianium/paratest": "^2.0 || ^3.0",
+ "consistence/coding-standard": "^3.5",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
- "ext-gd": "*",
"ext-intl": "*",
"ext-mysqli": "*",
+ "ext-simplexml": "*",
+ "ext-soap": "*",
"ext-zip": "*",
"jakub-onderka/php-parallel-lint": "^1.0",
+ "localheinz/composer-normalize": "^1.1.0",
"phing/phing": "^2.16.0",
- "phpstan/phpstan-php-parser": "^0.10",
- "phpstan/phpstan-phpunit": "^0.10",
- "phpstan/phpstan-strict-rules": "^0.10",
- "phpunit/phpunit": "^7.0",
- "slevomat/coding-standard": "^4.6.2"
+ "phpstan/phpstan-deprecation-rules": "^0.11",
+ "phpstan/phpstan-php-parser": "^0.11",
+ "phpstan/phpstan-phpunit": "^0.11",
+ "phpstan/phpstan-strict-rules": "^0.11",
+ "phpunit/phpunit": "^7.5.14 || ^8.0",
+ "slevomat/coding-standard": "^4.7.2",
+ "squizlabs/php_codesniffer": "^3.3.2"
},
"bin": [
"bin/phpstan"
@@ -2559,14 +2818,13 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "0.10-dev"
+ "dev-master": "0.11-dev"
}
},
"autoload": {
"psr-4": {
"PHPStan\\": [
- "src/",
- "build/PHPStan"
+ "src/"
]
}
},
@@ -2575,40 +2833,45 @@
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
- "time": "2018-06-24T17:49:58+00:00"
+ "time": "2019-09-17T11:19:51+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
- "version": "0.10",
+ "version": "0.11.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-deprecation-rules.git",
- "reference": "ae3a84298c5d93ff82783d2ae8c5a5859dd94c2a"
+ "reference": "5685fe48873efc5af1f2cc95d9c1b8ae82c728fe"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/ae3a84298c5d93ff82783d2ae8c5a5859dd94c2a",
- "reference": "ae3a84298c5d93ff82783d2ae8c5a5859dd94c2a",
+ "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/5685fe48873efc5af1f2cc95d9c1b8ae82c728fe",
+ "reference": "5685fe48873efc5af1f2cc95d9c1b8ae82c728fe",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.0",
"php": "~7.1",
- "phpstan/phpstan": "^0.10"
+ "phpstan/phpstan": "^0.11.8"
},
"require-dev": {
"consistence/coding-standard": "^3.0.1",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
"jakub-onderka/php-parallel-lint": "^1.0",
"phing/phing": "^2.16.0",
- "phpstan/phpstan-phpunit": "^0.10",
+ "phpstan/phpstan-phpunit": "^0.11",
"phpunit/phpunit": "^7.0",
"slevomat/coding-standard": "^4.5.2"
},
- "type": "library",
+ "type": "phpstan-extension",
"extra": {
"branch-alias": {
- "dev-master": "0.10-dev"
+ "dev-master": "0.11-dev"
+ },
+ "phpstan": {
+ "includes": [
+ "rules.neon"
+ ]
}
},
"autoload": {
@@ -2621,26 +2884,27 @@
"MIT"
],
"description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
- "time": "2018-06-24T16:51:04+00:00"
+ "time": "2019-05-28T19:54:04+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
- "version": "0.10",
+ "version": "0.11.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
- "reference": "6feecc7faae187daa6be44140cd0f1ba210e6aa0"
+ "reference": "fbf2ad56c3b13189d29655e226c9b1da47c2fad9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6feecc7faae187daa6be44140cd0f1ba210e6aa0",
- "reference": "6feecc7faae187daa6be44140cd0f1ba210e6aa0",
+ "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/fbf2ad56c3b13189d29655e226c9b1da47c2fad9",
+ "reference": "fbf2ad56c3b13189d29655e226c9b1da47c2fad9",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.0",
"php": "~7.1",
- "phpstan/phpstan": "^0.10"
+ "phpstan/phpdoc-parser": "^0.3",
+ "phpstan/phpstan": "^0.11.4"
},
"conflict": {
"phpunit/phpunit": "<7.0"
@@ -2650,15 +2914,21 @@
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
"jakub-onderka/php-parallel-lint": "^1.0",
"phing/phing": "^2.16.0",
- "phpstan/phpstan-strict-rules": "^0.10",
+ "phpstan/phpstan-strict-rules": "^0.11",
"phpunit/phpunit": "^7.0",
"satooshi/php-coveralls": "^1.0",
"slevomat/coding-standard": "^4.5.2"
},
- "type": "library",
+ "type": "phpstan-extension",
"extra": {
"branch-alias": {
- "dev-master": "0.10-dev"
+ "dev-master": "0.11-dev"
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon",
+ "rules.neon"
+ ]
}
},
"autoload": {
@@ -2671,40 +2941,45 @@
"MIT"
],
"description": "PHPUnit extensions and rules for PHPStan",
- "time": "2018-06-22T18:12:17+00:00"
+ "time": "2019-05-17T17:50:16+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
- "version": "0.10",
+ "version": "0.11.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
- "reference": "bffdf03fc70602833936dccf6c2eb3be58ed78d6"
+ "reference": "a203a7afdda073d4ea405a6d9007a5b32de3be61"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/bffdf03fc70602833936dccf6c2eb3be58ed78d6",
- "reference": "bffdf03fc70602833936dccf6c2eb3be58ed78d6",
+ "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/a203a7afdda073d4ea405a6d9007a5b32de3be61",
+ "reference": "a203a7afdda073d4ea405a6d9007a5b32de3be61",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.0",
"php": "~7.1",
- "phpstan/phpstan": "^0.10"
+ "phpstan/phpstan": "^0.11.4"
},
"require-dev": {
"consistence/coding-standard": "^3.0.1",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
"jakub-onderka/php-parallel-lint": "^1.0",
"phing/phing": "^2.16.0",
- "phpstan/phpstan-phpunit": "^0.10",
+ "phpstan/phpstan-phpunit": "^0.11",
"phpunit/phpunit": "^7.0",
"slevomat/coding-standard": "^4.5.2"
},
- "type": "library",
+ "type": "phpstan-extension",
"extra": {
"branch-alias": {
- "dev-master": "0.10-dev"
+ "dev-master": "0.11-dev"
+ },
+ "phpstan": {
+ "includes": [
+ "rules.neon"
+ ]
}
},
"autoload": {
@@ -2717,31 +2992,100 @@
"MIT"
],
"description": "Extra strict and opinionated rules for PHPStan",
- "time": "2018-06-22T18:09:47+00:00"
+ "time": "2019-05-12T16:59:47+00:00"
+ },
+ {
+ "name": "phpstan/phpstan-symfony",
+ "version": "0.11.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpstan-symfony.git",
+ "reference": "c7be3054c21fd472a52b1c38eb129c3f93776084"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/c7be3054c21fd472a52b1c38eb129c3f93776084",
+ "reference": "c7be3054c21fd472a52b1c38eb129c3f93776084",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "nikic/php-parser": "^4.0",
+ "php": "^7.1",
+ "phpstan/phpstan": "^0.11.7"
+ },
+ "conflict": {
+ "symfony/framework-bundle": "<3.0"
+ },
+ "require-dev": {
+ "consistence/coding-standard": "^3.0.1",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
+ "jakub-onderka/php-parallel-lint": "^1.0",
+ "nette/di": "^3.0-stable",
+ "phing/phing": "^2.16.0",
+ "phpstan/phpstan-phpunit": "^0.11",
+ "phpstan/phpstan-strict-rules": "^0.11",
+ "phpunit/phpunit": "^7.0",
+ "slevomat/coding-standard": "^4.5.2",
+ "squizlabs/php_codesniffer": "^3.3.2",
+ "symfony/console": "^3.0 || ^4.0",
+ "symfony/framework-bundle": "^3.0 || ^4.0",
+ "symfony/messenger": "^4.2",
+ "symfony/serializer": "^3.0 || ^4.0"
+ },
+ "type": "phpstan-extension",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.11-dev"
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lukáš Unger",
+ "email": "looky.msc@gmail.com",
+ "homepage": "https://lookyman.net"
+ }
+ ],
+ "description": "Symfony Framework extensions and rules for PHPStan",
+ "time": "2019-05-19T17:40:25+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "6.0.4",
+ "version": "6.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca"
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/52187754b0eed0b8159f62a6fa30073327e8c2ca",
- "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-xmlwriter": "*",
"php": "^7.1",
- "phpunit/php-file-iterator": "^1.4.2",
+ "phpunit/php-file-iterator": "^2.0",
"phpunit/php-text-template": "^1.2.1",
"phpunit/php-token-stream": "^3.0",
"sebastian/code-unit-reverse-lookup": "^1.0.1",
- "sebastian/environment": "^3.1",
+ "sebastian/environment": "^3.1 || ^4.0",
"sebastian/version": "^2.0.1",
"theseer/tokenizer": "^1.1"
},
@@ -2754,7 +3098,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "6.0-dev"
+ "dev-master": "6.1-dev"
}
},
"autoload": {
@@ -2780,29 +3124,32 @@
"testing",
"xunit"
],
- "time": "2018-04-29T14:59:09+00:00"
+ "time": "2018-10-31T16:06:48+00:00"
},
{
"name": "phpunit/php-file-iterator",
- "version": "1.4.5",
+ "version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
+ "reference": "050bedf145a257b1ff02746c31894800e5122946"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
- "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
+ "reference": "050bedf145a257b1ff02746c31894800e5122946",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4.x-dev"
+ "dev-master": "2.0.x-dev"
}
},
"autoload": {
@@ -2817,7 +3164,7 @@
"authors": [
{
"name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
+ "email": "sebastian@phpunit.de",
"role": "lead"
}
],
@@ -2827,7 +3174,7 @@
"filesystem",
"iterator"
],
- "time": "2017-11-27T13:52:08+00:00"
+ "time": "2018-09-13T20:33:42+00:00"
},
{
"name": "phpunit/php-text-template",
@@ -2872,16 +3219,16 @@
},
{
"name": "phpunit/php-timer",
- "version": "2.0.0",
+ "version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f"
+ "reference": "1038454804406b0b5f5f520358e78c1c2f71501e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f",
- "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e",
+ "reference": "1038454804406b0b5f5f520358e78c1c2f71501e",
"shasum": ""
},
"require": {
@@ -2893,7 +3240,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "2.1-dev"
}
},
"autoload": {
@@ -2917,20 +3264,20 @@
"keywords": [
"timer"
],
- "time": "2018-02-01T13:07:23+00:00"
+ "time": "2019-06-07T04:22:29+00:00"
},
{
"name": "phpunit/php-token-stream",
- "version": "3.0.0",
+ "version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace"
+ "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace",
- "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff",
+ "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff",
"shasum": ""
},
"require": {
@@ -2943,7 +3290,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-master": "3.1-dev"
}
},
"autoload": {
@@ -2966,51 +3313,55 @@
"keywords": [
"tokenizer"
],
- "time": "2018-02-01T13:16:43+00:00"
+ "time": "2019-09-17T06:23:10+00:00"
},
{
"name": "phpunit/phpunit",
- "version": "7.1.5",
+ "version": "7.5.16",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "ca64dba53b88aba6af32aebc6b388068db95c435"
+ "reference": "316afa6888d2562e04aeb67ea7f2017a0eb41661"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ca64dba53b88aba6af32aebc6b388068db95c435",
- "reference": "ca64dba53b88aba6af32aebc6b388068db95c435",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/316afa6888d2562e04aeb67ea7f2017a0eb41661",
+ "reference": "316afa6888d2562e04aeb67ea7f2017a0eb41661",
"shasum": ""
},
"require": {
+ "doctrine/instantiator": "^1.1",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
- "myclabs/deep-copy": "^1.6.1",
- "phar-io/manifest": "^1.0.1",
- "phar-io/version": "^1.0",
+ "myclabs/deep-copy": "^1.7",
+ "phar-io/manifest": "^1.0.2",
+ "phar-io/version": "^2.0",
"php": "^7.1",
"phpspec/prophecy": "^1.7",
- "phpunit/php-code-coverage": "^6.0.1",
- "phpunit/php-file-iterator": "^1.4.3",
+ "phpunit/php-code-coverage": "^6.0.7",
+ "phpunit/php-file-iterator": "^2.0.1",
"phpunit/php-text-template": "^1.2.1",
- "phpunit/php-timer": "^2.0",
- "phpunit/phpunit-mock-objects": "^6.1.1",
+ "phpunit/php-timer": "^2.1",
"sebastian/comparator": "^3.0",
"sebastian/diff": "^3.0",
- "sebastian/environment": "^3.1",
+ "sebastian/environment": "^4.0",
"sebastian/exporter": "^3.1",
"sebastian/global-state": "^2.0",
"sebastian/object-enumerator": "^3.0.3",
- "sebastian/resource-operations": "^1.0",
+ "sebastian/resource-operations": "^2.0",
"sebastian/version": "^2.0.1"
},
+ "conflict": {
+ "phpunit/phpunit-mock-objects": "*"
+ },
"require-dev": {
"ext-pdo": "*"
},
"suggest": {
+ "ext-soap": "*",
"ext-xdebug": "*",
"phpunit/php-invoker": "^2.0"
},
@@ -3020,7 +3371,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "7.1-dev"
+ "dev-master": "7.5-dev"
}
},
"autoload": {
@@ -3046,77 +3397,20 @@
"testing",
"xunit"
],
- "time": "2018-04-29T15:09:19+00:00"
- },
- {
- "name": "phpunit/phpunit-mock-objects",
- "version": "6.1.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/70c740bde8fd9ea9ea295be1cd875dd7b267e157",
- "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "^1.0.5",
- "php": "^7.1",
- "phpunit/php-text-template": "^1.2.1",
- "sebastian/exporter": "^3.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^7.0"
- },
- "suggest": {
- "ext-soap": "*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "6.1-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Mock Object library for PHPUnit",
- "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
- "keywords": [
- "mock",
- "xunit"
- ],
- "abandoned": true,
- "time": "2018-04-11T04:50:36+00:00"
+ "time": "2019-09-14T09:08:39+00:00"
},
{
"name": "psr/log",
- "version": "1.0.2",
+ "version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"shasum": ""
},
"require": {
@@ -3150,7 +3444,7 @@
"psr",
"psr-3"
],
- "time": "2016-10-10T12:19:37+00:00"
+ "time": "2018-11-20T15:27:04+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@@ -3199,16 +3493,16 @@
},
{
"name": "sebastian/comparator",
- "version": "3.0.0",
+ "version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "ed5fd2281113729f1ebcc64d101ad66028aeb3d5"
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ed5fd2281113729f1ebcc64d101ad66028aeb3d5",
- "reference": "ed5fd2281113729f1ebcc64d101ad66028aeb3d5",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
"shasum": ""
},
"require": {
@@ -3259,27 +3553,27 @@
"compare",
"equality"
],
- "time": "2018-04-18T13:33:00+00:00"
+ "time": "2018-07-12T15:12:46+00:00"
},
{
"name": "sebastian/diff",
- "version": "3.0.0",
+ "version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8"
+ "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/e09160918c66281713f1c324c1f4c4c3037ba1e8",
- "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
+ "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"require-dev": {
- "phpunit/phpunit": "^7.0",
+ "phpunit/phpunit": "^7.5 || ^8.0",
"symfony/process": "^2 || ^3.3 || ^4"
},
"type": "library",
@@ -3315,32 +3609,35 @@
"unidiff",
"unified diff"
],
- "time": "2018-02-01T13:45:15+00:00"
+ "time": "2019-02-04T06:01:07+00:00"
},
{
"name": "sebastian/environment",
- "version": "3.1.0",
+ "version": "4.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5"
+ "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
- "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
+ "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
"shasum": ""
},
"require": {
- "php": "^7.0"
+ "php": "^7.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.1"
+ "phpunit/phpunit": "^7.5"
+ },
+ "suggest": {
+ "ext-posix": "*"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.1.x-dev"
+ "dev-master": "4.2-dev"
}
},
"autoload": {
@@ -3365,20 +3662,20 @@
"environment",
"hhvm"
],
- "time": "2017-07-01T08:51:00+00:00"
+ "time": "2019-05-05T09:05:15+00:00"
},
{
"name": "sebastian/exporter",
- "version": "3.1.0",
+ "version": "3.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "234199f4528de6d12aaa58b612e98f7d36adb937"
+ "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937",
- "reference": "234199f4528de6d12aaa58b612e98f7d36adb937",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e",
+ "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e",
"shasum": ""
},
"require": {
@@ -3405,6 +3702,10 @@
"BSD-3-Clause"
],
"authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
@@ -3413,17 +3714,13 @@
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@2bepublished.at"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
@@ -3432,7 +3729,7 @@
"export",
"exporter"
],
- "time": "2017-04-03T13:19:02+00:00"
+ "time": "2019-09-14T09:02:43+00:00"
},
{
"name": "sebastian/global-state",
@@ -3632,25 +3929,25 @@
},
{
"name": "sebastian/resource-operations",
- "version": "1.0.0",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
- "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
- "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
"shasum": ""
},
"require": {
- "php": ">=5.6.0"
+ "php": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "2.0-dev"
}
},
"autoload": {
@@ -3670,7 +3967,7 @@
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
- "time": "2015-07-28T20:34:47+00:00"
+ "time": "2018-10-04T04:07:39+00:00"
},
{
"name": "sebastian/version",
@@ -3717,30 +4014,30 @@
},
{
"name": "slevomat/coding-standard",
- "version": "5.0.2",
+ "version": "5.0.4",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
- "reference": "223f02b6193fe47b7b483bfa5bf75693535482dd"
+ "reference": "287ac3347c47918c0bf5e10335e36197ea10894c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/223f02b6193fe47b7b483bfa5bf75693535482dd",
- "reference": "223f02b6193fe47b7b483bfa5bf75693535482dd",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/287ac3347c47918c0bf5e10335e36197ea10894c",
+ "reference": "287ac3347c47918c0bf5e10335e36197ea10894c",
"shasum": ""
},
"require": {
"php": "^7.1",
"phpstan/phpdoc-parser": "^0.3.1",
- "squizlabs/php_codesniffer": "^3.4.0"
+ "squizlabs/php_codesniffer": "^3.4.1"
},
"require-dev": {
"jakub-onderka/php-parallel-lint": "1.0.0",
"phing/phing": "2.16.1",
- "phpstan/phpstan": "0.11.1",
+ "phpstan/phpstan": "0.11.4",
"phpstan/phpstan-phpunit": "0.11",
"phpstan/phpstan-strict-rules": "0.11",
- "phpunit/phpunit": "8.0.0"
+ "phpunit/phpunit": "8.0.5"
},
"type": "phpcodesniffer-standard",
"autoload": {
@@ -3753,20 +4050,20 @@
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
- "time": "2019-03-12T20:26:36+00:00"
+ "time": "2019-03-22T19:10:53+00:00"
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.4.0",
+ "version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "379deb987e26c7cd103a7b387aea178baec96e48"
+ "reference": "0afebf16a2e7f1e434920fa976253576151effe9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/379deb987e26c7cd103a7b387aea178baec96e48",
- "reference": "379deb987e26c7cd103a7b387aea178baec96e48",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/0afebf16a2e7f1e434920fa976253576151effe9",
+ "reference": "0afebf16a2e7f1e434920fa976253576151effe9",
"shasum": ""
},
"require": {
@@ -3799,25 +4096,25 @@
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
- "homepage": "http://www.squizlabs.com/php-codesniffer",
+ "homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
- "time": "2018-12-19T23:57:18+00:00"
+ "time": "2019-09-26T23:12:26+00:00"
},
{
"name": "symfony/finder",
- "version": "v4.1.0",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "087e2ee0d74464a4c6baac4e90417db7477dc238"
+ "reference": "5e575faa95548d0586f6bedaeabec259714e44d1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/087e2ee0d74464a4c6baac4e90417db7477dc238",
- "reference": "087e2ee0d74464a4c6baac4e90417db7477dc238",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1",
+ "reference": "5e575faa95548d0586f6bedaeabec259714e44d1",
"shasum": ""
},
"require": {
@@ -3826,7 +4123,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.1-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -3853,20 +4150,78 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2018-05-16T14:33:22+00:00"
+ "time": "2019-09-16T11:29:48+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.12-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "time": "2019-08-06T08:03:45+00:00"
},
{
"name": "symfony/process",
- "version": "v4.0.9",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25"
+ "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25",
- "reference": "d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25",
+ "url": "https://api.github.com/repos/symfony/process/zipball/50556892f3cc47d4200bfd1075314139c4c9ff4b",
+ "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b",
"shasum": ""
},
"require": {
@@ -3875,7 +4230,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -3902,24 +4257,25 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2018-04-03T05:24:00+00:00"
+ "time": "2019-09-26T21:17:10+00:00"
},
{
"name": "symfony/yaml",
- "version": "v4.0.9",
+ "version": "v4.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "275ad099e4cbe612a2acbca14a16dd1c5311324d"
+ "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/275ad099e4cbe612a2acbca14a16dd1c5311324d",
- "reference": "275ad099e4cbe612a2acbca14a16dd1c5311324d",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/41e16350a2a1c7383c4735aa2f9fce74cf3d1178",
+ "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178",
"shasum": ""
},
"require": {
- "php": "^7.1.3"
+ "php": "^7.1.3",
+ "symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"symfony/console": "<3.4"
@@ -3933,7 +4289,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-master": "4.3-dev"
}
},
"autoload": {
@@ -3960,20 +4316,20 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2018-04-08T08:49:08+00:00"
+ "time": "2019-09-11T15:41:19+00:00"
},
{
"name": "theseer/tokenizer",
- "version": "1.1.0",
+ "version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b"
+ "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b",
- "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
+ "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
"shasum": ""
},
"require": {
@@ -4000,28 +4356,28 @@
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
- "time": "2017-04-07T12:08:54+00:00"
+ "time": "2019-06-13T22:48:21+00:00"
},
{
"name": "webmozart/assert",
- "version": "1.3.0",
+ "version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
- "reference": "0df1908962e7a3071564e857d86874dad1ef204a"
+ "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
- "reference": "0df1908962e7a3071564e857d86874dad1ef204a",
+ "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4",
+ "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4",
"shasum": ""
},
"require": {
- "php": "^5.3.3 || ^7.0"
+ "php": "^5.3.3 || ^7.0",
+ "symfony/polyfill-ctype": "^1.8"
},
"require-dev": {
- "phpunit/phpunit": "^4.6",
- "sebastian/version": "^1.0.1"
+ "phpunit/phpunit": "^4.8.36 || ^7.5.13"
},
"type": "library",
"extra": {
@@ -4050,7 +4406,7 @@
"check",
"validate"
],
- "time": "2018-01-29T19:49:41+00:00"
+ "time": "2019-08-24T08:43:50+00:00"
}
],
"aliases": [],
diff --git a/docs/en/reference/configuration.rst b/docs/en/reference/configuration.rst
index 4f5ee758c6..34cdd5f98f 100644
--- a/docs/en/reference/configuration.rst
+++ b/docs/en/reference/configuration.rst
@@ -25,12 +25,20 @@ Now, in the root of your project place a file named ``migrations.php``, ``migrat
return [
'name' => 'My Project Migrations',
- 'migrations_namespace' => 'MyProject\Migrations',
- 'table_name' => 'doctrine_migration_versions',
- 'column_name' => 'version',
- 'column_length' => 14,
- 'executed_at_column_name' => 'executed_at',
- 'migrations_directory' => '/data/doctrine/migrations-docs-example/lib/MyProject/Migrations',
+
+ 'table_storage' => [
+ 'table_name' => 'doctrine_migration_versions',
+ 'version_column_name' => 'version',
+ 'version_column_length' => 1024,
+ 'executed_at_column_name' => 'executed_at',
+ 'execution_time_column_name' => 'execution_time',
+ ],
+
+ 'migrations_paths' => [
+ 'MyProject\Migrations' => '/data/doctrine/migrations/lib/MyProject/Migrations',
+ 'MyProject\Component\Migrations' => './Component/MyProject/Migrations',
+ ],
+
'all_or_nothing' => true,
'check_database_platform' => true,
];
@@ -38,30 +46,44 @@ Now, in the root of your project place a file named ``migrations.php``, ``migrat
.. code-block:: yaml
name: "My Project Migrations"
- migrations_namespace: "MyProject\Migrations"
- table_name: "doctrine_migration_versions"
- column_name: "version"
- column_length: 14
- executed_at_column_name: "executed_at"
- migrations_directory: "/data/doctrine/migrations-docs-example/lib/MyProject/Migrations"
+
+ table_storage:
+ table_name: doctrine_migration_versions
+ version_column_name: version
+ version_column_length: 1024
+ executed_at_column_name: executed_at
+ execution_time_column_name: execution_time
+
+ migrations_paths:
+ 'MyProject\Migrations': /data/doctrine/migrations/lib/MyProject/Migrations
+ 'MyProject\Component\Migrations': ./Component/MyProject/Migrations
+
all_or_nothing: true
check_database_platform: true
.. code-block:: xml
-
+ xsi:schemaLocation="http://doctrine-project.org/schemas/migrations/configuration/3.0
+ http://doctrine-project.org/schemas/migrations/configuration-3.0.xsd">
My Project Migrations
- MyProject\Migrations
-
-
-
- /data/doctrine/migrations-docs-example/lib/MyProject/Migrations
+
+
+
+
+ /data/doctrine/migrations/lib/MyProject/Migrations
+ ./Component/MyProject/Migrations
+
true
@@ -72,12 +94,21 @@ Now, in the root of your project place a file named ``migrations.php``, ``migrat
{
"name": "My Project Migrations",
- "migrations_namespace": "MyProject\Migrations",
- "table_name": "doctrine_migration_versions",
- "column_name": "version",
- "column_length": 14,
- "executed_at_column_name": "executed_at",
- "migrations_directory": "/data/doctrine/migrations-docs-example/lib/MyProject/Migrations",
+ "name": "My Project Migrations",
+
+ "table_storage": {
+ "table_name: "doctrine_migration_versions",
+ "version_column_name": "version",
+ "version_column_length": 1024,
+ "executed_at_column_name": "executed_at",
+ "execution_time_column_name": "execution_time"
+ },
+
+ "migrations_paths": {
+ "MyProject\Migrations": "/data/doctrine/migrations/lib/MyProject/Migrations",
+ "MyProject\Component\Migrations": "./Component/MyProject/Migrations"
+ },
+
"all_or_nothing": true,
"check_database_platform": true
}
@@ -95,23 +126,31 @@ Here are details about what each configuration option does:
+============================+============+==============================+==================================================================================+
| name | no | Doctrine Database Migrations | The name that shows at the top of the migrations console application. |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| migrations_namespace | yes | null | The PHP namespace your migration classes are located under. |
+| migrations_paths | yes | null | The PHP namespace your migration classes are located under and the path to a directory where to look for migration classes. |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| table_name | no | doctrine_migration_versions | The name of the table to track executed migrations in. |
+| table_storage | no | | Used by doctrine migrations to track the currently executed migrations |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| column_name | no | version | The name of the column which stores the version name. |
+| all_or_nothing | no | false | Whether or not to wrap multiple migrations in a single transaction. |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| column_length | no | 14 | The length of the column which stores the version name. |
+| migrations | no | [] | Manually specify the array of migration versions instead of finding migrations. |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| executed_at_column_name | no | executed_at | The name of the column which stores the date that a migration was executed. |
+| check_database_platform | no | true | Whether to add a database platform check at the beginning of the generated code. |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| migrations_directory | yes | null | The path to a directory where to look for migration classes. |
+
+
+Here the possible options for ``table_storage``:
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| all_or_nothing | no | false | Whether or not to wrap multiple migrations in a single transaction. |
+| Name | Required | Default | Description |
++============================+============+==============================+==================================================================================+
+| table_name | no | doctrine_migration_versions | The name of the table to track executed migrations in. |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| migrations | no | [] | Manually specify the array of migration versions instead of finding migrations. |
+| version_column_name | no | version | The name of the column which stores the version name. |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
-| check_database_platform | no | true | Whether to add a database platform check at the beginning of the generated code. |
+| version_column_length | no | 1024 | The length of the column which stores the version name. |
++----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
+| executed_at_column_name | no | executed_at | The name of the column which stores the date that a migration was executed. |
++----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
+| execution_time_column_name | no | executed_at | The name of the column which stores how long a migration took (milliseconds). |
+----------------------------+------------+------------------------------+----------------------------------------------------------------------------------+
Manually Providing Migrations
@@ -130,10 +169,7 @@ classes using the ``migrations`` configuration setting:
// ..
'migrations' => [
- 'migration1' => [
- 'version' => '1',
- 'class' => 'MyProject\Migrations\NewMigration',
- ],
+ 'MyProject\Migrations\NewMigration',
],
];
@@ -142,9 +178,7 @@ classes using the ``migrations`` configuration setting:
// ...
migrations:
- migration1:
- version: "1"
- class: "MyProject\Migrations\NewMigration"
+ - "MyProject\Migrations\NewMigration"
.. code-block:: xml
@@ -157,7 +191,7 @@ classes using the ``migrations`` configuration setting:
// ...
-
+
@@ -166,13 +200,9 @@ classes using the ``migrations`` configuration setting:
{
// ...
- "migrations": {
- "migration1": {
- "version": 1,
- "class": "DoctrineMigrations\NewMigration"
- }
- }
- }
+ "migrations": [
+ "DoctrineMigrations\NewMigration"
+ ]
}
All or Nothing Transaction
diff --git a/docs/en/reference/custom-configuration.rst b/docs/en/reference/custom-configuration.rst
index bdb9caf2a0..069854b4d9 100644
--- a/docs/en/reference/custom-configuration.rst
+++ b/docs/en/reference/custom-configuration.rst
@@ -16,6 +16,7 @@ Once you have your custom integration setup, you can modify it to look like the
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
use Doctrine\Migrations\Configuration\Configuration;
+ une Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\Tools\Console\Command;
use Doctrine\Migrations\Tools\Console\Helper\ConfigurationHelper;
use Symfony\Component\Console\Application;
@@ -33,16 +34,17 @@ Once you have your custom integration setup, you can modify it to look like the
$connection = DriverManager::getConnection($dbParams);
$configuration = new Configuration($connection);
+
$configuration->setName('My Project Migrations');
- $configuration->setMigrationsNamespace('MyProject\Migrations');
- $configuration->setMigrationsTableName('doctrine_migration_versions');
- $configuration->setMigrationsColumnName('version');
- $configuration->setMigrationsColumnLength(255);
- $configuration->setMigrationsExecutedAtColumnName('executed_at');
- $configuration->setMigrationsDirectory('/data/doctrine/migrations-docs-example/lib/MyProject/Migrations');
+ $configuration->addMigrationsDirectory('MyProject\Migrations', '/data/doctrine/migrations-docs-example/lib/MyProject/Migrations');
$configuration->setAllOrNothing(true);
$configuration->setCheckDatabasePlatform(false);
+ $storageConfiguration = new TableMetadataStorageConfiguration();
+ $storageConfiguration->setTableName('doctrine_migration_versions');
+
+ $configuration->setMetadataStorageConfiguration($storageConfiguration);
+
$helperSet = new HelperSet();
$helperSet->set(new QuestionHelper(), 'question');
$helperSet->set(new ConnectionHelper($connection), 'db');
diff --git a/docs/en/reference/generating-migrations.rst b/docs/en/reference/generating-migrations.rst
index e6cf799078..0066eab0e6 100644
--- a/docs/en/reference/generating-migrations.rst
+++ b/docs/en/reference/generating-migrations.rst
@@ -66,9 +66,9 @@ Now when you run the ``diff`` command it will generate a migration which will cr
$ ./vendor/bin/doctrine-migrations diff
Generated new migration class to "/data/doctrine/migrations-docs-example/lib/MyProject/Migrations/Version20180601215504.php"
- To run just this migration for testing purposes, you can use migrations:execute --up 20180601215504
+ To run just this migration for testing purposes, you can use migrations:execute --up 'MyProject\Migrations\Version20180601215504'
- To revert the migration you can use migrations:execute --down 20180601215504
+ To revert the migration you can use migrations:execute --down 'MyProject\Migrations\Version20180601215504'
Take a look at the generated migration:
@@ -129,9 +129,9 @@ Now you are ready to execute your diff migration:
WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)y
- Migrating up to 20180601215504 from 20180601193057
+ Migrating up to MyProject\Migrations\Version20180601215504 from MyProject\Migrations\Version20180601193057
- ++ migrating 20180601215504
+ ++ migrating MyProject\Migrations\Version20180601215504
-> CREATE TABLE users (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
-> DROP TABLE example_table
diff --git a/docs/en/reference/managing-migrations.rst b/docs/en/reference/managing-migrations.rst
index bcaecab21b..2185d5baf4 100644
--- a/docs/en/reference/managing-migrations.rst
+++ b/docs/en/reference/managing-migrations.rst
@@ -27,8 +27,8 @@ that the new migration is registered and ready to be executed:
>> Migrations Directory: /data/doctrine/migrations-docs-example/lib/MyProject/Migrations
>> Previous Version: Already at first version
>> Current Version: 0
- >> Next Version: 2018-06-01 19:30:57 (20180601193057)
- >> Latest Version: 2018-06-01 19:30:57 (20180601193057)
+ >> Next Version: 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057)
+ >> Latest Version: 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057)
>> Executed Migrations: 0
>> Executed Unavailable Migrations: 0
>> Available Migrations: 1
@@ -36,7 +36,7 @@ that the new migration is registered and ready to be executed:
== Available Migration Versions
- >> 2018-06-01 19:30:57 (20180601193057) not migrated This is my example migration.
+ >> 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057) not migrated This is my example migration.
As you can see we have a new migration version available and it is ready to be executed. The problem
is, it does not have anything in it so nothing would be executed! Let's add some code to it and add a new table:
@@ -85,9 +85,9 @@ Now we are ready to give it a test! First lets just do a dry-run to make sure it
My Project Migrations
- Executing dry run of migration up to 20180601193057 from 0
+ Executing dry run of migration up to MyProject\Migrations\Version20180601193057 from 0
- ++ migrating 20180601193057
+ ++ migrating MyProject\Migrations\Version20180601193057
-> CREATE TABLE example_table (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))
@@ -118,9 +118,9 @@ Everything looks good so we can remove the ``--dry-run`` option and actually exe
WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)y
- Migrating up to 20180601193057 from 0
+ Migrating up to MyProject\Migrations\Version20180601193057 from 0
- ++ migrating 20180601193057
+ ++ migrating MyProject\Migrations\Version20180601193057
-> CREATE TABLE example_table (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))
@@ -140,10 +140,10 @@ You may want to just execute a single migration up or down. You can do this with
.. code-block:: sh
- $ ./vendor/bin/doctrine-migrations execute 20180601193057 --down
+ $ ./vendor/bin/doctrine-migrations execute MyProject\Migrations\Version20180601193057 --down
WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)y
- ++ migrating 20180601193057
+ ++ migrating MyProject\Migrations\Version20180601193057
-> DROP TABLE example_table
@@ -162,9 +162,9 @@ execute the migrations without any extra prompting from Doctrine.
My Project Migrations
- Migrating up to 20180601193057 from 0
+ Migrating up to MyProject\Migrations\Version20180601193057 from 0
- ++ migrating 20180601193057
+ ++ migrating MyProject\Migrations\Version20180601193057
-> CREATE TABLE example_table (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))
@@ -195,9 +195,9 @@ By checking the status again after using either method you will see everything i
>> Migrations Namespace: MyProject\Migrations
>> Migrations Directory: /data/doctrine/migrations-docs-example/lib/MyProject/Migrations
>> Previous Version: 0
- >> Current Version: 2018-06-01 19:30:57 (20180601193057)
+ >> Current Version: 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057)
>> Next Version: Already at latest version
- >> Latest Version: 2018-06-01 19:30:57 (20180601193057)
+ >> Latest Version: 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057)
>> Executed Migrations: 1
>> Executed Unavailable Migrations: 0
>> Available Migrations: 1
@@ -205,7 +205,7 @@ By checking the status again after using either method you will see everything i
== Available Migration Versions
- >> 2018-06-01 19:30:57 (20180601193057) migrated (executed at 2018-06-01 17:08:44) This is my example migration.
+ >> 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057) migrated (executed at 2018-06-01 17:08:44) This is my example migration.
Reverting Migrations
--------------------
@@ -222,9 +222,9 @@ it will migrate down. To rollback to the the first version you can use the ``fir
WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)y
- Migrating down to 0 from 20180601193057
+ Migrating down to 0 from MyProject\Migrations\Version20180601193057
- -- reverting 20180601193057
+ -- reverting MyProject\Migrations\Version20180601193057
-> DROP TABLE example_table
@@ -256,8 +256,8 @@ Now if you run the ``status`` command again, you will see that the database is b
>> Migrations Directory: /data/doctrine/migrations-docs-example/lib/MyProject/Migrations
>> Previous Version: Already at first version
>> Current Version: 0
- >> Next Version: 2018-06-01 19:30:57 (20180601193057)
- >> Latest Version: 2018-06-01 19:30:57 (20180601193057)
+ >> Next Version: 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057)
+ >> Latest Version: 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057)
>> Executed Migrations: 0
>> Executed Unavailable Migrations: 0
>> Available Migrations: 1
@@ -265,7 +265,7 @@ Now if you run the ``status`` command again, you will see that the database is b
== Available Migration Versions
- >> 2018-06-01 19:30:57 (20180601193057) not migrated This is my example migration.
+ >> 2018-06-01 19:30:57 (MyProject\Migrations\Version20180601193057) not migrated This is my example migration.
Version Aliases
---------------
@@ -298,9 +298,9 @@ statement to a file. This is possible by using the ``--write-sql`` option:
My Project Migrations
- Executing dry run of migration up to 20180601193057 from 0
+ Executing dry run of migration up to MyProject\Migrations\Version20180601193057 from 0
- ++ migrating 20180601193057
+ ++ migrating MyProject\Migrations\Version20180601193057
-> CREATE TABLE example_table (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))
@@ -312,7 +312,7 @@ statement to a file. This is possible by using the ``--write-sql`` option:
++ used 8M memory
++ 1 migrations executed
++ 1 sql queries
- -- Migrating from 0 to 20180601193057
+ -- Migrating from 0 to MyProject\Migrations\Version20180601193057
Writing migration file to "/data/doctrine/migrations-docs-example/doctrine_migration_20180601172528.sql"
@@ -325,9 +325,9 @@ executed SQL outputted in a nice format:
$ cat doctrine_migration_20180601172528.sql
-- Doctrine Migration File Generated on 2018-06-01 17:25:28
- -- Version 20180601193057
+ -- Version MyProject\Migrations\Version20180601193057
CREATE TABLE example_table (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id));
- INSERT INTO doctrine_migration_versions (version, executed_at) VALUES ('20180601193057', CURRENT_TIMESTAMP);
+ INSERT INTO doctrine_migration_versions (version, executed_at) VALUES ('MyProject\Migrations\Version20180601193057', CURRENT_TIMESTAMP);
The ``--write-sql`` option also accepts an optional value for where to write the sql file. It can be a relative path
to a file that will write to the current working directory:
@@ -360,13 +360,13 @@ Sometimes you may need to manually mark a migration as migrated or not. You can
.. code-block:: sh
- $ ./vendor/bin/doctrine-migrations version 20180601193057 --add
+ $ ./vendor/bin/doctrine-migrations version 'MyProject\Migrations\Version20180601193057' --add
Or you can delete that version:
.. code-block:: sh
- $ ./vendor/bin/doctrine-migrations version 20180601193057 --delete
+ $ ./vendor/bin/doctrine-migrations version 'MyProject\Migrations\Version20180601193057' --delete
This command does not actually execute any migrations, it just adds or deletes the version from the version table where
we track whether or not a migration version has been executed or not.
diff --git a/docs/en/reference/migration-classes.rst b/docs/en/reference/migration-classes.rst
index ff4e7a3426..5db22470c8 100644
--- a/docs/en/reference/migration-classes.rst
+++ b/docs/en/reference/migration-classes.rst
@@ -9,9 +9,9 @@ and ``down`` methods. You can easily generate a blank migration to modify with t
$ ./vendor/bin/doctrine-migrations generate
Generated new migration class to "/data/doctrine/migrations-docs-example/lib/MyProject/Migrations/Version20180601193057.php"
- To run just this migration for testing purposes, you can use migrations:execute --up 20180601193057
+ To run just this migration for testing purposes, you can use migrations:execute --up 'MyProject\Migrations\Version20180601193057'
- To revert the migration you can use migrations:execute --down 20180601193057
+ To revert the migration you can use migrations:execute --down 'MyProject\Migrations\Version20180601193057'
The above command will generate a PHP class with the path to it visible like above. Here is what the blank
migration looks like:
diff --git a/lib/Doctrine/Migrations/AbstractMigration.php b/lib/Doctrine/Migrations/AbstractMigration.php
index a684780143..a6c5e61170 100644
--- a/lib/Doctrine/Migrations/AbstractMigration.php
+++ b/lib/Doctrine/Migrations/AbstractMigration.php
@@ -11,7 +11,8 @@
use Doctrine\Migrations\Exception\AbortMigration;
use Doctrine\Migrations\Exception\IrreversibleMigration;
use Doctrine\Migrations\Exception\SkipMigration;
-use Doctrine\Migrations\Version\Version;
+use Psr\Log\LoggerInterface;
+use function func_get_args;
use function sprintf;
/**
@@ -20,9 +21,6 @@
*/
abstract class AbstractMigration
{
- /** @var Version */
- protected $version;
-
/** @var Connection */
protected $connection;
@@ -32,18 +30,18 @@ abstract class AbstractMigration
/** @var AbstractPlatform */
protected $platform;
- /** @var OutputWriter */
- private $outputWriter;
+ /** @var LoggerInterface */
+ private $logger;
- public function __construct(Version $version)
- {
- $config = $version->getConfiguration();
+ /** @var mixed[] */
+ private $plannedSql = [];
- $this->version = $version;
- $this->connection = $config->getConnection();
- $this->sm = $this->connection->getSchemaManager();
- $this->platform = $this->connection->getDatabasePlatform();
- $this->outputWriter = $config->getOutputWriter();
+ public function __construct(Connection $connection, LoggerInterface $logger)
+ {
+ $this->connection = $connection;
+ $this->sm = $this->connection->getSchemaManager();
+ $this->platform = $this->connection->getDatabasePlatform();
+ $this->logger = $logger;
}
/**
@@ -73,11 +71,7 @@ public function warnIf(bool $condition, string $message = '') : void
$message = $message ?: 'Unknown Reason';
- $this->outputWriter->write(sprintf(
- ' Warning during %s: %s',
- $this->version->getExecutionState(),
- $message
- ));
+ $this->logger->warning($message, ['migration' => $this]);
}
/**
@@ -118,7 +112,10 @@ public function postDown(Schema $schema) : void
abstract public function up(Schema $schema) : void;
- abstract public function down(Schema $schema) : void;
+ public function down(Schema $schema) : void
+ {
+ $this->abortIf(true, sprintf('No down() migration provided for "%s"', static::class));
+ }
/**
* @param mixed[] $params
@@ -129,12 +126,20 @@ protected function addSql(
array $params = [],
array $types = []
) : void {
- $this->version->addSql($sql, $params, $types);
+ $this->plannedSql[] = func_get_args();
+ }
+
+ /**
+ * @return mixed[]
+ */
+ public function getSql() : array
+ {
+ return $this->plannedSql;
}
protected function write(string $message) : void
{
- $this->outputWriter->write($message);
+ $this->logger->notice($message, ['migration' => $this]);
}
protected function throwIrreversibleMigrationException(?string $message = null) : void
diff --git a/lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php b/lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php
deleted file mode 100644
index 554de779e9..0000000000
--- a/lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php
+++ /dev/null
@@ -1,152 +0,0 @@
- 'setMigrationsNamespace',
- 'table_name' => 'setMigrationsTableName',
- 'column_name' => 'setMigrationsColumnName',
- 'column_length' => 'setMigrationsColumnLength',
- 'executed_at_column_name' => 'setMigrationsExecutedAtColumnName',
- 'organize_migrations' => 'setMigrationOrganization',
- 'name' => 'setName',
- 'migrations_directory' => 'loadMigrationsFromDirectory',
- 'migrations' => 'loadMigrations',
- 'custom_template' => 'setCustomTemplate',
- 'all_or_nothing' => 'setAllOrNothing',
- 'check_database_platform' => 'setCheckDatabasePlatform',
- ];
-
- /** @var string */
- private $file;
-
- /** @var bool */
- private $loaded = false;
-
- /**
- * @throws FileNotFound
- */
- public function load(string $file) : void
- {
- if ($this->loaded) {
- throw FileAlreadyLoaded::new();
- }
-
- $path = getcwd() . '/' . $file;
-
- if (file_exists($path)) {
- $file = $path;
- }
-
- $this->file = $file;
-
- if (! file_exists($file)) {
- throw FileNotFound::new();
- }
-
- $this->doLoad($file);
- $this->loaded = true;
- }
-
- public function getFile() : string
- {
- return $this->file;
- }
-
- /**
- * @param mixed[] $config
- */
- protected function setConfiguration(array $config) : void
- {
- foreach ($config as $configurationKey => $configurationValue) {
- if (! in_array($configurationKey, self::ALLOWED_CONFIGURATION_KEYS, true)) {
- throw InvalidConfigurationKey::new($configurationKey);
- }
- }
-
- foreach (self::CONFIGURATION_METHOD_MAP as $key => $method) {
- if (! isset($config[$key])) {
- continue;
- }
-
- $this->$method($config[$key]);
- }
- }
-
- protected function getDirectoryRelativeToFile(string $file, string $input) : string
- {
- $path = realpath(dirname($file) . '/' . $input);
-
- return $path !== false ? $path : $input;
- }
-
- /**
- * Abstract method that each file configuration driver must implement to
- * load the given configuration file whether it be xml, yaml, etc. or something
- * else.
- */
- abstract protected function doLoad(string $file) : void;
-
- private function loadMigrationsFromDirectory(string $migrationsDirectory) : void
- {
- $this->setMigrationsDirectory($migrationsDirectory);
- $this->registerMigrationsFromDirectory($migrationsDirectory);
- }
-
- /** @param string[][] $migrations */
- private function loadMigrations(array $migrations) : void
- {
- foreach ($migrations as $migration) {
- $this->registerMigration(
- $migration['version'],
- $migration['class']
- );
- }
- }
-
- private function setMigrationOrganization(string $migrationOrganization) : void
- {
- if (strcasecmp($migrationOrganization, self::VERSIONS_ORGANIZATION_BY_YEAR) === 0) {
- $this->setMigrationsAreOrganizedByYear();
- } elseif (strcasecmp($migrationOrganization, self::VERSIONS_ORGANIZATION_BY_YEAR_AND_MONTH) === 0) {
- $this->setMigrationsAreOrganizedByYearAndMonth();
- } else {
- throw UnknownConfigurationValue::new('organize_migrations', $migrationOrganization);
- }
- }
-}
diff --git a/lib/Doctrine/Migrations/Configuration/ArrayConfiguration.php b/lib/Doctrine/Migrations/Configuration/ArrayConfiguration.php
deleted file mode 100644
index 95a2cbf15f..0000000000
--- a/lib/Doctrine/Migrations/Configuration/ArrayConfiguration.php
+++ /dev/null
@@ -1,28 +0,0 @@
-getDirectoryRelativeToFile(
- $file,
- $config['migrations_directory']
- );
- }
-
- $this->setConfiguration($config);
- }
-}
diff --git a/lib/Doctrine/Migrations/Configuration/Configuration.php b/lib/Doctrine/Migrations/Configuration/Configuration.php
index d9f40008a6..59a5f42c7b 100644
--- a/lib/Doctrine/Migrations/Configuration/Configuration.php
+++ b/lib/Doctrine/Migrations/Configuration/Configuration.php
@@ -4,56 +4,29 @@
namespace Doctrine\Migrations\Configuration;
-use DateTimeImmutable;
-use DateTimeInterface;
-use DateTimeZone;
-use Doctrine\Common\EventArgs;
-use Doctrine\DBAL\Connection;
-use Doctrine\DBAL\Connections\MasterSlaveConnection;
-use Doctrine\Migrations\Configuration\Exception\MigrationsNamespaceRequired;
-use Doctrine\Migrations\Configuration\Exception\ParameterIncompatibleWithFinder;
-use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Configuration\Exception\MissingNamespaceConfiguration;
+use Doctrine\Migrations\Configuration\Exception\UnknownConfigurationValue;
use Doctrine\Migrations\Exception\MigrationException;
-use Doctrine\Migrations\Exception\MigrationsDirectoryRequired;
-use Doctrine\Migrations\Finder\MigrationDeepFinder;
-use Doctrine\Migrations\Finder\MigrationFinder;
-use Doctrine\Migrations\OutputWriter;
-use Doctrine\Migrations\QueryWriter;
-use Doctrine\Migrations\Version\Version;
-use function str_replace;
-use function strlen;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorageConfigration;
+use function count;
+use function strcasecmp;
/**
* The Configuration class is responsible for defining migration configuration information.
*/
-class Configuration
+final class Configuration
{
- public const VERSIONS_ORGANIZATION_BY_YEAR = 'year';
-
+ public const VERSIONS_ORGANIZATION_BY_YEAR = 'year';
public const VERSIONS_ORGANIZATION_BY_YEAR_AND_MONTH = 'year_and_month';
- public const VERSION_FORMAT = 'YmdHis';
-
/** @var string|null */
private $name;
- /** @var string */
- private $migrationsTableName = 'doctrine_migration_versions';
-
- /** @var string */
- private $migrationsColumnName = 'version';
-
- /** @var int */
- private $migrationsColumnLength;
-
- /** @var string */
- private $migrationsExecutedAtColumnName = 'executed_at';
-
- /** @var string|null */
- private $migrationsDirectory;
+ /** @var array */
+ private $migrationsDirectories = [];
- /** @var string|null */
- private $migrationsNamespace;
+ /** @var string[] */
+ private $migrationClasses = [];
/** @var bool */
private $migrationsAreOrganizedByYear = false;
@@ -70,128 +43,56 @@ class Configuration
/** @var bool */
private $allOrNothing = false;
- /** @var Connection */
- private $connection;
-
- /** @var OutputWriter|null */
- private $outputWriter;
-
- /** @var MigrationFinder|null */
- private $migrationFinder;
-
- /** @var QueryWriter|null */
- private $queryWriter;
-
- /** @var DependencyFactory|null */
- private $dependencyFactory;
-
/** @var bool */
private $checkDbPlatform = true;
- public function __construct(
- Connection $connection,
- ?OutputWriter $outputWriter = null,
- ?MigrationFinder $migrationFinder = null,
- ?QueryWriter $queryWriter = null,
- ?DependencyFactory $dependencyFactory = null
- ) {
- $this->connection = $connection;
- $this->outputWriter = $outputWriter;
- $this->migrationFinder = $migrationFinder;
- $this->queryWriter = $queryWriter;
- $this->dependencyFactory = $dependencyFactory;
- $this->migrationsColumnLength = strlen($this->createDateTime()->format(self::VERSION_FORMAT));
- }
-
- public function setName(string $name) : void
- {
- $this->name = $name;
- }
-
- public function getName() : ?string
- {
- return $this->name;
- }
-
- public function getConnection() : Connection
- {
- return $this->connection;
- }
-
- public function setMigrationsTableName(string $tableName) : void
- {
- $this->migrationsTableName = $tableName;
- }
-
- public function getMigrationsTableName() : string
- {
- return $this->migrationsTableName;
- }
-
- public function setMigrationsColumnName(string $columnName) : void
- {
- $this->migrationsColumnName = $columnName;
- }
-
- public function getMigrationsColumnName() : string
- {
- return $this->migrationsColumnName;
- }
-
- public function getQuotedMigrationsColumnName() : string
- {
- return $this->getDependencyFactory()
- ->getTrackingTableDefinition()
- ->getMigrationsColumn()
- ->getQuotedName($this->connection->getDatabasePlatform());
- }
-
- public function setMigrationsColumnLength(int $columnLength) : void
- {
- $this->migrationsColumnLength = $columnLength;
- }
+ /** @var MetadataStorageConfigration */
+ private $metadataStorageConfiguration;
- public function getMigrationsColumnLength() : int
+ public function setMetadataStorageConfiguration(MetadataStorageConfigration $metadataStorageConfiguration) : void
{
- return $this->migrationsColumnLength;
+ $this->metadataStorageConfiguration = $metadataStorageConfiguration;
}
- public function setMigrationsExecutedAtColumnName(string $migrationsExecutedAtColumnName) : void
+ /**
+ * @return string[]
+ */
+ public function getMigrationClasses() : array
{
- $this->migrationsExecutedAtColumnName = $migrationsExecutedAtColumnName;
+ return $this->migrationClasses;
}
- public function getMigrationsExecutedAtColumnName() : string
+ public function addMigrationClass(string $className) : void
{
- return $this->migrationsExecutedAtColumnName;
+ $this->migrationClasses[] = $className;
}
- public function getQuotedMigrationsExecutedAtColumnName() : string
+ public function getMetadataStorageConfiguration() : ?MetadataStorageConfigration
{
- return $this->getDependencyFactory()
- ->getTrackingTableDefinition()
- ->getExecutedAtColumn()
- ->getQuotedName($this->connection->getDatabasePlatform());
+ return $this->metadataStorageConfiguration;
}
- public function setMigrationsDirectory(string $migrationsDirectory) : void
+ public function addMigrationsDirectory(string $namespace, string $path) : void
{
- $this->migrationsDirectory = $migrationsDirectory;
+ $this->migrationsDirectories[$namespace] = $path;
}
- public function getMigrationsDirectory() : ?string
+ /**
+ * @return array
+ */
+ public function getMigrationDirectories() : array
{
- return $this->migrationsDirectory;
+ return $this->migrationsDirectories;
}
- public function setMigrationsNamespace(string $migrationsNamespace) : void
+ public function setName(string $name) : void
{
- $this->migrationsNamespace = $migrationsNamespace;
+ $this->name = $name;
}
- public function getMigrationsNamespace() : ?string
+ public function getName() : ?string
{
- return $this->migrationsNamespace;
+ return $this->name;
}
public function setCustomTemplate(?string $customTemplate) : void
@@ -215,8 +116,6 @@ public function areMigrationsOrganizedByYear() : bool
public function setMigrationsAreOrganizedByYear(
bool $migrationsAreOrganizedByYear = true
) : void {
- $this->ensureOrganizeMigrationsIsCompatibleWithFinder();
-
$this->migrationsAreOrganizedByYear = $migrationsAreOrganizedByYear;
}
@@ -226,8 +125,6 @@ public function setMigrationsAreOrganizedByYear(
public function setMigrationsAreOrganizedByYearAndMonth(
bool $migrationsAreOrganizedByYearAndMonth = true
) : void {
- $this->ensureOrganizeMigrationsIsCompatibleWithFinder();
-
$this->migrationsAreOrganizedByYear = $migrationsAreOrganizedByYearAndMonth;
$this->migrationsAreOrganizedByYearAndMonth = $migrationsAreOrganizedByYearAndMonth;
}
@@ -237,57 +134,12 @@ public function areMigrationsOrganizedByYearAndMonth() : bool
return $this->migrationsAreOrganizedByYearAndMonth;
}
- /** @throws MigrationException */
- public function setMigrationsFinder(MigrationFinder $migrationFinder) : void
- {
- if (($this->migrationsAreOrganizedByYear || $this->migrationsAreOrganizedByYearAndMonth)
- && ! ($migrationFinder instanceof MigrationDeepFinder)) {
- throw ParameterIncompatibleWithFinder::new(
- 'organize-migrations',
- $migrationFinder
- );
- }
-
- $this->migrationFinder = $migrationFinder;
- }
-
- public function getMigrationsFinder() : MigrationFinder
- {
- if ($this->migrationFinder === null) {
- $this->migrationFinder = $this->getDependencyFactory()->getRecursiveRegexFinder();
- }
-
- return $this->migrationFinder;
- }
-
/** @throws MigrationException */
public function validate() : void
{
- if ($this->migrationsNamespace === null) {
- throw MigrationsNamespaceRequired::new();
+ if (count($this->migrationsDirectories) === 0) {
+ throw MissingNamespaceConfiguration::new();
}
-
- if ($this->migrationsDirectory === null) {
- throw MigrationsDirectoryRequired::new();
- }
- }
-
- public function hasVersionMigrated(Version $version) : bool
- {
- return $this->getDependencyFactory()->getMigrationRepository()->hasVersionMigrated($version);
- }
-
- /**
- * @return mixed[]
- */
- public function getVersionData(Version $version) : ?array
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getVersionData($version);
- }
-
- public function resolveVersionAlias(string $alias) : ?string
- {
- return $this->getDependencyFactory()->getVersionAliasResolver()->resolveVersionAlias($alias);
}
public function setIsDryRun(bool $isDryRun) : void
@@ -320,229 +172,14 @@ public function isDatabasePlatformChecked() : bool
return $this->checkDbPlatform;
}
- public function isMigrationTableCreated() : bool
- {
- return $this->getDependencyFactory()->getTrackingTableStatus()->isCreated();
- }
-
- public function createMigrationTable() : bool
- {
- return $this->getDependencyFactory()->getTrackingTableManipulator()->createMigrationTable();
- }
-
- public function getDateTime(string $version) : string
- {
- $datetime = str_replace('Version', '', $version);
- $datetime = DateTimeImmutable::createFromFormat(self::VERSION_FORMAT, $datetime);
-
- if ($datetime === false) {
- return '';
- }
-
- return $datetime->format('Y-m-d H:i:s');
- }
-
- public function generateVersionNumber(?DateTimeInterface $now = null) : string
- {
- $now = $now ?: $this->createDateTime();
-
- return $now->format(self::VERSION_FORMAT);
- }
-
- /**
- * Explicitely opens the database connection. This is done to play nice
- * with DBAL's MasterSlaveConnection. Which, in some cases, connects to a
- * follower when fetching the executed migrations. If a follower is lagging
- * significantly behind that means the migrations system may see unexecuted
- * migrations that were actually executed earlier.
- */
- public function connect() : bool
- {
- if ($this->connection instanceof MasterSlaveConnection) {
- return $this->connection->connect('master');
- }
-
- return $this->connection->connect();
- }
-
- public function dispatchMigrationEvent(string $eventName, string $direction, bool $dryRun) : void
- {
- $this->getDependencyFactory()->getEventDispatcher()->dispatchMigrationEvent(
- $eventName,
- $direction,
- $dryRun
- );
- }
-
- public function dispatchVersionEvent(
- Version $version,
- string $eventName,
- string $direction,
- bool $dryRun
- ) : void {
- $this->getDependencyFactory()->getEventDispatcher()->dispatchVersionEvent(
- $version,
- $eventName,
- $direction,
- $dryRun
- );
- }
-
- public function dispatchEvent(string $eventName, ?EventArgs $args = null) : void
- {
- $this->getDependencyFactory()->getEventDispatcher()->dispatchEvent(
- $eventName,
- $args
- );
- }
-
- public function getNumberOfExecutedMigrations() : int
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getNumberOfExecutedMigrations();
- }
-
- public function getNumberOfAvailableMigrations() : int
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getNumberOfAvailableMigrations();
- }
-
- public function getLatestVersion() : string
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getLatestVersion();
- }
-
- /** @return string[] */
- public function getMigratedVersions() : array
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getMigratedVersions();
- }
-
- /** @return string[] */
- public function getAvailableVersions() : array
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getAvailableVersions();
- }
-
- public function getCurrentVersion() : string
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getCurrentVersion();
- }
-
- /** @return Version[] */
- public function registerMigrationsFromDirectory(string $path) : array
- {
- $this->validate();
-
- return $this->getDependencyFactory()->getMigrationRepository()->registerMigrationsFromDirectory($path);
- }
-
- /** @throws MigrationException */
- public function registerMigration(string $version, string $class) : Version
- {
- return $this->getDependencyFactory()->getMigrationRepository()->registerMigration($version, $class);
- }
-
- /**
- * @param string[] $migrations
- *
- * @return Version[]
- */
- public function registerMigrations(array $migrations) : array
- {
- return $this->getDependencyFactory()->getMigrationRepository()->registerMigrations($migrations);
- }
-
- /**
- * @return Version[]
- */
- public function getMigrations() : array
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getMigrations();
- }
-
- public function getVersion(string $version) : Version
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getVersion($version);
- }
-
- public function hasVersion(string $version) : bool
- {
- return $this->getDependencyFactory()->getMigrationRepository()->hasVersion($version);
- }
-
- /** @return Version[] */
- public function getMigrationsToExecute(string $direction, string $to) : array
- {
- return $this->getDependencyFactory()->getMigrationPlanCalculator()->getMigrationsToExecute($direction, $to);
- }
-
- public function getPrevVersion() : ?string
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getPrevVersion();
- }
-
- public function getNextVersion() : ?string
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getNextVersion();
- }
-
- public function getRelativeVersion(string $version, int $delta) : ?string
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getRelativeVersion($version, $delta);
- }
-
- public function getDeltaVersion(string $delta) : ?string
- {
- return $this->getDependencyFactory()->getMigrationRepository()->getDeltaVersion($delta);
- }
-
- public function setOutputWriter(OutputWriter $outputWriter) : void
+ public function setMigrationOrganization(string $migrationOrganization) : void
{
- $this->outputWriter = $outputWriter;
- }
-
- public function getOutputWriter() : OutputWriter
- {
- if ($this->outputWriter === null) {
- $this->outputWriter = $this->getDependencyFactory()->getOutputWriter();
- }
-
- return $this->outputWriter;
- }
-
- public function getQueryWriter() : QueryWriter
- {
- if ($this->queryWriter === null) {
- $this->queryWriter = $this->getDependencyFactory()->getQueryWriter();
- }
-
- return $this->queryWriter;
- }
-
- public function getDependencyFactory() : DependencyFactory
- {
- if ($this->dependencyFactory === null) {
- $this->dependencyFactory = new DependencyFactory($this);
- }
-
- return $this->dependencyFactory;
- }
-
- /**
- * @throws MigrationException
- */
- private function ensureOrganizeMigrationsIsCompatibleWithFinder() : void
- {
- if (! ($this->getMigrationsFinder() instanceof MigrationDeepFinder)) {
- throw ParameterIncompatibleWithFinder::new(
- 'organize-migrations',
- $this->getMigrationsFinder()
- );
+ if (strcasecmp($migrationOrganization, self::VERSIONS_ORGANIZATION_BY_YEAR) === 0) {
+ $this->setMigrationsAreOrganizedByYear();
+ } elseif (strcasecmp($migrationOrganization, self::VERSIONS_ORGANIZATION_BY_YEAR_AND_MONTH) === 0) {
+ $this->setMigrationsAreOrganizedByYearAndMonth();
+ } else {
+ throw UnknownConfigurationValue::new('organize_migrations', $migrationOrganization);
}
}
-
- private function createDateTime() : DateTimeImmutable
- {
- return new DateTimeImmutable('now', new DateTimeZone('UTC'));
- }
}
diff --git a/lib/Doctrine/Migrations/Configuration/ConfigurationLoader.php b/lib/Doctrine/Migrations/Configuration/ConfigurationLoader.php
new file mode 100644
index 0000000000..0e15127df4
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/ConfigurationLoader.php
@@ -0,0 +1,53 @@
+loaders[$type] = $loader;
+ }
+
+ private function setDefaultLoaders() : void
+ {
+ $this->loaders = [
+ 'array' => new ArrayLoader(),
+ 'json' => new JsonFileLoader(),
+ 'php' => new PhpFileLoader(),
+ 'xml' => new XmlFileLoader(),
+ 'yaml' => new YamlFileLoader(),
+ 'yml' => new YamlFileLoader(),
+ ];
+ }
+
+ public function getLoader(string $type) : Loader
+ {
+ if (count($this->loaders) === 0) {
+ $this->setDefaultLoaders();
+ }
+
+ if (! isset($this->loaders[$type])) {
+ throw UnknownLoader::new($type);
+ }
+
+ return $this->loaders[$type];
+ }
+}
diff --git a/lib/Doctrine/Migrations/Configuration/Connection/ConnectionLoaderInterface.php b/lib/Doctrine/Migrations/Configuration/Connection/ConnectionLoaderInterface.php
index 43ce1db41d..52b11a5995 100644
--- a/lib/Doctrine/Migrations/Configuration/Connection/ConnectionLoaderInterface.php
+++ b/lib/Doctrine/Migrations/Configuration/Connection/ConnectionLoaderInterface.php
@@ -5,6 +5,7 @@
namespace Doctrine\Migrations\Configuration\Connection;
use Doctrine\DBAL\Connection;
+use Doctrine\Migrations\Tools\Console\Exception\ConnectionNotSpecified;
/**
* The ConnectionLoaderInterface defines the interface used to load the Doctrine\DBAL\Connection instance to use
@@ -17,6 +18,8 @@ interface ConnectionLoaderInterface
/**
* Read the input and return a Connection, returns null if the config
* is not supported.
+ *
+ * @throws ConnectionNotSpecified
*/
- public function chosen() : ?Connection;
+ public function getConnection() : Connection;
}
diff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php
index d380ab8e0e..e992c88188 100644
--- a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php
+++ b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ArrayConnectionConfigurationLoader.php
@@ -17,14 +17,18 @@
*
* @internal
*/
-class ArrayConnectionConfigurationLoader implements ConnectionLoaderInterface
+final class ArrayConnectionConfigurationLoader implements ConnectionLoaderInterface
{
/** @var string|null */
private $filename;
- public function __construct(?string $filename)
+ /** @var ConnectionLoaderInterface */
+ private $fallback;
+
+ public function __construct(?string $filename, ConnectionLoaderInterface $fallback)
{
$this->filename = $filename;
+ $this->fallback = $fallback;
}
/**
@@ -33,14 +37,14 @@ public function __construct(?string $filename)
*
* @throws InvalidConfiguration
*/
- public function chosen() : ?Connection
+ public function getConnection() : Connection
{
if ($this->filename === null) {
- return null;
+ return $this->fallback->getConnection();
}
if (! file_exists($this->filename)) {
- return null;
+ return $this->fallback->getConnection();
}
$params = include $this->filename;
diff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionConfigurationChainLoader.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionConfigurationChainLoader.php
deleted file mode 100644
index cd36ea8560..0000000000
--- a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionConfigurationChainLoader.php
+++ /dev/null
@@ -1,48 +0,0 @@
-loaders = $loaders;
- }
-
- /**
- * Read the input and return a Configuration, returns null if the config
- * is not supported.
- *
- * @throws InvalidConfiguration
- */
- public function chosen() : ?Connection
- {
- foreach ($this->loaders as $loader) {
- $confObj = $loader->chosen();
-
- if ($confObj !== null) {
- return $confObj;
- }
- }
-
- return null;
- }
-}
diff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionConfigurationLoader.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionConfigurationLoader.php
deleted file mode 100644
index b5f601e878..0000000000
--- a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionConfigurationLoader.php
+++ /dev/null
@@ -1,39 +0,0 @@
-configuration = $configuration;
- }
-
- /**
- * Read the input and return a Configuration, returns null if the config
- * is not supported.
- */
- public function chosen() : ?Connection
- {
- if ($this->configuration !== null) {
- return $this->configuration->getConnection();
- }
-
- return null;
- }
-}
diff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionHelperLoader.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionHelperLoader.php
index f4567da201..3a36dac986 100644
--- a/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionHelperLoader.php
+++ b/lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionHelperLoader.php
@@ -14,7 +14,7 @@
*
* @internal
*/
-class ConnectionHelperLoader implements ConnectionLoaderInterface
+final class ConnectionHelperLoader implements ConnectionLoaderInterface
{
/** @var string */
private $helperName;
@@ -22,22 +22,21 @@ class ConnectionHelperLoader implements ConnectionLoaderInterface
/** @var HelperSet */
private $helperSet;
- public function __construct(?HelperSet $helperSet = null, string $helperName)
+ /** @var ConnectionLoaderInterface */
+ private $fallback;
+
+ public function __construct(string $helperName, ConnectionLoaderInterface $fallback, ?HelperSet $helperSet = null)
{
+ $this->helperSet = $helperSet ?: new HelperSet();
$this->helperName = $helperName;
-
- if ($helperSet === null) {
- $helperSet = new HelperSet();
- }
-
- $this->helperSet = $helperSet;
+ $this->fallback = $fallback;
}
/**
* Read the input and return a Configuration, returns null if the config
* is not supported.
*/
- public function chosen() : ?Connection
+ public function getConnection() : Connection
{
if ($this->helperSet->has($this->helperName)) {
$connectionHelper = $this->helperSet->get($this->helperName);
@@ -47,6 +46,6 @@ public function chosen() : ?Connection
}
}
- return null;
+ return $this->fallback->getConnection();
}
}
diff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/InvalidConfiguration.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/InvalidConfiguration.php
index 3b14f939a8..d3bc011bd3 100644
--- a/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/InvalidConfiguration.php
+++ b/lib/Doctrine/Migrations/Configuration/Connection/Loader/Exception/InvalidConfiguration.php
@@ -12,4 +12,9 @@ public static function invalidArrayConfiguration() : self
{
return new self('The connection file has to return an array with database configuration parameters.');
}
+
+ public static function notShardedConnection() : self
+ {
+ return new self('The connection must implement shards configuration.');
+ }
}
diff --git a/lib/Doctrine/Migrations/Configuration/Connection/Loader/NoConnectionLoader.php b/lib/Doctrine/Migrations/Configuration/Connection/Loader/NoConnectionLoader.php
new file mode 100644
index 0000000000..208b5154fc
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/Connection/Loader/NoConnectionLoader.php
@@ -0,0 +1,20 @@
+shard = $shard;
+ $this->fallback = $fallback;
+ }
+
+ /**
+ * Read the input and return a Configuration, returns null if the config
+ * is not supported.
+ */
+ public function getConnection() : Connection
+ {
+ $connection = $this->fallback->getConnection();
+
+ if ($this->shard === null) {
+ return $connection;
+ }
+
+ if (! $connection instanceof PoolingShardConnection) {
+ throw InvalidConfiguration::notShardedConnection();
+ }
+
+ $connection->connect($this->shard);
+
+ return $connection;
+ }
+}
diff --git a/lib/Doctrine/Migrations/Configuration/Exception/FileAlreadyLoaded.php b/lib/Doctrine/Migrations/Configuration/Exception/FileAlreadyLoaded.php
deleted file mode 100644
index 35ceb70a22..0000000000
--- a/lib/Doctrine/Migrations/Configuration/Exception/FileAlreadyLoaded.php
+++ /dev/null
@@ -1,15 +0,0 @@
-getDirectoryRelativeToFile(
- $file,
- $config['migrations_directory']
- );
- }
-
- $this->setConfiguration($config);
- }
-}
diff --git a/lib/Doctrine/Migrations/Configuration/Loader/AbstractFileLoader.php b/lib/Doctrine/Migrations/Configuration/Loader/AbstractFileLoader.php
new file mode 100644
index 0000000000..6aedabbd5e
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/Loader/AbstractFileLoader.php
@@ -0,0 +1,30 @@
+ $input
+ *
+ * @return array
+ */
+ final protected function getDirectoryRelativeToFile(string $file, array $input) : array
+ {
+ foreach ($input as $ns => $dir) {
+ $path = realpath(dirname($file) . '/' . $dir);
+
+ $input[$ns] = $path !== false ? $path : $dir;
+ }
+
+ return $input;
+ }
+}
diff --git a/lib/Doctrine/Migrations/Configuration/Loader/ArrayLoader.php b/lib/Doctrine/Migrations/Configuration/Loader/ArrayLoader.php
new file mode 100644
index 0000000000..c7970fcec6
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/Loader/ArrayLoader.php
@@ -0,0 +1,110 @@
+ static function ($paths, Configuration $configuration) : void {
+ foreach ($paths as $namespace => $path) {
+ $configuration->addMigrationsDirectory($namespace, $path);
+ }
+ },
+ 'migrations' => static function ($migrations, Configuration $configuration) : void {
+ foreach ($migrations as $className) {
+ $configuration->addMigrationClass($className);
+ }
+ },
+ 'table_storage' => [
+ 'table_name' => 'setTableName',
+ 'version_column_name' => 'setVersionColumnName',
+ 'version_column_length' => static function ($value, TableMetadataStorageConfiguration $configuration) : void {
+ $configuration->setVersionColumnLength((int) $value);
+ },
+ 'executed_at_column_name' => 'setExecutedAtColumnName',
+ 'execution_time_column_name' => 'setExecutionTimeColumnName',
+ ],
+
+ 'organize_migrations' => 'setMigrationOrganization',
+ 'name' => 'setName',
+ 'custom_template' => 'setCustomTemplate',
+ 'all_or_nothing' => static function ($value, Configuration $configuration) : void {
+ $configuration->setAllOrNothing(is_bool($value) ? $value : BooleanStringFormatter::toBoolean($value, false));
+ },
+ 'check_database_platform' => static function ($value, Configuration $configuration) : void {
+ $configuration->setCheckDatabasePlatform(is_bool($value) ? $value :BooleanStringFormatter::toBoolean($value, false));
+ },
+ ];
+
+ $object = new Configuration();
+ self::applyConfigs($configMap, $object, $array);
+
+ if ($object->getMetadataStorageConfiguration() === null) {
+ $object->setMetadataStorageConfiguration(new TableMetadataStorageConfiguration());
+ }
+
+ return $object;
+ }
+
+ /**
+ * @param mixed[] $configMap
+ * @param Configuration|TableMetadataStorageConfiguration $object
+ * @param array $data
+ */
+ private static function applyConfigs(array $configMap, $object, array $data) : void
+ {
+ foreach ($data as $configurationKey => $configurationValue) {
+ if (! isset($configMap[$configurationKey])) {
+ throw InvalidConfigurationKey::new((string) $configurationKey);
+ }
+
+ if (is_array($configMap[$configurationKey])) {
+ if ($configurationKey !== 'table_storage') {
+ throw InvalidConfigurationKey::new((string) $configurationKey);
+ }
+
+ $storageConfig = new TableMetadataStorageConfiguration();
+ assert($object instanceof Configuration);
+ $object->setMetadataStorageConfiguration($storageConfig);
+ self::applyConfigs($configMap[$configurationKey], $storageConfig, $configurationValue);
+ } else {
+ $callable = $configMap[$configurationKey] instanceof Closure
+ ? $configMap[$configurationKey]
+ : [$object, $configMap[$configurationKey]];
+ assert(is_callable($callable));
+ call_user_func(
+ $callable,
+ $configurationValue,
+ $object,
+ $data
+ );
+ }
+ }
+ }
+}
diff --git a/lib/Doctrine/Migrations/Configuration/Loader/JsonFileLoader.php b/lib/Doctrine/Migrations/Configuration/Loader/JsonFileLoader.php
new file mode 100644
index 0000000000..33946685cb
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/Loader/JsonFileLoader.php
@@ -0,0 +1,58 @@
+arrayLoader = new ArrayLoader();
+ }
+
+ /**
+ * @param mixed $file
+ */
+ public function load($file) : Configuration
+ {
+ if (! file_exists($file)) {
+ throw FileNotFound::new();
+ }
+
+ $contents = file_get_contents($file);
+
+ assert($contents !== false);
+
+ $config = json_decode($contents, true);
+
+ if (json_last_error() !== JSON_ERROR_NONE) {
+ throw JsonNotValid::new();
+ }
+
+ if (isset($config['migrations_paths'])) {
+ $config['migrations_paths'] = $this->getDirectoryRelativeToFile(
+ $file,
+ $config['migrations_paths']
+ );
+ }
+
+ return $this->arrayLoader->load($config);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Configuration/Loader/Loader.php b/lib/Doctrine/Migrations/Configuration/Loader/Loader.php
new file mode 100644
index 0000000000..80e6190ce8
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/Loader/Loader.php
@@ -0,0 +1,15 @@
+arrayLoader = new ArrayLoader();
+ }
+
+ /**
+ * @param mixed $file
+ */
+ public function load($file) : Configuration
+ {
+ if (! file_exists($file)) {
+ throw FileNotFound::new();
+ }
+ $config = require $file;
+ if ($config instanceof Configuration) {
+ return $config;
+ }
+
+ assert(is_array($config));
+ if (isset($config['migrations_paths'])) {
+ $config['migrations_paths'] = $this->getDirectoryRelativeToFile(
+ $file,
+ $config['migrations_paths']
+ );
+ }
+
+ return $this->arrayLoader->load($config);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Configuration/Loader/XML/configuration.xsd b/lib/Doctrine/Migrations/Configuration/Loader/XML/configuration.xsd
new file mode 100644
index 0000000000..e6bed43d94
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/Loader/XML/configuration.xsd
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/Doctrine/Migrations/Configuration/Loader/XmlFileLoader.php b/lib/Doctrine/Migrations/Configuration/Loader/XmlFileLoader.php
new file mode 100644
index 0000000000..dabcf03f60
--- /dev/null
+++ b/lib/Doctrine/Migrations/Configuration/Loader/XmlFileLoader.php
@@ -0,0 +1,126 @@
+arrayLoader = new ArrayLoader();
+ }
+
+ /**
+ * @param mixed|string $file
+ */
+ public function load($file) : Configuration
+ {
+ if (! file_exists($file)) {
+ throw FileNotFound::new();
+ }
+
+ $this->validateXml($file);
+
+ $rawXML = file_get_contents($file);
+ assert($rawXML !== false);
+
+ $root = simplexml_load_string($rawXML, SimpleXMLElement::class, LIBXML_NOCDATA);
+ assert($root !== false);
+
+ $config = $this->extractParameters($root, true);
+
+ if (isset($config['all_or_nothing'])) {
+ $config['all_or_nothing'] = BooleanStringFormatter::toBoolean(
+ $config['all_or_nothing'],
+ false
+ );
+ }
+ if (isset($config['migrations_paths'])) {
+ $config['migrations_paths'] = $this->getDirectoryRelativeToFile(
+ $file,
+ $config['migrations_paths']
+ );
+ }
+
+ return $this->arrayLoader->load($config);
+ }
+
+ /**
+ * @return mixed[]
+ */
+ private function extractParameters(SimpleXMLElement $root, bool $loopOverNodes) : array
+ {
+ $config = [];
+
+ $itemsToCheck = $loopOverNodes ? $root->children() : $root->attributes();
+
+ if (! ($itemsToCheck instanceof SimpleXMLElement)) {
+ return $config;
+ }
+ foreach ($itemsToCheck as $node) {
+ $nodeName = strtr($node->getName(), '-', '_');
+ if ($nodeName === 'migrations_paths') {
+ $config['migrations_paths'] = [];
+ foreach ($node->{'path'} as $pathNode) {
+ $config['migrations_paths'][(string) $pathNode['namespace']] = (string) $pathNode;
+ }
+ } elseif ($nodeName === 'storage' && $node->{'table-storage'} instanceof SimpleXMLElement) {
+ $config['table_storage'] = $this->extractParameters($node->{'table-storage'}, false);
+ } elseif ($nodeName === 'migrations') {
+ $config['migrations'] = [];
+ foreach ($node->{'migration'} as $pathNode) {
+ $config['migrations'][] = (string) $pathNode;
+ }
+ } else {
+ $config[$nodeName] = (string) $node;
+ }
+ }
+
+ return $config;
+ }
+
+ private function validateXml(string $file) : void
+ {
+ try {
+ libxml_use_internal_errors(true);
+
+ $xml = new DOMDocument();
+
+ if ($xml->load($file) === false) {
+ throw XmlNotValid::malformed();
+ }
+
+ $xsdPath = __DIR__ . DIRECTORY_SEPARATOR . 'XML' . DIRECTORY_SEPARATOR . 'configuration.xsd';
+
+ if ($xml->schemaValidate($xsdPath) === false) {
+ throw XmlNotValid::failedValidation();
+ }
+ } finally {
+ libxml_clear_errors();
+ libxml_use_internal_errors(false);
+ }
+ }
+}
diff --git a/lib/Doctrine/Migrations/Configuration/YamlConfiguration.php b/lib/Doctrine/Migrations/Configuration/Loader/YamlFileLoader.php
similarity index 52%
rename from lib/Doctrine/Migrations/Configuration/YamlConfiguration.php
rename to lib/Doctrine/Migrations/Configuration/Loader/YamlFileLoader.php
index 17c86c7bee..b75e64c340 100644
--- a/lib/Doctrine/Migrations/Configuration/YamlConfiguration.php
+++ b/lib/Doctrine/Migrations/Configuration/Loader/YamlFileLoader.php
@@ -2,33 +2,46 @@
declare(strict_types=1);
-namespace Doctrine\Migrations\Configuration;
+namespace Doctrine\Migrations\Configuration\Loader;
+use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\Configuration\Exception\FileNotFound;
use Doctrine\Migrations\Configuration\Exception\YamlNotAvailable;
use Doctrine\Migrations\Configuration\Exception\YamlNotValid;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;
use function assert;
use function class_exists;
+use function file_exists;
use function file_get_contents;
use function is_array;
/**
- * The YamlConfiguration class is responsible for loading migration configuration information from a YAML file.
- *
* @internal
*/
-class YamlConfiguration extends AbstractFileConfiguration
+final class YamlFileLoader extends AbstractFileLoader
{
+ /** @var ArrayLoader */
+ private $arrayLoader;
+
+ public function __construct()
+ {
+ $this->arrayLoader = new ArrayLoader();
+ }
+
/**
- * @inheritdoc
+ * @param mixed $file
*/
- protected function doLoad(string $file) : void
+ public function load($file) : Configuration
{
if (! class_exists(Yaml::class)) {
throw YamlNotAvailable::new();
}
+ if (! file_exists($file)) {
+ throw FileNotFound::new();
+ }
+
$content = file_get_contents($file);
assert($content !== false);
@@ -43,13 +56,13 @@ protected function doLoad(string $file) : void
throw YamlNotValid::invalid();
}
- if (isset($config['migrations_directory'])) {
- $config['migrations_directory'] = $this->getDirectoryRelativeToFile(
+ if (isset($config['migrations_paths'])) {
+ $config['migrations_paths'] = $this->getDirectoryRelativeToFile(
$file,
- $config['migrations_directory']
+ $config['migrations_paths']
);
}
- $this->setConfiguration($config);
+ return $this->arrayLoader->load($config);
}
}
diff --git a/lib/Doctrine/Migrations/Configuration/XML/configuration.xsd b/lib/Doctrine/Migrations/Configuration/XML/configuration.xsd
deleted file mode 100644
index 187c4aefe1..0000000000
--- a/lib/Doctrine/Migrations/Configuration/XML/configuration.xsd
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/Doctrine/Migrations/Configuration/XmlConfiguration.php b/lib/Doctrine/Migrations/Configuration/XmlConfiguration.php
deleted file mode 100644
index 0c074828db..0000000000
--- a/lib/Doctrine/Migrations/Configuration/XmlConfiguration.php
+++ /dev/null
@@ -1,119 +0,0 @@
-load($file) === false) {
- throw XmlNotValid::malformed();
- }
-
- $xsdPath = __DIR__ . DIRECTORY_SEPARATOR . 'XML' . DIRECTORY_SEPARATOR . 'configuration.xsd';
-
- if (! $xml->schemaValidate($xsdPath)) {
- libxml_clear_errors();
-
- throw XmlNotValid::failedValidation();
- }
-
- $rawXML = file_get_contents($file);
- assert($rawXML !== false);
-
- $xml = simplexml_load_string($rawXML, SimpleXMLElement::class, LIBXML_NOCDATA);
- assert($xml !== false);
-
- $config = [];
-
- if (isset($xml->name)) {
- $config['name'] = (string) $xml->name;
- }
-
- if (isset($xml->{'custom-template'})) {
- $config['custom_template'] = (string) $xml->{'custom-template'};
- }
-
- if (isset($xml->table['name'])) {
- $config['table_name'] = (string) $xml->table['name'];
- }
-
- if (isset($xml->table['column'])) {
- $config['column_name'] = (string) $xml->table['column'];
- }
-
- if (isset($xml->table['column_length'])) {
- $config['column_length'] = (int) $xml->table['column_length'];
- }
-
- if (isset($xml->table['executed_at_column'])) {
- $config['executed_at_column_name'] = (string) $xml->table['executed_at_column'];
- }
-
- if (isset($xml->{'migrations-namespace'})) {
- $config['migrations_namespace'] = (string) $xml->{'migrations-namespace'};
- }
-
- if (isset($xml->{'organize-migrations'})) {
- $config['organize_migrations'] = (string) $xml->{'organize-migrations'};
- }
-
- if (isset($xml->{'migrations-directory'})) {
- $config['migrations_directory'] = $this->getDirectoryRelativeToFile(
- $file,
- (string) $xml->{'migrations-directory'}
- );
- }
-
- if (isset($xml->{'all-or-nothing'})) {
- $config['all_or_nothing'] = BooleanStringFormatter::toBoolean(
- (string) $xml->{'all-or-nothing'},
- false
- );
- }
-
- if (isset($xml->migrations->migration)) {
- $migrations = [];
-
- foreach ($xml->migrations->migration as $migration) {
- $attributes = $migration->attributes();
-
- $version = (string) $attributes['version'];
- $class = (string) $attributes['class'];
-
- $migrations[] = [
- 'version' => $version,
- 'class' => $class,
- ];
- }
-
- $config['migrations'] = $migrations;
- }
-
- $this->setConfiguration($config);
- }
-}
diff --git a/lib/Doctrine/Migrations/DependencyFactory.php b/lib/Doctrine/Migrations/DependencyFactory.php
index 87090c350c..a81c22365a 100644
--- a/lib/Doctrine/Migrations/DependencyFactory.php
+++ b/lib/Doctrine/Migrations/DependencyFactory.php
@@ -6,25 +6,40 @@
use Doctrine\DBAL\Connection;
use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\Exception\MissingDependency;
+use Doctrine\Migrations\Finder\GlobFinder;
+use Doctrine\Migrations\Finder\MigrationFinder;
use Doctrine\Migrations\Finder\RecursiveRegexFinder;
+use Doctrine\Migrations\Generator\ClassNameGenerator;
+use Doctrine\Migrations\Generator\DiffGenerator;
use Doctrine\Migrations\Generator\FileBuilder;
use Doctrine\Migrations\Generator\Generator;
use Doctrine\Migrations\Generator\SqlGenerator;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorageConfigration;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorage;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
+use Doctrine\Migrations\Provider\DBALSchemaDiffProvider;
use Doctrine\Migrations\Provider\LazySchemaDiffProvider;
+use Doctrine\Migrations\Provider\OrmSchemaProvider;
use Doctrine\Migrations\Provider\SchemaDiffProvider;
-use Doctrine\Migrations\Provider\SchemaDiffProviderInterface;
+use Doctrine\Migrations\Provider\SchemaProvider;
+use Doctrine\Migrations\Tools\Console\ConsoleInputMigratorConfigurationFactory;
use Doctrine\Migrations\Tools\Console\Helper\MigrationStatusInfosHelper;
-use Doctrine\Migrations\Tracking\TableDefinition;
-use Doctrine\Migrations\Tracking\TableManipulator;
-use Doctrine\Migrations\Tracking\TableStatus;
-use Doctrine\Migrations\Tracking\TableUpdater;
+use Doctrine\Migrations\Tools\Console\MigratorConfigurationFactory;
use Doctrine\Migrations\Version\AliasResolver;
+use Doctrine\Migrations\Version\AliasResolverInterface;
use Doctrine\Migrations\Version\Executor;
-use Doctrine\Migrations\Version\Factory;
+use Doctrine\Migrations\Version\MigrationFactory;
+use Doctrine\ORM\EntityManagerInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
use Symfony\Component\Stopwatch\Stopwatch as SymfonyStopwatch;
+use function preg_quote;
+use function sprintf;
/**
- * The DepenencyFactory is responsible for wiring up and managing internal class dependencies.
+ * The DependencyFactory is responsible for wiring up and managing internal class dependencies.
*
* @internal
*/
@@ -36,40 +51,114 @@ class DependencyFactory
/** @var object[] */
private $dependencies = [];
- public function __construct(Configuration $configuration)
+ /** @var LoggerInterface */
+ private $logger;
+
+ /** @var Connection */
+ private $connection;
+
+ /** @var callable */
+ private $sorter;
+
+ /** @var EntityManagerInterface|null */
+ private $em;
+
+ public function __construct(Configuration $configuration, Connection $connection, ?EntityManagerInterface $em = null, ?LoggerInterface $logger = null)
{
+ if ($configuration->getMetadataStorageConfiguration() instanceof MetadataStorageConfigration) {
+ $this->setMetadataStorageConfiguration($configuration->getMetadataStorageConfiguration());
+ }
+
$this->configuration = $configuration;
+ $this->logger = $logger ?: new NullLogger();
+ $this->connection = $connection;
+ $this->em = $em;
+ }
+
+ public function setLogger(LoggerInterface $logger) : void
+ {
+ $this->logger = $logger;
+ }
+
+ public function getConfiguration() : Configuration
+ {
+ return $this->configuration;
+ }
+
+ private function getConnection() : Connection
+ {
+ return $this->connection;
}
public function getEventDispatcher() : EventDispatcher
{
return $this->getDependency(EventDispatcher::class, function () : EventDispatcher {
return new EventDispatcher(
- $this->configuration,
+ $this->getConnection(),
$this->getConnection()->getEventManager()
);
});
}
+ public function getClassNameGenerator() : ClassNameGenerator
+ {
+ return $this->getDependency(ClassNameGenerator::class, static function () : ClassNameGenerator {
+ return new ClassNameGenerator();
+ });
+ }
+
public function getSchemaDumper() : SchemaDumper
{
return $this->getDependency(SchemaDumper::class, function () : SchemaDumper {
+ $excludedTables = [];
+
+ $metadataConfig = $this->configuration->getMetadataStorageConfiguration();
+ if ($metadataConfig instanceof TableMetadataStorageConfiguration) {
+ $excludedTables[] = sprintf('/^%s$/', preg_quote($metadataConfig->getTableName(), '/'));
+ }
+
return new SchemaDumper(
$this->getConnection()->getDatabasePlatform(),
$this->getConnection()->getSchemaManager(),
$this->getMigrationGenerator(),
+ $this->getMigrationSqlGenerator(),
+ $excludedTables
+ );
+ });
+ }
+
+ private function getSchemaProvider() : SchemaProvider
+ {
+ return $this->getDependency(SchemaProvider::class, function () : SchemaProvider {
+ if ($this->em === null) {
+ throw new MissingDependency('The doctrine entity manager should be provided in order to be able to instantiate SchemaProvider');
+ }
+
+ return new OrmSchemaProvider($this->em);
+ });
+ }
+
+ public function getDiffGenerator() : DiffGenerator
+ {
+ return $this->getDependency(DiffGenerator::class, function () : DiffGenerator {
+ return new DiffGenerator(
+ $this->getConnection()->getConfiguration(),
+ $this->getConnection()->getSchemaManager(),
+ $this->getSchemaProvider(),
+ $this->getConnection()->getDatabasePlatform(),
+ $this->getMigrationGenerator(),
$this->getMigrationSqlGenerator()
);
});
}
- public function getSchemaDiffProvider() : SchemaDiffProviderInterface
+ public function getSchemaDiffProvider() : SchemaDiffProvider
{
- return $this->getDependency(SchemaDiffProviderInterface::class, function () : LazySchemaDiffProvider {
+ return $this->getDependency(SchemaDiffProvider::class, function () : LazySchemaDiffProvider {
return LazySchemaDiffProvider::fromDefaultProxyFactoryConfiguration(
- new SchemaDiffProvider(
- $this->getConnection()->getSchemaManager(),
- $this->getConnection()->getDatabasePlatform()
+ new DBALSchemaDiffProvider(
+ $this->connection->getSchemaManager(),
+ $this->connection->getDatabasePlatform()
)
);
});
@@ -77,119 +166,110 @@ public function getSchemaDiffProvider() : SchemaDiffProviderInterface
public function getFileBuilder() : FileBuilder
{
- return $this->getDependency(FileBuilder::class, function () : FileBuilder {
- return new FileBuilder(
- $this->getConnection()->getDatabasePlatform(),
- $this->configuration->getMigrationsTableName(),
- $this->configuration->getQuotedMigrationsColumnName(),
- $this->configuration->getQuotedMigrationsExecutedAtColumnName()
- );
+ return $this->getDependency(FileBuilder::class, static function () : FileBuilder {
+ return new FileBuilder();
});
}
public function getParameterFormatter() : ParameterFormatterInterface
{
return $this->getDependency(ParameterFormatter::class, function () : ParameterFormatter {
- return new ParameterFormatter($this->getConnection());
+ return new ParameterFormatter($this->connection);
+ });
+ }
+
+ public function getMigrationsFinder() : MigrationFinder
+ {
+ return $this->getDependency(GlobFinder::class, function () : MigrationFinder {
+ $configs = $this->getConfiguration();
+ $needsRecursiveFinder = $configs->areMigrationsOrganizedByYear() || $configs->areMigrationsOrganizedByYearAndMonth();
+
+ return $needsRecursiveFinder ? new RecursiveRegexFinder() : new GlobFinder();
});
}
+ public function setSorter(callable $sorter) : void
+ {
+ $this->sorter = $sorter;
+ }
+
public function getMigrationRepository() : MigrationRepository
{
return $this->getDependency(MigrationRepository::class, function () : MigrationRepository {
return new MigrationRepository(
- $this->configuration,
- $this->getConnection(),
- $this->configuration->getMigrationsFinder(),
- new Factory($this->configuration, $this->getVersionExecutor())
+ $this->getConfiguration()->getMigrationClasses(),
+ $this->getConfiguration()->getMigrationDirectories(),
+ $this->getMigrationsFinder(),
+ new MigrationFactory($this->getConnection(), $this->getLogger()),
+ $this->sorter
);
});
}
- public function getTrackingTableManipulator() : TableManipulator
+ public function setMetadataStorageConfiguration(MetadataStorageConfigration $metadataStorageConfigration) : void
{
- return $this->getDependency(TableManipulator::class, function () : TableManipulator {
- return new TableManipulator(
- $this->configuration,
- $this->getConnection()->getSchemaManager(),
- $this->getTrackingTableDefinition(),
- $this->getTrackingTableStatus(),
- $this->getTrackingTableUpdater()
- );
- });
+ $this->dependencies[MetadataStorageConfigration::class] = $metadataStorageConfigration;
}
- public function getTrackingTableDefinition() : TableDefinition
+ private function getMetadataStorageConfiguration() : MetadataStorageConfigration
{
- return $this->getDependency(TableDefinition::class, function () : TableDefinition {
- return new TableDefinition(
- $this->getConnection()->getSchemaManager(),
- $this->configuration->getMigrationsTableName(),
- $this->configuration->getMigrationsColumnName(),
- $this->configuration->getMigrationsColumnLength(),
- $this->configuration->getMigrationsExecutedAtColumnName()
- );
+ return $this->getDependency(MetadataStorageConfigration::class, static function () : MetadataStorageConfigration {
+ return new TableMetadataStorageConfiguration();
});
}
- public function getTrackingTableStatus() : TableStatus
+ public function getMetadataStorage() : MetadataStorage
{
- return $this->getDependency(TableStatus::class, function () : TableStatus {
- return new TableStatus(
- $this->getConnection()->getSchemaManager(),
- $this->getTrackingTableDefinition()
+ return $this->getDependency(TableMetadataStorage::class, function () : MetadataStorage {
+ return new TableMetadataStorage(
+ $this->connection,
+ $this->getMetadataStorageConfiguration()
);
});
}
- public function getTrackingTableUpdater() : TableUpdater
+ public function getEntityManager() : ?EntityManagerInterface
{
- return $this->getDependency(TableUpdater::class, function () : TableUpdater {
- return new TableUpdater(
- $this->getConnection(),
- $this->getConnection()->getSchemaManager(),
- $this->getTrackingTableDefinition(),
- $this->getConnection()->getDatabasePlatform()
- );
- });
+ return $this->em;
+ }
+
+ public function getLogger() : LoggerInterface
+ {
+ return $this->logger;
}
public function getVersionExecutor() : Executor
{
return $this->getDependency(Executor::class, function () : Executor {
return new Executor(
- $this->configuration,
- $this->getConnection(),
+ $this->getMetadataStorage(),
+ $this->getEventDispatcher(),
+ $this->connection,
$this->getSchemaDiffProvider(),
- $this->getOutputWriter(),
+ $this->getLogger(),
$this->getParameterFormatter(),
$this->getStopwatch()
);
});
}
- public function getQueryWriter() : FileQueryWriter
+ public function getQueryWriter() : QueryWriter
{
- return $this->getDependency(FileQueryWriter::class, function () : FileQueryWriter {
+ return $this->getDependency(QueryWriter::class, function () : QueryWriter {
return new FileQueryWriter(
- $this->getOutputWriter(),
- $this->getFileBuilder()
+ $this->getFileBuilder(),
+ $this->logger
);
});
}
- public function getOutputWriter() : OutputWriter
- {
- return $this->getDependency(OutputWriter::class, static function () : OutputWriter {
- return new OutputWriter();
- });
- }
-
- public function getVersionAliasResolver() : AliasResolver
+ public function getVersionAliasResolver() : AliasResolverInterface
{
- return $this->getDependency(AliasResolver::class, function () : AliasResolver {
+ return $this->getDependency(AliasResolverInterface::class, function () : AliasResolverInterface {
return new AliasResolver(
- $this->getMigrationRepository()
+ $this->getMigrationRepository(),
+ $this->getMetadataStorage(),
+ $this->getMigrationPlanCalculator()
);
});
}
@@ -197,21 +277,17 @@ public function getVersionAliasResolver() : AliasResolver
public function getMigrationPlanCalculator() : MigrationPlanCalculator
{
return $this->getDependency(MigrationPlanCalculator::class, function () : MigrationPlanCalculator {
- return new MigrationPlanCalculator($this->getMigrationRepository());
- });
- }
-
- public function getRecursiveRegexFinder() : RecursiveRegexFinder
- {
- return $this->getDependency(RecursiveRegexFinder::class, static function () : RecursiveRegexFinder {
- return new RecursiveRegexFinder();
+ return new MigrationPlanCalculator(
+ $this->getMigrationRepository(),
+ $this->getMetadataStorage()
+ );
});
}
public function getMigrationGenerator() : Generator
{
return $this->getDependency(Generator::class, function () : Generator {
- return new Generator($this->configuration);
+ return new Generator($this->getConfiguration());
});
}
@@ -219,8 +295,17 @@ public function getMigrationSqlGenerator() : SqlGenerator
{
return $this->getDependency(SqlGenerator::class, function () : SqlGenerator {
return new SqlGenerator(
- $this->configuration,
- $this->getConnection()->getDatabasePlatform()
+ $this->getConfiguration(),
+ $this->connection->getDatabasePlatform()
+ );
+ });
+ }
+
+ public function getConsoleInputMigratorConfigurationFactory() : MigratorConfigurationFactory
+ {
+ return $this->getDependency(MigratorConfigurationFactory::class, function () : MigratorConfigurationFactory {
+ return new ConsoleInputMigratorConfigurationFactory(
+ $this->getConfiguration()
);
});
}
@@ -229,19 +314,21 @@ public function getMigrationStatusInfosHelper() : MigrationStatusInfosHelper
{
return $this->getDependency(MigrationStatusInfosHelper::class, function () : MigrationStatusInfosHelper {
return new MigrationStatusInfosHelper(
- $this->configuration,
- $this->getMigrationRepository()
+ $this->getConfiguration(),
+ $this->connection,
+ $this->getVersionAliasResolver()
);
});
}
- public function getMigrator() : Migrator
+ public function getMigrator() : MigratorInterface
{
- return $this->getDependency(Migrator::class, function () : Migrator {
+ return $this->getDependency(MigratorInterface::class, function () : MigratorInterface {
return new Migrator(
- $this->configuration,
- $this->getMigrationRepository(),
- $this->getOutputWriter(),
+ $this->connection,
+ $this->getEventDispatcher(),
+ $this->getVersionExecutor(),
+ $this->logger,
$this->getStopwatch()
);
});
@@ -260,8 +347,7 @@ public function getRollup() : Rollup
{
return $this->getDependency(Rollup::class, function () : Rollup {
return new Rollup(
- $this->configuration,
- $this->getConnection(),
+ $this->getMetadataStorage(),
$this->getMigrationRepository()
);
});
@@ -278,9 +364,4 @@ private function getDependency(string $className, callable $callback)
return $this->dependencies[$className];
}
-
- private function getConnection() : Connection
- {
- return $this->configuration->getConnection();
- }
}
diff --git a/lib/Doctrine/Migrations/Event/Listeners/AutoCommitListener.php b/lib/Doctrine/Migrations/Event/Listeners/AutoCommitListener.php
index 8d723c6641..7726476534 100644
--- a/lib/Doctrine/Migrations/Event/Listeners/AutoCommitListener.php
+++ b/lib/Doctrine/Migrations/Event/Listeners/AutoCommitListener.php
@@ -19,8 +19,9 @@ final class AutoCommitListener implements EventSubscriber
public function onMigrationsMigrated(MigrationsEventArgs $args) : void
{
$conn = $args->getConnection();
+ $conf = $args->getMigratorConfiguration();
- if ($args->isDryRun() || $conn->isAutoCommit()) {
+ if ($conf->isDryRun() || $conn->isAutoCommit()) {
return;
}
diff --git a/lib/Doctrine/Migrations/Event/MigrationsEventArgs.php b/lib/Doctrine/Migrations/Event/MigrationsEventArgs.php
index 6778a815ba..62e58cac06 100644
--- a/lib/Doctrine/Migrations/Event/MigrationsEventArgs.php
+++ b/lib/Doctrine/Migrations/Event/MigrationsEventArgs.php
@@ -6,46 +6,45 @@
use Doctrine\Common\EventArgs;
use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
+use Doctrine\Migrations\MigratorConfiguration;
/**
* The MigrationEventsArgs class is passed to events not related to a single migration version.
*/
-class MigrationsEventArgs extends EventArgs
+final class MigrationsEventArgs extends EventArgs
{
- /** @var Configuration */
- private $config;
-
- /** @var string */
- private $direction;
-
- /** @var bool */
- private $dryRun;
-
- public function __construct(Configuration $config, string $direction, bool $dryRun)
- {
- $this->config = $config;
- $this->direction = $direction;
- $this->dryRun = $dryRun;
- }
-
- public function getConfiguration() : Configuration
- {
- return $this->config;
+ /** @var Connection */
+ private $connection;
+
+ /** @var MigrationPlanList */
+ private $plan;
+
+ /** @var MigratorConfiguration */
+ private $migratorConfiguration;
+
+ public function __construct(
+ Connection $connection,
+ MigrationPlanList $plan,
+ MigratorConfiguration $migratorConfiguration
+ ) {
+ $this->connection = $connection;
+ $this->plan = $plan;
+ $this->migratorConfiguration = $migratorConfiguration;
}
public function getConnection() : Connection
{
- return $this->config->getConnection();
+ return $this->connection;
}
- public function getDirection() : string
+ public function getPlan() : MigrationPlanList
{
- return $this->direction;
+ return $this->plan;
}
- public function isDryRun() : bool
+ public function getMigratorConfiguration() : MigratorConfiguration
{
- return $this->dryRun;
+ return $this->migratorConfiguration;
}
}
diff --git a/lib/Doctrine/Migrations/Event/MigrationsVersionEventArgs.php b/lib/Doctrine/Migrations/Event/MigrationsVersionEventArgs.php
index 83f11f2d83..05f2effdd4 100644
--- a/lib/Doctrine/Migrations/Event/MigrationsVersionEventArgs.php
+++ b/lib/Doctrine/Migrations/Event/MigrationsVersionEventArgs.php
@@ -4,30 +4,47 @@
namespace Doctrine\Migrations\Event;
-use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Version\Version;
+use Doctrine\Common\EventArgs;
+use Doctrine\DBAL\Connection;
+use Doctrine\Migrations\Metadata\MigrationPlan;
+use Doctrine\Migrations\MigratorConfiguration;
/**
* The MigrationsVersionEventArgs class is passed to events related to a single migration version.
*/
-class MigrationsVersionEventArgs extends MigrationsEventArgs
+final class MigrationsVersionEventArgs extends EventArgs
{
- /** @var Version */
- private $version;
+ /** @var Connection */
+ private $connection;
+
+ /** @var MigrationPlan */
+ private $plan;
+
+ /** @var MigratorConfiguration */
+ private $migratorConfiguration;
public function __construct(
- Version $version,
- Configuration $config,
- string $direction,
- bool $dryRun
+ Connection $connection,
+ MigrationPlan $plan,
+ MigratorConfiguration $migratorConfiguration
) {
- parent::__construct($config, $direction, $dryRun);
+ $this->connection = $connection;
+ $this->plan = $plan;
+ $this->migratorConfiguration = $migratorConfiguration;
+ }
- $this->version = $version;
+ public function getConnection() : Connection
+ {
+ return $this->connection;
+ }
+
+ public function getPlan() : MigrationPlan
+ {
+ return $this->plan;
}
- public function getVersion() : Version
+ public function getMigratorConfiguration() : MigratorConfiguration
{
- return $this->version;
+ return $this->migratorConfiguration;
}
}
diff --git a/lib/Doctrine/Migrations/EventDispatcher.php b/lib/Doctrine/Migrations/EventDispatcher.php
index d8e562555f..16485b6ab2 100644
--- a/lib/Doctrine/Migrations/EventDispatcher.php
+++ b/lib/Doctrine/Migrations/EventDispatcher.php
@@ -6,10 +6,11 @@
use Doctrine\Common\EventArgs;
use Doctrine\Common\EventManager;
-use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\DBAL\Connection;
use Doctrine\Migrations\Event\MigrationsEventArgs;
use Doctrine\Migrations\Event\MigrationsVersionEventArgs;
-use Doctrine\Migrations\Version\Version;
+use Doctrine\Migrations\Metadata\MigrationPlan;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
/**
* The EventDispatcher class is responsible for dispatching events internally that a user can listen for.
@@ -18,60 +19,61 @@
*/
final class EventDispatcher
{
- /** @var Configuration */
- private $configuration;
-
/** @var EventManager */
private $eventManager;
- public function __construct(Configuration $configuration, EventManager $eventManager)
+ /** @var Connection */
+ private $connection;
+
+ public function __construct(Connection $connection, EventManager $eventManager)
{
- $this->configuration = $configuration;
- $this->eventManager = $eventManager;
+ $this->eventManager = $eventManager;
+ $this->connection = $connection;
}
- public function dispatchMigrationEvent(string $eventName, string $direction, bool $dryRun) : void
- {
- $event = $this->createMigrationEventArgs($direction, $dryRun);
+ public function dispatchMigrationEvent(
+ string $eventName,
+ MigrationPlanList $migrationsPlan,
+ MigratorConfiguration $migratorConfiguration
+ ) : void {
+ $event = $this->createMigrationEventArgs($migrationsPlan, $migratorConfiguration);
$this->dispatchEvent($eventName, $event);
}
public function dispatchVersionEvent(
- Version $version,
string $eventName,
- string $direction,
- bool $dryRun
+ MigrationPlan $plan,
+ MigratorConfiguration $migratorConfiguration
) : void {
$event = $this->createMigrationsVersionEventArgs(
- $version,
- $direction,
- $dryRun
+ $plan,
+ $migratorConfiguration
);
$this->dispatchEvent($eventName, $event);
}
- public function dispatchEvent(string $eventName, ?EventArgs $args = null) : void
+ private function dispatchEvent(string $eventName, ?EventArgs $args = null) : void
{
$this->eventManager->dispatchEvent($eventName, $args);
}
- private function createMigrationEventArgs(string $direction, bool $dryRun) : MigrationsEventArgs
- {
- return new MigrationsEventArgs($this->configuration, $direction, $dryRun);
+ private function createMigrationEventArgs(
+ MigrationPlanList $migrationsPlan,
+ MigratorConfiguration $migratorConfiguration
+ ) : MigrationsEventArgs {
+ return new MigrationsEventArgs($this->connection, $migrationsPlan, $migratorConfiguration);
}
private function createMigrationsVersionEventArgs(
- Version $version,
- string $direction,
- bool $dryRun
+ MigrationPlan $plan,
+ MigratorConfiguration $migratorConfiguration
) : MigrationsVersionEventArgs {
return new MigrationsVersionEventArgs(
- $version,
- $this->configuration,
- $direction,
- $dryRun
+ $this->connection,
+ $plan,
+ $migratorConfiguration
);
}
}
diff --git a/lib/Doctrine/Migrations/Exception/MigrationClassNotFound.php b/lib/Doctrine/Migrations/Exception/MigrationClassNotFound.php
index fe392068fe..571442228c 100644
--- a/lib/Doctrine/Migrations/Exception/MigrationClassNotFound.php
+++ b/lib/Doctrine/Migrations/Exception/MigrationClassNotFound.php
@@ -9,13 +9,12 @@
final class MigrationClassNotFound extends RuntimeException implements MigrationException
{
- public static function new(string $migrationClass, ?string $migrationNamespace) : self
+ public static function new(string $migrationClass) : self
{
return new self(
sprintf(
- 'Migration class "%s" was not found. Is it placed in "%s" namespace?',
- $migrationClass,
- $migrationNamespace
+ 'Migration class "%s" was not found?',
+ $migrationClass
)
);
}
diff --git a/lib/Doctrine/Migrations/Exception/MigrationNotAvailable.php b/lib/Doctrine/Migrations/Exception/MigrationNotAvailable.php
new file mode 100644
index 0000000000..d22397f502
--- /dev/null
+++ b/lib/Doctrine/Migrations/Exception/MigrationNotAvailable.php
@@ -0,0 +1,23 @@
+outputWriter = $outputWriter;
$this->migrationFileBuilder = $migrationFileBuilder;
+ $this->logger = $logger;
}
/**
@@ -48,11 +49,7 @@ public function write(
$path = $this->buildMigrationFilePath($path, $now);
- if ($this->outputWriter !== null) {
- $this->outputWriter->write(
- "\n" . sprintf('Writing migration file to "%s"', $path)
- );
- }
+ $this->logger->info('Writing migration file to "{path}"', ['path' => $path]);
return file_put_contents($path, $string) !== false;
}
diff --git a/lib/Doctrine/Migrations/Finder/Finder.php b/lib/Doctrine/Migrations/Finder/Finder.php
index 1c7b3db02b..42a37bed8b 100644
--- a/lib/Doctrine/Migrations/Finder/Finder.php
+++ b/lib/Doctrine/Migrations/Finder/Finder.php
@@ -16,7 +16,6 @@
use function realpath;
use function strlen;
use function strncmp;
-use function substr;
/**
* The Finder class is responsible for for finding migrations on disk at a given path.
@@ -64,13 +63,7 @@ protected function loadMigrations(array $files, ?string $namespace) : array
$classes = $this->loadMigrationClasses($includedFiles, $namespace);
$versions = [];
foreach ($classes as $class) {
- $version = substr($class->getShortName(), 7);
-
- if ($version === '0') {
- throw NameIsReserved::new($version);
- }
-
- $versions[$version] = $class->getName();
+ $versions[] = $class->getName();
}
ksort($versions, SORT_STRING);
@@ -87,7 +80,7 @@ protected function loadMigrations(array $files, ?string $namespace) : array
*
* @return ReflectionClass[] the classes in `$files`
*/
- protected function loadMigrationClasses(array $files, ?string $namespace) : array
+ protected function loadMigrationClasses(array $files, ?string $namespace = null) : array
{
$classes = [];
foreach (get_declared_classes() as $class) {
diff --git a/lib/Doctrine/Migrations/Finder/GlobFinder.php b/lib/Doctrine/Migrations/Finder/GlobFinder.php
index aa4045e045..ae0fb39ae1 100644
--- a/lib/Doctrine/Migrations/Finder/GlobFinder.php
+++ b/lib/Doctrine/Migrations/Finder/GlobFinder.php
@@ -13,13 +13,13 @@
final class GlobFinder extends Finder
{
/**
- * @return string[]
+ * {@inheritDoc}
*/
public function findMigrations(string $directory, ?string $namespace = null) : array
{
$dir = $this->getRealPath($directory);
- $files = glob(rtrim($dir, '/') . '/Version*.php');
+ $files = glob(rtrim($dir, '/') . '/Version*.php') ?: [];
return $this->loadMigrations($files, $namespace);
}
diff --git a/lib/Doctrine/Migrations/Finder/MigrationDeepFinder.php b/lib/Doctrine/Migrations/Finder/MigrationDeepFinder.php
deleted file mode 100644
index 9c8e5eccaa..0000000000
--- a/lib/Doctrine/Migrations/Finder/MigrationDeepFinder.php
+++ /dev/null
@@ -1,12 +0,0 @@
-pattern = $pattern ?: sprintf(
+ '#^.+\\%s[^\\%s]+\\.php$#i',
+ DIRECTORY_SEPARATOR,
+ DIRECTORY_SEPARATOR
+ );
+ }
+
/**
* @return string[]
*/
@@ -43,11 +55,7 @@ private function createIterator(string $dir) : RegexIterator
private function getPattern() : string
{
- return sprintf(
- '#^.+\\%sVersion[^\\%s]{1,255}\\.php$#i',
- DIRECTORY_SEPARATOR,
- DIRECTORY_SEPARATOR
- );
+ return $this->pattern;
}
/**
diff --git a/lib/Doctrine/Migrations/Generator/ClassNameGenerator.php b/lib/Doctrine/Migrations/Generator/ClassNameGenerator.php
new file mode 100644
index 0000000000..3c9ca0c835
--- /dev/null
+++ b/lib/Doctrine/Migrations/Generator/ClassNameGenerator.php
@@ -0,0 +1,25 @@
+generateVersionNumber();
+ }
+
+ private function generateVersionNumber() : string
+ {
+ $now = new DateTimeImmutable('now', new DateTimeZone('UTC'));
+
+ return $now->format(self::VERSION_FORMAT);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Generator/DiffGenerator.php b/lib/Doctrine/Migrations/Generator/DiffGenerator.php
index ffe304899a..eaa6fc1213 100644
--- a/lib/Doctrine/Migrations/Generator/DiffGenerator.php
+++ b/lib/Doctrine/Migrations/Generator/DiffGenerator.php
@@ -10,7 +10,7 @@
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\Generator\Exception\NoChangesDetected;
-use Doctrine\Migrations\Provider\SchemaProviderInterface;
+use Doctrine\Migrations\Provider\SchemaProvider;
use function preg_match;
use function strpos;
use function substr;
@@ -29,7 +29,7 @@ class DiffGenerator
/** @var AbstractSchemaManager */
private $schemaManager;
- /** @var SchemaProviderInterface */
+ /** @var SchemaProvider */
private $schemaProvider;
/** @var AbstractPlatform */
@@ -44,7 +44,7 @@ class DiffGenerator
public function __construct(
DBALConfiguration $dbalConfiguration,
AbstractSchemaManager $schemaManager,
- SchemaProviderInterface $schemaProvider,
+ SchemaProvider $schemaProvider,
AbstractPlatform $platform,
Generator $migrationGenerator,
SqlGenerator $migrationSqlGenerator
@@ -61,7 +61,7 @@ public function __construct(
* @throws NoChangesDetected
*/
public function generate(
- string $versionNumber,
+ string $fqcn,
?string $filterExpression,
bool $formatted = false,
int $lineLength = 120,
@@ -102,7 +102,7 @@ static function ($assetName) use ($filterExpression) {
}
return $this->migrationGenerator->generateMigration(
- $versionNumber,
+ $fqcn,
$up,
$down
);
diff --git a/lib/Doctrine/Migrations/Generator/FileBuilder.php b/lib/Doctrine/Migrations/Generator/FileBuilder.php
index 933860855a..f87ee43d82 100644
--- a/lib/Doctrine/Migrations/Generator/FileBuilder.php
+++ b/lib/Doctrine/Migrations/Generator/FileBuilder.php
@@ -4,9 +4,8 @@
namespace Doctrine\Migrations\Generator;
+use DateTimeImmutable;
use DateTimeInterface;
-use Doctrine\DBAL\Platforms\AbstractPlatform;
-use Doctrine\Migrations\Version\Direction;
use function sprintf;
/**
@@ -14,38 +13,15 @@
*
* @internal
*/
-final class FileBuilder
+final class FileBuilder implements FileBuilderInterface
{
- /** @var AbstractPlatform */
- private $platform;
-
- /** @var string */
- private $tableName;
-
- /** @var string */
- private $columnName;
-
- /** @var string */
- private $executedAtColumnName;
-
- public function __construct(
- AbstractPlatform $platform,
- string $tableName,
- string $columnName,
- string $executedAtColumnName
- ) {
- $this->platform = $platform;
- $this->tableName = $tableName;
- $this->columnName = $columnName;
- $this->executedAtColumnName = $executedAtColumnName;
- }
-
/** @param string[][] $queriesByVersion */
public function buildMigrationFile(
array $queriesByVersion,
string $direction,
- DateTimeInterface $now
+ ?DateTimeInterface $now = null
) : string {
+ $now = $now ?: new DateTimeImmutable();
$string = sprintf("-- Doctrine Migration File Generated on %s\n", $now->format('Y-m-d H:i:s'));
foreach ($queriesByVersion as $version => $queries) {
@@ -56,31 +32,8 @@ public function buildMigrationFile(
foreach ($queries as $query) {
$string .= $query . ";\n";
}
-
- $string .= $this->getVersionUpdateQuery($version, $direction);
}
return $string;
}
-
- private function getVersionUpdateQuery(string $version, string $direction) : string
- {
- if ($direction === Direction::DOWN) {
- return sprintf(
- "DELETE FROM %s WHERE %s = '%s';\n",
- $this->tableName,
- $this->columnName,
- $version
- );
- }
-
- return sprintf(
- "INSERT INTO %s (%s, %s) VALUES ('%s', %s);\n",
- $this->tableName,
- $this->columnName,
- $this->executedAtColumnName,
- $version,
- $this->platform->getCurrentTimestampSQL()
- );
- }
}
diff --git a/lib/Doctrine/Migrations/Generator/FileBuilderInterface.php b/lib/Doctrine/Migrations/Generator/FileBuilderInterface.php
new file mode 100644
index 0000000000..d54e19ee78
--- /dev/null
+++ b/lib/Doctrine/Migrations/Generator/FileBuilderInterface.php
@@ -0,0 +1,18 @@
+ extends AbstractMigration
+final class extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
- public function up(Schema $schema) : void
+
}
- public function down(Schema $schema) : void
+>
}
-}
+>}
TEMPLATE;
@@ -71,30 +76,62 @@ public function __construct(Configuration $configuration)
}
public function generateMigration(
- string $version,
+ string $fqcn,
?string $up = null,
- ?string $down = null
+ ?string $down = null,
+ ?string $upMethod = null,
+ ?string $downMethod = null
) : string {
- $placeHolders = [
- '',
- '',
- '',
- '',
- ];
+ $mch = [];
+ if (preg_match('~(.*)\\\\([^\\\\]+)~', $fqcn, $mch) === 0) {
+ throw new InvalidArgumentException(sprintf('Invalid FQCN'));
+ }
+ [$fqcn, $namespace, $className] = $mch;
+
+ $dirs = $this->configuration->getMigrationDirectories();
+ if (! isset($dirs[$namespace])) {
+ throw new InvalidArgumentException(sprintf('Path not defined for the namespace "%s"', $namespace));
+ }
+
+ $dir = $dirs[$namespace];
$replacements = [
- $this->configuration->getMigrationsNamespace(),
- $version,
- $up !== null ? ' ' . implode("\n ", explode("\n", $up)) : null,
- $down !== null ? ' ' . implode("\n ", explode("\n", $down)) : null,
+ 'namespace' => $namespace,
+ 'className' => $className,
+ 'up' => $up !== null ? ' ' . implode("\n ", explode("\n", $up)) : null,
+ 'down' => $down !== null ? ' ' . implode("\n ", explode("\n", $down)) : null,
];
- $code = str_replace($placeHolders, $replacements, $this->getTemplate());
+ if ($upMethod !== null) {
+ $replacements['upMethod'] = $upMethod;
+ }
+
+ if ($downMethod !== null) {
+ $replacements['downMethod'] = $downMethod;
+ }
+ $code = $this->getTemplate();
+
+ for ($i = 0; $i<2; $i++) {
+ $code = preg_replace_callback('/\<(?:[^<>]+|(?R))*+\>/m', static function (array $mch) use ($replacements) : string {
+ $subMatch = [];
+ if (preg_match('/^\<([a-z]+)\>$/i', $mch[0], $subMatch)!==0) {
+ return $replacements[$subMatch[1]] ?? '';
+ }
+
+ if (preg_match('/\<([a-z]+),(.+)\>/ixs', $mch[0], $subMatch)!==0) {
+ return $replacements[$subMatch[1]] ?? $subMatch[2];
+ }
+
+ return '';
+ }, $code);
+ assert(is_string($code));
+ }
+
$code = preg_replace('/^ +$/m', '', $code);
- $directoryHelper = new MigrationDirectoryHelper($this->configuration);
- $dir = $directoryHelper->getMigrationDirectory();
- $path = $dir . '/Version' . $version . '.php';
+ $directoryHelper = new MigrationDirectoryHelper();
+ $dir = $directoryHelper->getMigrationDirectory($this->configuration, $dir);
+ $path = $dir . '/' . $className . '.php';
file_put_contents($path, $code);
diff --git a/lib/Doctrine/Migrations/Generator/SqlGenerator.php b/lib/Doctrine/Migrations/Generator/SqlGenerator.php
index fa216179bc..8c92c126ed 100644
--- a/lib/Doctrine/Migrations/Generator/SqlGenerator.php
+++ b/lib/Doctrine/Migrations/Generator/SqlGenerator.php
@@ -6,6 +6,7 @@
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use SqlFormatter;
use function array_unshift;
use function count;
@@ -44,8 +45,10 @@ public function generate(
) : string {
$code = [];
+ $storageConfiguration = $this->configuration->getMetadataStorageConfiguration();
foreach ($sql as $query) {
- if (stripos($query, $this->configuration->getMigrationsTableName()) !== false) {
+ if ($storageConfiguration instanceof TableMetadataStorageConfiguration
+ && stripos($query, $storageConfiguration->getTableName()) !== false) {
continue;
}
diff --git a/lib/Doctrine/Migrations/Metadata/AvailableMigration.php b/lib/Doctrine/Migrations/Metadata/AvailableMigration.php
new file mode 100644
index 0000000000..2a60c32f80
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/AvailableMigration.php
@@ -0,0 +1,33 @@
+version = $version;
+ $this->migration = $migration;
+ }
+
+ public function getVersion() : Version
+ {
+ return $this->version;
+ }
+
+ public function getMigration() : AbstractMigration
+ {
+ return $this->migration;
+ }
+}
diff --git a/lib/Doctrine/Migrations/Metadata/AvailableMigrationsList.php b/lib/Doctrine/Migrations/Metadata/AvailableMigrationsList.php
new file mode 100644
index 0000000000..b375e2c0dd
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/AvailableMigrationsList.php
@@ -0,0 +1,80 @@
+items = array_values($items);
+ }
+
+ /**
+ * @return AvailableMigration[]
+ */
+ public function getItems() : array
+ {
+ return $this->items;
+ }
+
+ public function getFirst(int $offset = 0) : AvailableMigration
+ {
+ if (! isset($this->items[$offset])) {
+ throw NoMigrationsFoundWithCriteria::new('first' . ($offset > 0 ? ('+' . $offset) : ''));
+ }
+
+ return $this->items[$offset];
+ }
+
+ public function getLast(int $offset = 0) : AvailableMigration
+ {
+ $offset = count($this->items) - 1 - (-1 * $offset);
+ if (! isset($this->items[$offset])) {
+ throw NoMigrationsFoundWithCriteria::new('last' . ($offset > 0 ? ('+' . $offset) : ''));
+ }
+
+ return $this->items[$offset];
+ }
+
+ public function count() : int
+ {
+ return count($this->items);
+ }
+
+ public function hasMigration(Version $version) : bool
+ {
+ foreach ($this->items as $migration) {
+ if ($migration->getVersion()->equals($version)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function getMigration(Version $version) : AvailableMigration
+ {
+ foreach ($this->items as $migration) {
+ if ($migration->getVersion()->equals($version)) {
+ return $migration;
+ }
+ }
+
+ throw MigrationNotAvailable::forVersion($version);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Metadata/ExecutedMigration.php b/lib/Doctrine/Migrations/Metadata/ExecutedMigration.php
new file mode 100644
index 0000000000..4f86e46dd5
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/ExecutedMigration.php
@@ -0,0 +1,46 @@
+version = $version;
+ $this->executedAt = $executedAt;
+ $this->executionTime = $executionTime;
+ }
+
+ public function getExecutionTime() : ?int
+ {
+ return $this->executionTime;
+ }
+
+ public function getExecutedAt() : ?DateTimeImmutable
+ {
+ return $this->executedAt;
+ }
+
+ public function getVersion() : Version
+ {
+ return $this->version;
+ }
+}
diff --git a/lib/Doctrine/Migrations/Metadata/ExecutedMigrationsSet.php b/lib/Doctrine/Migrations/Metadata/ExecutedMigrationsSet.php
new file mode 100644
index 0000000000..0a38419c6f
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/ExecutedMigrationsSet.php
@@ -0,0 +1,79 @@
+items = array_values($items);
+ }
+
+ /**
+ * @return ExecutedMigration[]
+ */
+ public function getItems() : array
+ {
+ return $this->items;
+ }
+
+ public function getFirst(int $offset = 0) : ExecutedMigration
+ {
+ if (! isset($this->items[$offset])) {
+ throw NoMigrationsFoundWithCriteria::new('first' . ($offset > 0 ? ('+' . $offset) : ''));
+ }
+
+ return $this->items[$offset];
+ }
+
+ public function getLast(int $offset = 0) : ExecutedMigration
+ {
+ $offset = count($this->items) - 1 - (-1 * $offset);
+ if (! isset($this->items[$offset])) {
+ throw NoMigrationsFoundWithCriteria::new('last' . ($offset > 0 ? ('+' . $offset) : ''));
+ }
+
+ return $this->items[$offset];
+ }
+
+ public function count() : int
+ {
+ return count($this->items);
+ }
+
+ public function hasMigration(Version $version) : bool
+ {
+ foreach ($this->items as $migration) {
+ if ($migration->getVersion()->equals($version)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function getMigration(Version $version) : ExecutedMigration
+ {
+ foreach ($this->items as $migration) {
+ if ($migration->getVersion()->equals($version)) {
+ return $migration;
+ }
+ }
+ throw MigrationNotExecuted::new((string) $version);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Metadata/MigrationPlan.php b/lib/Doctrine/Migrations/Metadata/MigrationPlan.php
new file mode 100644
index 0000000000..8ee430b69a
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/MigrationPlan.php
@@ -0,0 +1,59 @@
+version = $version;
+ $this->migration = $migration;
+ $this->direction = $direction;
+ }
+
+ public function getVersion() : Version
+ {
+ return $this->version;
+ }
+
+ public function getResult() : ?ExecutionResult
+ {
+ return $this->result;
+ }
+
+ public function markAsExecuted(ExecutionResult $result) : void
+ {
+ if ($this->result !== null) {
+ throw PlanAlreadyExecuted::new();
+ }
+
+ $this->result = $result;
+ }
+
+ public function getMigration() : AbstractMigration
+ {
+ return $this->migration;
+ }
+
+ public function getDirection() : string
+ {
+ return $this->direction;
+ }
+}
diff --git a/lib/Doctrine/Migrations/Metadata/MigrationPlanList.php b/lib/Doctrine/Migrations/Metadata/MigrationPlanList.php
new file mode 100644
index 0000000000..459f36bf67
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/MigrationPlanList.php
@@ -0,0 +1,65 @@
+items = $items;
+ $this->direction = $direction;
+ }
+
+ public function count() : int
+ {
+ return count($this->items);
+ }
+
+ /**
+ * @return MigrationPlan[]
+ */
+ public function getItems() : array
+ {
+ return $this->items;
+ }
+
+ public function getDirection() : string
+ {
+ return $this->direction;
+ }
+
+ public function getFirst() : MigrationPlan
+ {
+ if (count($this->items) === 0) {
+ throw NoMigrationsFoundWithCriteria::new('first');
+ }
+
+ return reset($this->items);
+ }
+
+ public function getLast() : MigrationPlan
+ {
+ if (count($this->items) === 0) {
+ throw NoMigrationsFoundWithCriteria::new('last');
+ }
+
+ return end($this->items);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Metadata/Storage/MetadataStorage.php b/lib/Doctrine/Migrations/Metadata/Storage/MetadataStorage.php
new file mode 100644
index 0000000000..ee458726cd
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/Storage/MetadataStorage.php
@@ -0,0 +1,17 @@
+connection = $connection;
+ $this->schemaManager = $connection->getSchemaManager();
+ $this->platform = $connection->getDatabasePlatform();
+
+ if ($configuration !== null && ! ($configuration instanceof TableMetadataStorageConfiguration)) {
+ throw new InvalidArgumentException(sprintf('%s accepts only %s as configuration', self::class, TableMetadataStorageConfiguration::class));
+ }
+ $this->configuration = $configuration ?: new TableMetadataStorageConfiguration();
+ }
+
+ private function isInitialized() : bool
+ {
+ if ($this->connection instanceof MasterSlaveConnection) {
+ $this->connection->connect('master');
+ }
+
+ return $this->schemaManager->tablesExist([$this->configuration->getTableName()]);
+ }
+
+ private function initialize() : void
+ {
+ $schemaChangelog = new Table($this->configuration->getTableName());
+
+ $schemaChangelog->addColumn($this->configuration->getVersionColumnName(), 'string', ['notnull' => true, 'length' => $this->configuration->getVersionColumnLength()]);
+ $schemaChangelog->addColumn($this->configuration->getExecutedAtColumnName(), 'datetime', ['notnull' => false]);
+ $schemaChangelog->addColumn($this->configuration->getExecutionTimeColumnName(), 'integer', ['notnull' => false]);
+
+ $schemaChangelog->setPrimaryKey([$this->configuration->getVersionColumnName()]);
+
+ $this->schemaManager->createTable($schemaChangelog);
+ }
+
+ public function getExecutedMigrations() : ExecutedMigrationsSet
+ {
+ if (! $this->isInitialized()) {
+ $this->initialize();
+ }
+
+ $rows = $this->connection->fetchAll(sprintf('SELECT * FROM %s', $this->configuration->getTableName()));
+
+ $migrations = [];
+ foreach ($rows as $row) {
+ $row = array_change_key_case($row, CASE_LOWER);
+
+ $version = new Version($row[strtolower($this->configuration->getVersionColumnName())]);
+
+ $executedAt = $row[strtolower($this->configuration->getExecutedAtColumnName())] ?? '';
+ $executedAt = $executedAt !== ''
+ ? DateTimeImmutable::createFromFormat($this->platform->getDateTimeFormatString(), $executedAt)
+ : null;
+
+ $executionTime = isset($row[strtolower($this->configuration->getExecutionTimeColumnName())])
+ ? intval($row[strtolower($this->configuration->getExecutionTimeColumnName())])
+ : null;
+
+ $migration = new ExecutedMigration(
+ $version,
+ $executedAt instanceof DateTimeImmutable ? $executedAt : null,
+ $executionTime
+ );
+
+ $migrations[(string) $version] = $migration;
+ }
+
+ return new ExecutedMigrationsSet($migrations);
+ }
+
+ public function reset() : void
+ {
+ $this->connection->executeUpdate(
+ sprintf(
+ 'DELETE FROM %s WHERE 1 = 1',
+ $this->platform->quoteIdentifier($this->configuration->getTableName())
+ )
+ );
+ }
+
+ public function complete(ExecutionResult $result) : void
+ {
+ if (! $this->isInitialized()) {
+ $this->initialize();
+ }
+
+ if ($result->getDirection() === Direction::DOWN) {
+ $this->connection->delete($this->configuration->getTableName(), [
+ $this->configuration->getVersionColumnName() => (string) $result->getVersion(),
+ ]);
+ } else {
+ $this->connection->insert($this->configuration->getTableName(), [
+ $this->configuration->getVersionColumnName() => (string) $result->getVersion(),
+ $this->configuration->getExecutedAtColumnName() => $result->getExecutedAt(),
+ $this->configuration->getExecutionTimeColumnName() => $result->getTime() === null ? null : (int) $result->getTime(),
+ ], [
+ Type::STRING,
+ Type::DATETIME,
+ Type::INTEGER,
+ ]);
+ }
+ }
+}
diff --git a/lib/Doctrine/Migrations/Metadata/Storage/TableMetadataStorageConfiguration.php b/lib/Doctrine/Migrations/Metadata/Storage/TableMetadataStorageConfiguration.php
new file mode 100644
index 0000000000..f250af57b3
--- /dev/null
+++ b/lib/Doctrine/Migrations/Metadata/Storage/TableMetadataStorageConfiguration.php
@@ -0,0 +1,73 @@
+tableName;
+ }
+
+ public function setTableName(string $tableName) : void
+ {
+ $this->tableName = $tableName;
+ }
+
+ public function getVersionColumnName() : string
+ {
+ return $this->versionColumnName;
+ }
+
+ public function setVersionColumnName(string $versionColumnName) : void
+ {
+ $this->versionColumnName = $versionColumnName;
+ }
+
+ public function getVersionColumnLength() : int
+ {
+ return $this->versionColumnLength;
+ }
+
+ public function setVersionColumnLength(int $versionColumnLength) : void
+ {
+ $this->versionColumnLength = $versionColumnLength;
+ }
+
+ public function getExecutedAtColumnName() : string
+ {
+ return $this->executedAtColumnName;
+ }
+
+ public function setExecutedAtColumnName(string $executedAtColumnName) : void
+ {
+ $this->executedAtColumnName = $executedAtColumnName;
+ }
+
+ public function getExecutionTimeColumnName() : string
+ {
+ return $this->executionTimeColumnName;
+ }
+
+ public function setExecutionTimeColumnName(string $executionTimeColumnName) : void
+ {
+ $this->executionTimeColumnName = $executionTimeColumnName;
+ }
+}
diff --git a/lib/Doctrine/Migrations/MigrationPlanCalculator.php b/lib/Doctrine/Migrations/MigrationPlanCalculator.php
index b494ddb598..22f8d2e568 100644
--- a/lib/Doctrine/Migrations/MigrationPlanCalculator.php
+++ b/lib/Doctrine/Migrations/MigrationPlanCalculator.php
@@ -4,12 +4,20 @@
namespace Doctrine\Migrations;
+use Doctrine\Migrations\Exception\NoMigrationsFoundWithCriteria;
+use Doctrine\Migrations\Exception\NoMigrationsToExecute;
+use Doctrine\Migrations\Metadata\AvailableMigration;
+use Doctrine\Migrations\Metadata\AvailableMigrationsList;
+use Doctrine\Migrations\Metadata\ExecutedMigration;
+use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
+use Doctrine\Migrations\Metadata\MigrationPlan;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\Version\Direction;
use Doctrine\Migrations\Version\Version;
use function array_filter;
+use function array_map;
use function array_reverse;
-use function count;
-use function in_array;
/**
* The MigrationPlanCalculator is responsible for calculating the plan for migrating from the current
@@ -22,56 +30,107 @@ final class MigrationPlanCalculator
/** @var MigrationRepository */
private $migrationRepository;
- public function __construct(MigrationRepository $migrationRepository)
+ /** @var MetadataStorage */
+ private $metadataStorage;
+
+ public function __construct(MigrationRepository $migrationRepository, MetadataStorage $metadataStorage)
{
$this->migrationRepository = $migrationRepository;
+ $this->metadataStorage = $metadataStorage;
}
- /** @return Version[] */
- public function getMigrationsToExecute(string $direction, string $to) : array
+ public function getPlanForExactVersion(Version $version, string $direction) : MigrationPlanList
{
- $allVersions = $this->migrationRepository->getMigrations();
+ $migration = $this->migrationRepository->getMigration($version);
+
+ $planItem = new MigrationPlan($migration->getVersion(), $migration->getMigration(), $direction);
+
+ return new MigrationPlanList([$planItem], $direction);
+ }
- if ($direction === Direction::DOWN && count($allVersions) !== 0) {
- $allVersions = array_reverse($allVersions);
+ public function getPlanUntilVersion(?Version $to = null) : MigrationPlanList
+ {
+ $availableMigrations = $this->migrationRepository->getMigrations();
+ $executedMigrations = $this->metadataStorage->getExecutedMigrations();
+
+ try {
+ $to = $to ?: $availableMigrations->getLast()->getVersion();
+ } catch (NoMigrationsFoundWithCriteria $e) {
+ throw NoMigrationsToExecute::new($e);
}
- $migrated = $this->migrationRepository->getMigratedVersions();
+ $direction = $this->findDirection($to, $executedMigrations);
- return array_filter($allVersions, function (Version $version) use (
- $migrated,
- $direction,
- $to
- ) {
- return $this->shouldExecuteMigration($direction, $version, $to, $migrated);
- });
- }
+ $migrationsToCheck = $this->arrangeMigrationsForDirection($direction, $availableMigrations);
- /** @param string[] $migrated */
- private function shouldExecuteMigration(
- string $direction,
- Version $version,
- string $to,
- array $migrated
- ) : bool {
- $to = (int) $to;
-
- if ($direction === Direction::DOWN) {
- if (! in_array($version->getVersion(), $migrated, true)) {
- return false;
- }
+ $toExecute = $this->findMigrationsToExecute($to, $migrationsToCheck, $direction, $executedMigrations);
+
+ return new MigrationPlanList(array_map(static function (AvailableMigration $migration) use ($direction) {
+ return new MigrationPlan($migration->getVersion(), $migration->getMigration(), $direction);
+ }, $toExecute), $direction);
+ }
- return (int) $version->getVersion() > $to;
+ private function findDirection(Version $to, Metadata\ExecutedMigrationsSet $executedMigrations) : string
+ {
+ if ((string) $to === '0' || ($executedMigrations->hasMigration($to) && ! $executedMigrations->getLast()->getVersion()->equals($to))) {
+ return Direction::DOWN;
}
- if ($direction === Direction::UP) {
- if (in_array($version->getVersion(), $migrated, true)) {
- return false;
+ return Direction::UP;
+ }
+
+ /**
+ * @return AvailableMigration[]
+ */
+ private function arrangeMigrationsForDirection(string $direction, Metadata\AvailableMigrationsList $availableMigrations) : array
+ {
+ return $direction === Direction::UP ? $availableMigrations->getItems() : array_reverse($availableMigrations->getItems());
+ }
+
+ /**
+ * @param AvailableMigration[] $migrationsToCheck
+ *
+ * @return AvailableMigration[]
+ */
+ private function findMigrationsToExecute(Version $to, array $migrationsToCheck, string $direction, Metadata\ExecutedMigrationsSet $executedMigrations) : array
+ {
+ $toExecute = [];
+ foreach ($migrationsToCheck as $availableMigration) {
+ if ($direction === Direction::DOWN && $availableMigration->getVersion()->equals($to)) {
+ break;
}
- return (int) $version->getVersion() <= $to;
+ if ($direction === Direction::UP && ! $executedMigrations->hasMigration($availableMigration->getVersion())) {
+ $toExecute[] = $availableMigration;
+ } elseif ($direction === Direction::DOWN && $executedMigrations->hasMigration($availableMigration->getVersion())) {
+ $toExecute[] = $availableMigration;
+ }
+
+ if ($direction === Direction::UP && $availableMigration->getVersion()->equals($to)) {
+ break;
+ }
}
- return false;
+ return $toExecute;
+ }
+
+ public function getExecutedUnavailableMigrations() : ExecutedMigrationsSet
+ {
+ $executedMigrationsSet = $this->metadataStorage->getExecutedMigrations();
+ $availableMigrationsSet = $this->migrationRepository->getMigrations();
+
+ return new ExecutedMigrationsSet(array_filter($executedMigrationsSet->getItems(), static function (ExecutedMigration $migrationInfo) use ($availableMigrationsSet) {
+ return ! $availableMigrationsSet->hasMigration($migrationInfo->getVersion());
+ }));
+ }
+
+ public function getNewMigrations() : AvailableMigrationsList
+ {
+ $executedMigrationsSet = $this->metadataStorage->getExecutedMigrations();
+ $availableMigrationsSet = $this->migrationRepository->getMigrations();
+
+ return new AvailableMigrationsList(array_filter($availableMigrationsSet->getItems(), static function (AvailableMigration $migrationInfo) use ($executedMigrationsSet) {
+ return ! $executedMigrationsSet->hasMigration($migrationInfo->getVersion());
+ }));
}
}
diff --git a/lib/Doctrine/Migrations/MigrationRepository.php b/lib/Doctrine/Migrations/MigrationRepository.php
index c98faa7c4d..0e2c4e6810 100644
--- a/lib/Doctrine/Migrations/MigrationRepository.php
+++ b/lib/Doctrine/Migrations/MigrationRepository.php
@@ -4,30 +4,17 @@
namespace Doctrine\Migrations;
-use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Exception\DuplicateMigrationVersion;
use Doctrine\Migrations\Exception\MigrationClassNotFound;
use Doctrine\Migrations\Exception\MigrationException;
-use Doctrine\Migrations\Exception\UnknownMigrationVersion;
use Doctrine\Migrations\Finder\MigrationFinder;
-use Doctrine\Migrations\Version\Factory;
+use Doctrine\Migrations\Metadata\AvailableMigration;
+use Doctrine\Migrations\Metadata\AvailableMigrationsList;
+use Doctrine\Migrations\Version\MigrationFactory;
use Doctrine\Migrations\Version\Version;
-use const SORT_STRING;
-use function array_diff;
-use function array_keys;
-use function array_map;
-use function array_search;
-use function array_unshift;
use function class_exists;
-use function count;
-use function end;
-use function get_class;
-use function implode;
-use function is_array;
-use function ksort;
-use function sprintf;
-use function substr;
+use function strcmp;
+use function uasort;
/**
* The MigrationRepository class is responsible for retrieving migrations, determing what the current migration
@@ -37,379 +24,140 @@
*/
class MigrationRepository
{
- /** @var Configuration */
- private $configuration;
+ /** @var bool */
+ private $migrationsLoaded = false;
- /** @var Connection */
- private $connection;
+ /** @var array */
+ private $migrationDirectories;
/** @var MigrationFinder */
private $migrationFinder;
- /** @var Factory */
+ /** @var MigrationFactory */
private $versionFactory;
- /** @var Version[] */
- private $versions = [];
+ /** @var AvailableMigration[] */
+ private $migrations = [];
- public function __construct(
- Configuration $configuration,
- Connection $connection,
- MigrationFinder $migrationFinder,
- Factory $versionFactory
- ) {
- $this->configuration = $configuration;
- $this->connection = $connection;
- $this->migrationFinder = $migrationFinder;
- $this->versionFactory = $versionFactory;
- }
+ /** @var callable */
+ private $sorter;
/**
- * @return string[]
+ * @param array $migrationDirectories
+ * @param string[] $classes
*/
- public function findMigrations(string $path) : array
- {
- return $this->migrationFinder->findMigrations(
- $path,
- $this->configuration->getMigrationsNamespace()
- );
- }
-
- /** @return Version[] */
- public function registerMigrationsFromDirectory(string $path) : array
- {
- return $this->registerMigrations($this->findMigrations($path));
- }
-
- public function addVersion(Version $version) : void
- {
- $this->versions[$version->getVersion()] = $version;
+ public function __construct(
+ array $classes,
+ array $migrationDirectories,
+ MigrationFinder $migrationFinder,
+ MigrationFactory $versionFactory,
+ ?callable $sorter = null
+ ) {
+ $this->migrationDirectories = $migrationDirectories;
+ $this->migrationFinder = $migrationFinder;
+ $this->versionFactory = $versionFactory;
+ $this->sorter = $sorter ?: static function (AvailableMigration $m1, AvailableMigration $m2) {
+ return strcmp((string) $m1->getVersion(), (string) $m2->getVersion());
+ };
- ksort($this->versions, SORT_STRING);
+ $this->registerMigrations($classes);
}
/**
- * @param Version[] $versions
+ * @internal DO NOT USE, THIS METHOD IS HERE ONLY TO EASE THE TESTING, WILL BE REMOVED IN UPCOMING MINOR/BUGFIX RELEASE
*/
- public function addVersions(array $versions) : void
+ public function registerMigrationInstance(Version $version, AbstractMigration $migration) : AvailableMigration
{
- foreach ($versions as $version) {
- $this->addVersion($version);
+ if (isset($this->migrations[(string) $version])) {
+ throw DuplicateMigrationVersion::new(
+ (string) $version,
+ (string) $version
+ );
}
- }
- public function removeMigrationVersionFromDatabase(string $version) : void
- {
- $this->connection->delete(
- $this->configuration->getMigrationsTableName(),
- [$this->configuration->getMigrationsColumnName() => $version]
- );
+ $this->migrations[(string) $version] = new AvailableMigration($version, $migration);
+
+ uasort($this->migrations, $this->sorter);
+
+ return $this->migrations[(string) $version];
}
/** @throws MigrationException */
- public function registerMigration(string $version, string $migrationClassName) : Version
+ public function registerMigration(string $migrationClassName) : AvailableMigration
{
$this->ensureMigrationClassExists($migrationClassName);
- if (isset($this->versions[$version])) {
- throw DuplicateMigrationVersion::new(
- $version,
- get_class($this->versions[$version])
- );
- }
-
- $version = $this->versionFactory->createVersion($version, $migrationClassName);
+ $version = new Version($migrationClassName);
+ $migration = $this->versionFactory->createVersion($migrationClassName);
- $this->addVersion($version);
-
- return $version;
+ return $this->registerMigrationInstance($version, $migration);
}
/**
* @param string[] $migrations
*
- * @return Version[]
+ * @return AvailableMigration[]
*/
- public function registerMigrations(array $migrations) : array
+ private function registerMigrations(array $migrations) : array
{
$versions = [];
- foreach ($migrations as $version => $class) {
- $versions[] = $this->registerMigration((string) $version, $class);
+ foreach ($migrations as $class) {
+ $versions[] = $this->registerMigration($class);
}
return $versions;
}
- public function getCurrentVersion() : string
- {
- $this->configuration->createMigrationTable();
-
- if (! $this->configuration->isMigrationTableCreated() && $this->configuration->isDryRun()) {
- return '0';
- }
-
- $this->configuration->connect();
-
- $this->loadMigrationsFromDirectory();
-
- $where = null;
-
- if (count($this->versions) !== 0) {
- $migratedVersions = [];
-
- foreach ($this->versions as $migration) {
- $migratedVersions[] = sprintf("'%s'", $migration->getVersion());
- }
-
- $where = sprintf(
- ' WHERE %s IN (%s)',
- $this->configuration->getQuotedMigrationsColumnName(),
- implode(', ', $migratedVersions)
- );
- }
-
- $sql = sprintf(
- 'SELECT %s FROM %s%s ORDER BY %s DESC',
- $this->configuration->getQuotedMigrationsColumnName(),
- $this->configuration->getMigrationsTableName(),
- $where,
- $this->configuration->getQuotedMigrationsColumnName()
- );
-
- $sql = $this->connection->getDatabasePlatform()->modifyLimitQuery($sql, 1);
- $result = $this->connection->fetchColumn($sql);
-
- return $result !== false ? (string) $result : '0';
- }
-
- /**
- * @return Version[]
- */
- public function getVersions() : array
+ public function hasMigration(string $version) : bool
{
- $this->loadMigrationsFromDirectory();
+ $this->loadMigrationsFromDirectories();
- return $this->versions;
+ return isset($this->migrations[$version]);
}
- public function clearVersions() : void
+ public function getMigration(Version $version) : AvailableMigration
{
- $this->versions = [];
- }
-
- public function getVersion(string $version) : Version
- {
- $this->loadMigrationsFromDirectory();
+ $this->loadMigrationsFromDirectories();
- if (! isset($this->versions[$version])) {
- throw UnknownMigrationVersion::new($version);
+ if (! isset($this->migrations[(string) $version])) {
+ throw MigrationClassNotFound::new((string) $version);
}
- return $this->versions[$version];
- }
-
- public function hasVersion(string $version) : bool
- {
- $this->loadMigrationsFromDirectory();
-
- return isset($this->versions[$version]);
- }
-
- public function hasVersionMigrated(Version $version) : bool
- {
- return $this->getVersionData($version) !== null;
+ return $this->migrations[(string) $version];
}
- /**
- * @return mixed[]|null
- */
- public function getVersionData(Version $version) : ?array
+ public function getMigrations() : AvailableMigrationsList
{
- $this->configuration->connect();
- $this->configuration->createMigrationTable();
-
- $sql = sprintf(
- 'SELECT %s, %s FROM %s WHERE %s = ?',
- $this->configuration->getQuotedMigrationsColumnName(),
- $this->configuration->getQuotedMigrationsExecutedAtColumnName(),
- $this->configuration->getMigrationsTableName(),
- $this->configuration->getQuotedMigrationsColumnName()
- );
+ $this->loadMigrationsFromDirectories();
- $data = $this->connection->fetchAssoc($sql, [$version->getVersion()]);
-
- return is_array($data) ? $data : null;
+ return new AvailableMigrationsList($this->migrations);
}
- /**
- * @return Version[]
- */
- public function getMigrations() : array
- {
- $this->loadMigrationsFromDirectory();
-
- return $this->versions;
- }
-
- /** @return string[] */
- public function getAvailableVersions() : array
- {
- $availableVersions = [];
-
- $this->loadMigrationsFromDirectory();
-
- foreach ($this->versions as $migration) {
- $availableVersions[] = $migration->getVersion();
- }
-
- return $availableVersions;
- }
-
- /** @return string[] */
- public function getNewVersions() : array
- {
- $availableMigrations = $this->getAvailableVersions();
- $executedMigrations = $this->getMigratedVersions();
-
- return array_diff($availableMigrations, $executedMigrations);
- }
-
- /** @return string[] */
- public function getMigratedVersions() : array
- {
- $this->configuration->createMigrationTable();
-
- if (! $this->configuration->isMigrationTableCreated() && $this->configuration->isDryRun()) {
- return [];
- }
-
- $this->configuration->connect();
-
- $sql = sprintf(
- 'SELECT %s FROM %s',
- $this->configuration->getQuotedMigrationsColumnName(),
- $this->configuration->getMigrationsTableName()
- );
-
- $result = $this->connection->fetchAll($sql);
-
- return array_map('current', $result);
- }
-
- /**
- * @return string[]
- */
- public function getExecutedUnavailableMigrations() : array
- {
- $executedMigrations = $this->getMigratedVersions();
- $availableMigrations = $this->getAvailableVersions();
-
- return array_diff($executedMigrations, $availableMigrations);
- }
-
- public function getNumberOfAvailableMigrations() : int
- {
- $this->loadMigrationsFromDirectory();
-
- return count($this->versions);
- }
-
- public function getLatestVersion() : string
- {
- $this->loadMigrationsFromDirectory();
-
- $versions = array_keys($this->versions);
- $latest = end($versions);
-
- return $latest !== false ? (string) $latest : '0';
- }
-
- public function getNumberOfExecutedMigrations() : int
- {
- $this->configuration->connect();
- $this->configuration->createMigrationTable();
-
- $sql = sprintf(
- 'SELECT COUNT(%s) FROM %s',
- $this->configuration->getQuotedMigrationsColumnName(),
- $this->configuration->getMigrationsTableName()
- );
-
- $result = $this->connection->fetchColumn($sql);
-
- return $result !== false ? (int) $result : 0;
- }
-
- public function getRelativeVersion(string $version, int $delta) : ?string
- {
- $this->loadMigrationsFromDirectory();
-
- $versions = array_map('strval', array_keys($this->versions));
-
- array_unshift($versions, '0');
-
- $offset = array_search($version, $versions, true);
-
- if ($offset === false) {
- return null;
- }
-
- $relativeVersion = ((int) $offset) + $delta;
-
- if (! isset($versions[$relativeVersion])) {
- // Unknown version or delta out of bounds.
- return null;
- }
-
- return $versions[$relativeVersion];
- }
-
- public function getDeltaVersion(string $delta) : ?string
+ /** @throws MigrationException */
+ private function ensureMigrationClassExists(string $class) : void
{
- $symbol = substr($delta, 0, 1);
- $number = (int) substr($delta, 1);
-
- if ($number <= 0) {
- return null;
- }
-
- if ($symbol === '+' || $symbol === '-') {
- return $this->getRelativeVersion($this->getCurrentVersion(), (int) $delta);
+ if (! class_exists($class)) {
+ throw MigrationClassNotFound::new($class);
}
-
- return null;
- }
-
- public function getPrevVersion() : ?string
- {
- return $this->getRelativeVersion($this->getCurrentVersion(), -1);
- }
-
- public function getNextVersion() : ?string
- {
- return $this->getRelativeVersion($this->getCurrentVersion(), 1);
}
- private function loadMigrationsFromDirectory() : void
+ private function loadMigrationsFromDirectories() : void
{
- $migrationsDirectory = $this->configuration->getMigrationsDirectory();
+ $migrationDirectories = $this->migrationDirectories;
- if (count($this->versions) !== 0 || $migrationsDirectory === null) {
+ if ($this->migrationsLoaded) {
return;
}
- $this->registerMigrationsFromDirectory($migrationsDirectory);
- }
+ $this->migrationsLoaded = true;
- /** @throws MigrationException */
- private function ensureMigrationClassExists(string $class) : void
- {
- if (! class_exists($class)) {
- throw MigrationClassNotFound::new(
- $class,
- $this->configuration->getMigrationsNamespace()
- );
+ foreach ($migrationDirectories as $namespace => $path) {
+ $migrations = $this->migrationFinder->findMigrations(
+ $path,
+ $namespace
+ );
+ $this->registerMigrations($migrations);
}
}
}
diff --git a/lib/Doctrine/Migrations/Migrator.php b/lib/Doctrine/Migrations/Migrator.php
index dfa5fad4ca..3b1d97a47e 100644
--- a/lib/Doctrine/Migrations/Migrator.php
+++ b/lib/Doctrine/Migrations/Migrator.php
@@ -4,252 +4,158 @@
namespace Doctrine\Migrations;
-use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Exception\MigrationException;
-use Doctrine\Migrations\Exception\NoMigrationsToExecute;
-use Doctrine\Migrations\Exception\UnknownMigrationVersion;
+use Doctrine\DBAL\Connection;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
use Doctrine\Migrations\Tools\BytesFormatter;
-use Doctrine\Migrations\Version\Direction;
-use Doctrine\Migrations\Version\Version;
+use Doctrine\Migrations\Version\ExecutorInterface;
+use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\StopwatchEvent;
use Throwable;
use const COUNT_RECURSIVE;
use function count;
-use function sprintf;
/**
* The Migrator class is responsible for generating and executing the SQL for a migration.
*
* @internal
*/
-class Migrator
+class Migrator implements MigratorInterface
{
- /** @var Configuration */
- private $configuration;
-
- /** @var MigrationRepository */
- private $migrationRepository;
-
- /** @var OutputWriter */
- private $outputWriter;
-
/** @var Stopwatch */
private $stopwatch;
- public function __construct(
- Configuration $configuration,
- MigrationRepository $migrationRepository,
- OutputWriter $outputWriter,
- Stopwatch $stopwatch
- ) {
- $this->configuration = $configuration;
- $this->migrationRepository = $migrationRepository;
- $this->outputWriter = $outputWriter;
- $this->stopwatch = $stopwatch;
- }
+ /** @var LoggerInterface */
+ private $logger;
- /** @return string[][] */
- public function getSql(?string $to = null) : array
- {
- $migratorConfiguration = (new MigratorConfiguration())
- ->setDryRun(true);
+ /** @var ExecutorInterface */
+ private $executor;
- return $this->migrate($to, $migratorConfiguration);
- }
+ /** @var Connection */
+ private $connection;
- public function writeSqlFile(string $path, ?string $to = null) : bool
- {
- $sql = $this->getSql($to);
+ /** @var EventDispatcher */
+ private $dispatcher;
- $from = $this->migrationRepository->getCurrentVersion();
-
- if ($to === null) {
- $to = $this->migrationRepository->getLatestVersion();
- }
-
- $direction = $from > $to
- ? Direction::DOWN
- : Direction::UP;
-
- $this->outputWriter->write(
- sprintf("-- Migrating from %s to %s\n", $from, $to)
- );
-
- /**
- * Since the configuration object changes during the creation we cannot inject things
- * properly, so I had to violate LoD here (so please, let's find a way to solve it on v2).
- */
- return $this->configuration
- ->getQueryWriter()
- ->write($path, $direction, $sql);
+ public function __construct(
+ Connection $connection,
+ EventDispatcher $dispatcher,
+ ExecutorInterface $executor,
+ LoggerInterface $logger,
+ Stopwatch $stopwatch
+ ) {
+ $this->stopwatch = $stopwatch;
+ $this->logger = $logger;
+ $this->executor = $executor;
+ $this->connection = $connection;
+ $this->dispatcher = $dispatcher;
}
/**
* @return string[][]
- *
- * @throws MigrationException
*/
- public function migrate(
- ?string $to = null,
- ?MigratorConfiguration $migratorConfiguration = null
+ private function executeMigrations(
+ MigrationPlanList $migrationsPlan,
+ MigratorConfiguration $migratorConfiguration
) : array {
- $migratorConfiguration = $migratorConfiguration ?? new MigratorConfiguration();
- $dryRun = $migratorConfiguration->isDryRun();
-
- if ($to === null) {
- $to = $this->migrationRepository->getLatestVersion();
- }
-
- $versions = $this->migrationRepository->getMigrations();
+ $allOrNothing = $migratorConfiguration->isAllOrNothing();
- if (! isset($versions[$to]) && $to > 0) {
- throw UnknownMigrationVersion::new($to);
+ if ($allOrNothing) {
+ $this->connection->beginTransaction();
}
- $from = $this->migrationRepository->getCurrentVersion();
-
- $direction = $this->calculateDirection($from, $to);
-
- $migrationsToExecute = $this->configuration
- ->getMigrationsToExecute($direction, $to);
-
- /**
- * If
- * there are no migrations to execute
- * and there are migrations,
- * and the migration from and to are the same
- * means we are already at the destination return an empty array()
- * to signify that there is nothing left to do.
- */
- if ($from === $to && count($migrationsToExecute) === 0 && count($versions) !== 0) {
- return $this->noMigrations();
- }
+ try {
+ $this->dispatcher->dispatchMigrationEvent(Events::onMigrationsMigrating, $migrationsPlan, $migratorConfiguration);
- $output = $dryRun ? 'Executing dry run of migration' : 'Migrating';
- $output .= ' %s to %s from %s';
+ $sql = $this->executePlan($migrationsPlan, $migratorConfiguration);
- $this->outputWriter->write(sprintf($output, $direction, $to, $from));
+ $this->dispatcher->dispatchMigrationEvent(Events::onMigrationsMigrated, $migrationsPlan, $migratorConfiguration);
+ } catch (Throwable $e) {
+ if ($allOrNothing) {
+ $this->connection->rollBack();
+ }
- /**
- * If there are no migrations to execute throw an exception.
- */
- if (count($migrationsToExecute) === 0 && ! $migratorConfiguration->getNoMigrationException()) {
- throw NoMigrationsToExecute::new();
+ throw $e;
}
- if (count($migrationsToExecute) === 0) {
- return $this->noMigrations();
+ if ($allOrNothing) {
+ $this->connection->commit();
}
- $stopwatchEvent = $this->stopwatch->start('migrate');
-
- $sql = $this->executeMigration($migrationsToExecute, $direction, $migratorConfiguration);
-
- $this->endMigration($stopwatchEvent, $migrationsToExecute, $sql);
-
return $sql;
}
/**
- * @param Version[] $migrationsToExecute
- *
- * @return string[][]
+ * @return array
*/
- private function executeMigration(
- array $migrationsToExecute,
- string $direction,
- MigratorConfiguration $migratorConfiguration
- ) : array {
- $dryRun = $migratorConfiguration->isDryRun();
-
- $connection = $this->configuration->getConnection();
-
- $allOrNothing = $migratorConfiguration->isAllOrNothing();
-
- if ($allOrNothing) {
- $connection->beginTransaction();
- }
-
- try {
- $this->configuration->dispatchMigrationEvent(Events::onMigrationsMigrating, $direction, $dryRun);
-
- $sql = [];
- $time = 0;
-
- foreach ($migrationsToExecute as $version) {
- $versionExecutionResult = $version->execute($direction, $migratorConfiguration);
-
- // capture the to Schema for the migration so we have the ability to use
- // it as the from Schema for the next migration when we are running a dry run
- // $toSchema may be null in the case of skipped migrations
- if (! $versionExecutionResult->isSkipped()) {
- $migratorConfiguration->setFromSchema($versionExecutionResult->getToSchema());
- }
+ private function executePlan(MigrationPlanList $migrationsPlan, MigratorConfiguration $migratorConfiguration) : array
+ {
+ $sql = [];
+ $time = 0;
- $sql[$version->getVersion()] = $versionExecutionResult->getSql();
- $time += $versionExecutionResult->getTime();
- }
+ foreach ($migrationsPlan->getItems() as $plan) {
+ $versionExecutionResult = $this->executor->execute($plan, $migratorConfiguration);
- $this->configuration->dispatchMigrationEvent(Events::onMigrationsMigrated, $direction, $dryRun);
- } catch (Throwable $e) {
- if ($allOrNothing) {
- $connection->rollBack();
+ // capture the to Schema for the migration so we have the ability to use
+ // it as the from Schema for the next migration when we are running a dry run
+ // $toSchema may be null in the case of skipped migrations
+ if (! $versionExecutionResult->isSkipped()) {
+ $migratorConfiguration->setFromSchema($versionExecutionResult->getToSchema());
}
- throw $e;
- }
-
- if ($allOrNothing) {
- $connection->commit();
+ $sql[(string) $plan->getVersion()] = $versionExecutionResult->getSql();
+ $time += $versionExecutionResult->getTime();
}
return $sql;
}
/**
- * @param Version[] $migrationsToExecute
* @param string[][] $sql
*/
- private function endMigration(
+ private function endMigrations(
StopwatchEvent $stopwatchEvent,
- array $migrationsToExecute,
+ MigrationPlanList $migrationsPlan,
array $sql
) : void {
$stopwatchEvent->stop();
- $this->outputWriter->write("\n ------------------------\n");
+ $this->logger->notice(
+ 'finished in {duration}ms, used {memory} memory, {migrations_count} migrations executed, {queries_count} sql queries',
+ [
+ 'duration' => $stopwatchEvent->getDuration(),
+ 'memory' => BytesFormatter::formatBytes($stopwatchEvent->getMemory()),
+ 'migrations_count' => count($migrationsPlan),
+ 'queries_count' => count($sql, COUNT_RECURSIVE) - count($sql),
+ ]
+ );
+ }
- $this->outputWriter->write(sprintf(
- ' ++ finished in %sms',
- $stopwatchEvent->getDuration()
- ));
+ /**
+ * {@inheritDoc}
+ */
+ public function migrate(MigrationPlanList $migrationsPlan, MigratorConfiguration $migratorConfiguration) : array
+ {
+ if (count($migrationsPlan) === 0) {
+ $this->logger->notice('No migrations to execute.');
- $this->outputWriter->write(sprintf(
- ' ++ used %s memory',
- BytesFormatter::formatBytes($stopwatchEvent->getMemory())
- ));
+ return [];
+ }
- $this->outputWriter->write(sprintf(
- ' ++ %s migrations executed',
- count($migrationsToExecute)
- ));
+ $dryRun = $migratorConfiguration->isDryRun();
+ $this->logger->notice(
+ ($dryRun ? 'Executing dry run of migration' : 'Migrating') . ' {direction} to {to}',
+ [
+ 'direction' => $migrationsPlan->getDirection(),
+ 'to' => (string) $migrationsPlan->getLast()->getVersion(),
+ ]
+ );
- $this->outputWriter->write(sprintf(
- ' ++ %s sql queries',
- count($sql, COUNT_RECURSIVE) - count($sql)
- ));
- }
+ $stopwatchEvent = $this->stopwatch->start('migrate');
- private function calculateDirection(string $from, string $to) : string
- {
- return (int) $from > (int) $to ? Direction::DOWN : Direction::UP;
- }
+ $sql = $this->executeMigrations($migrationsPlan, $migratorConfiguration);
- /** @return string[][] */
- private function noMigrations() : array
- {
- $this->outputWriter->write('No migrations to execute.');
+ $this->endMigrations($stopwatchEvent, $migrationsPlan, $sql);
- return [];
+ return $sql;
}
}
diff --git a/lib/Doctrine/Migrations/MigratorInterface.php b/lib/Doctrine/Migrations/MigratorInterface.php
new file mode 100644
index 0000000000..066f12445a
--- /dev/null
+++ b/lib/Doctrine/Migrations/MigratorInterface.php
@@ -0,0 +1,20 @@
+ A list of SQL statements executed, grouped by migration version
+ */
+ public function migrate(MigrationPlanList $migrationsPlan, MigratorConfiguration $migratorConfiguration) : array;
+}
diff --git a/lib/Doctrine/Migrations/OutputWriter.php b/lib/Doctrine/Migrations/OutputWriter.php
deleted file mode 100644
index ebb04adfb0..0000000000
--- a/lib/Doctrine/Migrations/OutputWriter.php
+++ /dev/null
@@ -1,43 +0,0 @@
-lastMessage = $message;
- };
- }
-
- $this->callback = $callback;
- }
-
- public function setCallback(callable $callback) : void
- {
- $this->callback = $callback;
- }
-
- public function write(string $message) : void
- {
- ($this->callback)($message);
- }
-
- public function getLastMessage() : string
- {
- return $this->lastMessage;
- }
-}
diff --git a/lib/Doctrine/Migrations/Provider/DBALSchemaDiffProvider.php b/lib/Doctrine/Migrations/Provider/DBALSchemaDiffProvider.php
new file mode 100644
index 0000000000..6515149030
--- /dev/null
+++ b/lib/Doctrine/Migrations/Provider/DBALSchemaDiffProvider.php
@@ -0,0 +1,50 @@
+schemaManager = $schemaManager;
+ $this->platform = $platform;
+ }
+
+ public function createFromSchema() : Schema
+ {
+ return $this->schemaManager->createSchema();
+ }
+
+ public function createToSchema(Schema $fromSchema) : Schema
+ {
+ return clone $fromSchema;
+ }
+
+ /** @return string[] */
+ public function getSqlDiffToMigrate(Schema $fromSchema, Schema $toSchema) : array
+ {
+ return $fromSchema->getMigrateToSql($toSchema, $this->platform);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Provider/LazySchemaDiffProvider.php b/lib/Doctrine/Migrations/Provider/LazySchemaDiffProvider.php
index e6f96b6a46..0d0df44c95 100644
--- a/lib/Doctrine/Migrations/Provider/LazySchemaDiffProvider.php
+++ b/lib/Doctrine/Migrations/Provider/LazySchemaDiffProvider.php
@@ -16,24 +16,24 @@
*
* @internal
*/
-class LazySchemaDiffProvider implements SchemaDiffProviderInterface
+class LazySchemaDiffProvider implements SchemaDiffProvider
{
/** @var LazyLoadingValueHolderFactory */
private $proxyFactory;
- /** @var SchemaDiffProviderInterface */
+ /** @var SchemaDiffProvider */
private $originalSchemaManipulator;
public function __construct(
LazyLoadingValueHolderFactory $proxyFactory,
- SchemaDiffProviderInterface $originalSchemaManipulator
+ SchemaDiffProvider $originalSchemaManipulator
) {
$this->proxyFactory = $proxyFactory;
$this->originalSchemaManipulator = $originalSchemaManipulator;
}
public static function fromDefaultProxyFactoryConfiguration(
- SchemaDiffProviderInterface $originalSchemaManipulator
+ SchemaDiffProvider $originalSchemaManipulator
) : LazySchemaDiffProvider {
$proxyConfig = new Configuration();
$proxyConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
@@ -65,7 +65,7 @@ public function createToSchema(Schema $fromSchema) : Schema
if ($fromSchema instanceof LazyLoadingInterface && ! $fromSchema->isProxyInitialized()) {
return $this->proxyFactory->createProxy(
Schema::class,
- static function (& $wrappedObject, $proxy, $method, array $parameters, & $initializer) use ($originalSchemaManipulator, $fromSchema) {
+ static function (&$wrappedObject, $proxy, $method, array $parameters, &$initializer) use ($originalSchemaManipulator, $fromSchema) {
$initializer = null;
$wrappedObject = $originalSchemaManipulator->createToSchema($fromSchema);
diff --git a/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php b/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php
index 1becea14cf..d3ddff0eea 100644
--- a/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php
+++ b/lib/Doctrine/Migrations/Provider/OrmSchemaProvider.php
@@ -17,7 +17,7 @@
*
* @internal
*/
-final class OrmSchemaProvider implements SchemaProviderInterface
+final class OrmSchemaProvider implements SchemaProvider
{
/** @var EntityManagerInterface */
private $entityManager;
diff --git a/lib/Doctrine/Migrations/Provider/SchemaDiffProvider.php b/lib/Doctrine/Migrations/Provider/SchemaDiffProvider.php
index d97870acfe..364046d62c 100644
--- a/lib/Doctrine/Migrations/Provider/SchemaDiffProvider.php
+++ b/lib/Doctrine/Migrations/Provider/SchemaDiffProvider.php
@@ -4,47 +4,20 @@
namespace Doctrine\Migrations\Provider;
-use Doctrine\DBAL\Platforms\AbstractPlatform;
-use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Schema;
/**
- * The SchemaDiffProvider class is responsible for providing a Doctrine\DBAL\Schema\Schema instance that
- * represents the current state of your database. A clone of this Schema instance is passed to each of your migrations
- * so that you can manipulate the Schema object. Your manipulated Schema object is then compared to the original Schema
- * object to produce the SQL statements that need to be executed.
+ * The SchemaDiffProvider defines the interface used to provide the from and to schemas and to produce
+ * the SQL queries needed to migrate.
*
* @internal
- *
- * @see Doctrine\Migrations\Version\Executor
*/
-class SchemaDiffProvider implements SchemaDiffProviderInterface
+interface SchemaDiffProvider
{
- /** @var AbstractPlatform */
- private $platform;
-
- /** @var AbstractSchemaManager */
- private $schemaManager;
-
- public function __construct(AbstractSchemaManager $schemaManager, AbstractPlatform $platform)
- {
- $this->schemaManager = $schemaManager;
- $this->platform = $platform;
- }
-
- public function createFromSchema() : Schema
- {
- return $this->schemaManager->createSchema();
- }
+ public function createFromSchema() : Schema;
- public function createToSchema(Schema $fromSchema) : Schema
- {
- return clone $fromSchema;
- }
+ public function createToSchema(Schema $fromSchema) : Schema;
/** @return string[] */
- public function getSqlDiffToMigrate(Schema $fromSchema, Schema $toSchema) : array
- {
- return $fromSchema->getMigrateToSql($toSchema, $this->platform);
- }
+ public function getSqlDiffToMigrate(Schema $fromSchema, Schema $toSchema) : array;
}
diff --git a/lib/Doctrine/Migrations/Provider/SchemaDiffProviderInterface.php b/lib/Doctrine/Migrations/Provider/SchemaDiffProviderInterface.php
deleted file mode 100644
index e0666cd211..0000000000
--- a/lib/Doctrine/Migrations/Provider/SchemaDiffProviderInterface.php
+++ /dev/null
@@ -1,23 +0,0 @@
-configuration = $configuration;
- $this->connection = $connection;
$this->migrationRepository = $migrationRepository;
+ $this->metadataStorage = $metadataStorage;
}
/**
@@ -46,7 +37,7 @@ public function __construct(
*/
public function rollup() : Version
{
- $versions = $this->migrationRepository->getVersions();
+ $versions = $this->migrationRepository->getMigrations();
if (count($versions) === 0) {
throw RollupFailed::noMigrationsFound();
@@ -56,17 +47,11 @@ public function rollup() : Version
throw RollupFailed::tooManyMigrations();
}
- $sql = sprintf(
- 'DELETE FROM %s',
- $this->configuration->getMigrationsTableName()
- );
-
- $this->connection->executeQuery($sql);
-
- $version = current($versions);
+ $this->metadataStorage->reset();
- $version->markMigrated();
+ $result = new ExecutionResult($versions->getFirst()->getVersion());
+ $this->metadataStorage->complete($result);
- return $version;
+ return $result->getVersion();
}
}
diff --git a/lib/Doctrine/Migrations/SchemaDumper.php b/lib/Doctrine/Migrations/SchemaDumper.php
index b8298227df..7c6e19bd0b 100644
--- a/lib/Doctrine/Migrations/SchemaDumper.php
+++ b/lib/Doctrine/Migrations/SchemaDumper.php
@@ -6,11 +6,24 @@
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
+use Doctrine\DBAL\Schema\Table;
use Doctrine\Migrations\Exception\NoTablesFound;
use Doctrine\Migrations\Generator\Generator;
use Doctrine\Migrations\Generator\SqlGenerator;
+use InvalidArgumentException;
+use const PREG_BACKTRACK_LIMIT_ERROR;
+use const PREG_BAD_UTF8_ERROR;
+use const PREG_BAD_UTF8_OFFSET_ERROR;
+use const PREG_INTERNAL_ERROR;
+use const PREG_RECURSION_LIMIT_ERROR;
+use function array_merge;
use function count;
use function implode;
+use function preg_last_error;
+use function preg_match;
+use function restore_error_handler;
+use function set_error_handler;
+use function sprintf;
/**
* The SchemaDumper class is responsible for dumping the current state of your database schema to a migration. This
@@ -34,25 +47,37 @@ class SchemaDumper
/** @var SqlGenerator */
private $migrationSqlGenerator;
+ /** @var string[] */
+ private $excludedTablesRegexes;
+
+ /**
+ * @param string[] $excludedTablesRegexes
+ */
public function __construct(
AbstractPlatform $platform,
AbstractSchemaManager $schemaManager,
Generator $migrationGenerator,
- SqlGenerator $migrationSqlGenerator
+ SqlGenerator $migrationSqlGenerator,
+ array $excludedTablesRegexes = []
) {
$this->platform = $platform;
$this->schemaManager = $schemaManager;
$this->migrationGenerator = $migrationGenerator;
$this->migrationSqlGenerator = $migrationSqlGenerator;
+ $this->excludedTablesRegexes = $excludedTablesRegexes;
}
/**
+ * @param string[] $excludedTablesRegexes
+ *
* @throws NoTablesFound
*/
public function dump(
- string $versionNumber,
+ string $fqcn,
+ array $excludedTablesRegexes = [],
bool $formatted = false,
- int $lineLength = 120
+ int $lineLength = 120,
+ bool $includeDownMigration = false
) : string {
$schema = $this->schemaManager->createSchema();
@@ -60,6 +85,10 @@ public function dump(
$down = [];
foreach ($schema->getTables() as $table) {
+ if ($this->shouldSkipTable($table, $excludedTablesRegexes)) {
+ continue;
+ }
+
$upSql = $this->platform->getCreateTableSQL($table);
$upCode = $this->migrationSqlGenerator->generate(
@@ -72,6 +101,9 @@ public function dump(
$up[] = $upCode;
}
+ if (! $includeDownMigration) {
+ continue;
+ }
$downSql = [$this->platform->getDropTableSQL($table)];
$downCode = $this->migrationSqlGenerator->generate(
@@ -91,13 +123,77 @@ public function dump(
throw NoTablesFound::new();
}
- $up = implode("\n", $up);
- $down = implode("\n", $down);
+ $up = implode("\n", $up);
return $this->migrationGenerator->generateMigration(
- $versionNumber,
+ $fqcn,
$up,
- $down
+ null,
+ null,
+ $includeDownMigration ? null : ''
);
}
+
+ /**
+ * @param string[] $excludedTablesRegexes
+ */
+ private function shouldSkipTable(Table $table, array $excludedTablesRegexes) : bool
+ {
+ foreach (array_merge($excludedTablesRegexes, $this->excludedTablesRegexes) as $regex) {
+ if (self::pregMatch($regex, $table->getName()) !== 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * A local wrapper for "preg_match" which will throw a InvalidArgumentException if there
+ * is an internal error in the PCRE engine.
+ * Copied from https://github.com/symfony/symfony/blob/62216ea67762b18982ca3db73c391b0748a49d49/src/Symfony/Component/Yaml/Parser.php#L1072-L1090
+ *
+ * @internal
+ *
+ * @param mixed[] $matches
+ */
+ private static function pregMatch(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0) : int
+ {
+ try {
+ $errorMessages = [];
+ set_error_handler(static function (int $severity, string $message, string $file, int $line, array $params) use (&$errorMessages) : bool {
+ $errorMessages[] = $message;
+
+ return true;
+ });
+ $ret = preg_match($pattern, $subject, $matches, $flags, $offset);
+ } finally {
+ restore_error_handler();
+ }
+
+ if ($ret === false) {
+ switch (preg_last_error()) {
+ case PREG_INTERNAL_ERROR:
+ $error = sprintf('Internal PCRE error, please check your Regex. Reported errors: %s.', implode(', ', $errorMessages));
+ break;
+ case PREG_BACKTRACK_LIMIT_ERROR:
+ $error = 'pcre.backtrack_limit reached.';
+ break;
+ case PREG_RECURSION_LIMIT_ERROR:
+ $error = 'pcre.recursion_limit reached.';
+ break;
+ case PREG_BAD_UTF8_ERROR:
+ $error = 'Malformed UTF-8 data.';
+ break;
+ case PREG_BAD_UTF8_OFFSET_ERROR:
+ $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.';
+ break;
+ default:
+ $error = 'Error.';
+ }
+ throw new InvalidArgumentException($error);
+ }
+
+ return $ret;
+ }
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/AbstractCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/AbstractCommand.php
index a42ab0fad5..d66aa6754f 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/AbstractCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/AbstractCommand.php
@@ -4,13 +4,13 @@
namespace Doctrine\Migrations\Tools\Console\Command;
-use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\DependencyFactory;
-use Doctrine\Migrations\MigrationRepository;
use Doctrine\Migrations\Tools\Console\ConnectionLoader;
+use Doctrine\Migrations\Tools\Console\ConsoleLogger;
+use Doctrine\Migrations\Tools\Console\Exception\DependenciesNotSatisfied;
use Doctrine\Migrations\Tools\Console\Helper\ConfigurationHelper;
use Doctrine\Migrations\Tools\Console\Helper\ConfigurationHelperInterface;
+use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputInterface;
@@ -18,6 +18,7 @@
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use function escapeshellarg;
+use function is_string;
use function proc_open;
use function str_repeat;
use function strlen;
@@ -27,53 +28,21 @@
*/
abstract class AbstractCommand extends Command
{
- /** @var Configuration */
- protected $configuration;
-
- /** @var Connection */
- protected $connection;
-
- /** @var DependencyFactory */
- protected $dependencyFactory;
-
- /** @var MigrationRepository */
- protected $migrationRepository;
-
- /** @var Configuration|null */
- protected $migrationConfiguration;
-
- public function setMigrationConfiguration(Configuration $configuration) : void
- {
- $this->configuration = $configuration;
-
- $this->initializeDependencies();
- }
-
- public function setConnection(Connection $connection) : void
- {
- $this->connection = $connection;
- }
-
- public function setDependencyFactory(DependencyFactory $dependencyFactory) : void
- {
- $this->dependencyFactory = $dependencyFactory;
- }
-
- public function setMigrationRepository(MigrationRepository $migrationRepository) : void
- {
- $this->migrationRepository = $migrationRepository;
- }
+ /** @var DependencyFactory|null */
+ private $dependencyFactory;
public function initialize(
InputInterface $input,
OutputInterface $output
) : void {
- $this->configuration = $this->getMigrationConfiguration($input, $output);
-
- $this->initializeDependencies();
+ $this->initializeDependencies($input, $output);
+ $this->getDependencyFactory()->getConfiguration()->validate();
+ }
- $this->configuration->validate();
- $this->configuration->createMigrationTable();
+ public function __construct(?string $name = null, ?DependencyFactory $dependencyFactory = null)
+ {
+ parent::__construct($name);
+ $this->dependencyFactory = $dependencyFactory;
}
protected function configure() : void
@@ -91,12 +60,19 @@ protected function configure() : void
InputOption::VALUE_OPTIONAL,
'The path to a database connection configuration file.'
);
+
+ $this->addOption(
+ 'shard',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'The shard connection to use for this command.'
+ );
}
protected function outputHeader(
OutputInterface $output
) : void {
- $name = $this->configuration->getName();
+ $name = $this->getDependencyFactory()->getConfiguration()->getName();
$name = $name ?? 'Doctrine Database Migrations';
$name = str_repeat(' ', 20) . $name . str_repeat(' ', 20);
$output->writeln('' . str_repeat(' ', strlen($name)) . '');
@@ -105,35 +81,54 @@ protected function outputHeader(
$output->writeln('');
}
- protected function getMigrationConfiguration(
+ private function enusreLogger(OutputInterface $output, DependencyFactory $dependencyFactory) : void
+ {
+ $logger = new ConsoleLogger($output);
+ $dependencyFactory->setLogger($logger);
+ }
+
+ protected function initializeDependencies(
InputInterface $input,
OutputInterface $output
- ) : Configuration {
- if ($this->migrationConfiguration === null) {
- if ($this->hasConfigurationHelper()) {
- /** @var ConfigurationHelper $configHelper */
- $configHelper = $this->getHelperSet()->get('configuration');
- } else {
- $configHelper = new ConfigurationHelper(
- $this->getConnection($input),
- $this->configuration
- );
- }
-
- $this->migrationConfiguration = $configHelper->getMigrationConfig($input);
-
- $this->migrationConfiguration->getOutputWriter()->setCallback(
- static function (string $message) use ($output) : void {
- $output->writeln($message);
- }
- );
+ ) : void {
+ if ($this->dependencyFactory !== null) {
+ $this->enusreLogger($output, $this->dependencyFactory);
+
+ return;
+ }
+ $helperSet = $this->getHelperSet() ?: new HelperSet();
+
+ if ($helperSet->has('configuration') && $helperSet->get('configuration') instanceof ConfigurationHelperInterface) {
+ /** @var ConfigurationHelper $configHelper */
+ $configHelper = $helperSet->get('configuration');
+ } else {
+ $configHelper = new ConfigurationHelper();
+ }
+
+ $configuration = $configHelper->getConfiguration($input);
+
+ $dbConfig = is_string($input->getOption('db-configuration')) ? $input->getOption('db-configuration'): null;
+ $shardId = is_string($input->getOption('shard')) ? $input->getOption('shard'): null;
+
+ $connection = (new ConnectionLoader())
+ ->getConnection($dbConfig, $shardId, $helperSet);
+
+ $em = null;
+ if ($helperSet->has('em') && $helperSet->get('em') instanceof EntityManagerHelper) {
+ $em = $helperSet->get('em')->getEntityManager();
}
- if ($this->migrationConfiguration === null && $this->configuration !== null) {
- $this->migrationConfiguration = $this->configuration;
+ $this->dependencyFactory = new DependencyFactory($configuration, $connection, $em);
+ $this->enusreLogger($output, $this->dependencyFactory);
+ }
+
+ protected function getDependencyFactory() : DependencyFactory
+ {
+ if ($this->dependencyFactory === null) {
+ throw DependenciesNotSatisfied::new();
}
- return $this->migrationConfiguration;
+ return $this->dependencyFactory;
}
protected function askConfirmation(
@@ -160,37 +155,4 @@ protected function procOpen(string $editorCommand, string $path) : void
{
proc_open($editorCommand . ' ' . escapeshellarg($path), [], $pipes);
}
-
- private function initializeDependencies() : void
- {
- $this->connection = $this->configuration->getConnection();
- $this->dependencyFactory = $this->configuration->getDependencyFactory();
- $this->migrationRepository = $this->dependencyFactory->getMigrationRepository();
- }
-
- private function hasConfigurationHelper() : bool
- {
- /** @var HelperSet|null $helperSet */
- $helperSet = $this->getHelperSet();
-
- if ($helperSet === null) {
- return false;
- }
-
- if (! $helperSet->has('configuration')) {
- return false;
- }
-
- return $helperSet->get('configuration') instanceof ConfigurationHelperInterface;
- }
-
- private function getConnection(InputInterface $input) : Connection
- {
- if ($this->connection === null) {
- $this->connection = (new ConnectionLoader($this->configuration))
- ->getConnection($input, $this->getHelperSet());
- }
-
- return $this->connection;
- }
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php
index 2c6b002faf..b3e6a6baa1 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/DiffCommand.php
@@ -4,17 +4,19 @@
namespace Doctrine\Migrations\Tools\Console\Command;
-use Doctrine\Migrations\Generator\DiffGenerator;
use Doctrine\Migrations\Generator\Exception\NoChangesDetected;
-use Doctrine\Migrations\Provider\OrmSchemaProvider;
-use Doctrine\Migrations\Provider\SchemaProviderInterface;
use Doctrine\Migrations\Tools\Console\Exception\InvalidOptionUsage;
+use OutOfBoundsException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use const FILTER_VALIDATE_BOOLEAN;
+use function addslashes;
+use function assert;
use function class_exists;
use function filter_var;
+use function is_string;
+use function key;
use function sprintf;
/**
@@ -26,16 +28,6 @@ class DiffCommand extends AbstractCommand
/** @var string */
protected static $defaultName = 'migrations:diff';
- /** @var SchemaProviderInterface|null */
- protected $schemaProvider;
-
- public function __construct(?SchemaProviderInterface $schemaProvider = null)
- {
- $this->schemaProvider = $schemaProvider;
-
- parent::__construct();
- }
-
protected function configure() : void
{
parent::configure();
@@ -53,16 +45,22 @@ protected function configure() : void
%command.full_name% --editor-cmd=mate
EOT
)
+ ->addOption(
+ 'namespace',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'The namespace to use for the migration (must be in the list of configured namespaces)'
+ )
->addOption(
'editor-cmd',
null,
- InputOption::VALUE_OPTIONAL,
+ InputOption::VALUE_REQUIRED,
'Open file with this command upon creation.'
)
->addOption(
'filter-expression',
null,
- InputOption::VALUE_OPTIONAL,
+ InputOption::VALUE_REQUIRED,
'Tables which are filtered by Regular Expression.'
)
->addOption(
@@ -74,7 +72,7 @@ protected function configure() : void
->addOption(
'line-length',
null,
- InputOption::VALUE_OPTIONAL,
+ InputOption::VALUE_REQUIRED,
'Max line length of unformatted lines.',
120
)
@@ -83,7 +81,7 @@ protected function configure() : void
null,
InputOption::VALUE_OPTIONAL,
'Check Database Platform to the generated code.',
- true
+ false
)
->addOption(
'allow-empty-diff',
@@ -100,12 +98,12 @@ public function execute(
InputInterface $input,
OutputInterface $output
) : ?int {
- $filterExpression = $input->getOption('filter-expression') ?? null;
- $formatted = (bool) $input->getOption('formatted');
+ $filterExpression = (string) $input->getOption('filter-expression') ?: null;
+ $formatted = filter_var($input->getOption('formatted'), FILTER_VALIDATE_BOOLEAN);
$lineLength = (int) $input->getOption('line-length');
- $allowEmptyDiff = (bool) $input->getOption('allow-empty-diff');
+ $allowEmptyDiff = $input->getOption('allow-empty-diff');
$checkDbPlatform = filter_var($input->getOption('check-database-platform'), FILTER_VALIDATE_BOOLEAN);
-
+ $namespace = $input->getOption('namespace') ?: null;
if ($formatted) {
if (! class_exists('SqlFormatter')) {
throw InvalidOptionUsage::new(
@@ -114,11 +112,23 @@ public function execute(
}
}
- $versionNumber = $this->configuration->generateVersionNumber();
+ $configuration = $this->getDependencyFactory()->getConfiguration();
+
+ $dirs = $configuration->getMigrationDirectories();
+ if ($namespace === null) {
+ $namespace = key($dirs);
+ } elseif (! isset($dirs[$namespace])) {
+ throw new OutOfBoundsException(sprintf('Path not defined for the namespace %s', $namespace));
+ }
+ assert(is_string($namespace));
+
+ $fqcn = $this->getDependencyFactory()->getClassNameGenerator()->generateClassName($namespace);
+
+ $diffGenerator = $this->getDependencyFactory()->getDiffGenerator();
try {
- $path = $this->createMigrationDiffGenerator()->generate(
- $versionNumber,
+ $path = $diffGenerator->generate(
+ $fqcn,
$filterExpression,
$formatted,
$lineLength,
@@ -136,6 +146,7 @@ public function execute(
$editorCommand = $input->getOption('editor-cmd');
if ($editorCommand !== null) {
+ assert(is_string($editorCommand));
$this->procOpen($editorCommand, $path);
}
@@ -143,39 +154,16 @@ public function execute(
sprintf('Generated new migration class to "%s"', $path),
'',
sprintf(
- 'To run just this migration for testing purposes, you can use migrations:execute --up %s',
- $versionNumber
+ 'To run just this migration for testing purposes, you can use migrations:execute --up \'%s\'',
+ addslashes($fqcn)
),
'',
sprintf(
- 'To revert the migration you can use migrations:execute --down %s',
- $versionNumber
+ 'To revert the migration you can use migrations:execute --down \'%s\'',
+ addslashes($fqcn)
),
]);
return 0;
}
-
- protected function createMigrationDiffGenerator() : DiffGenerator
- {
- return new DiffGenerator(
- $this->connection->getConfiguration(),
- $this->connection->getSchemaManager(),
- $this->getSchemaProvider(),
- $this->connection->getDatabasePlatform(),
- $this->dependencyFactory->getMigrationGenerator(),
- $this->dependencyFactory->getMigrationSqlGenerator()
- );
- }
-
- private function getSchemaProvider() : SchemaProviderInterface
- {
- if ($this->schemaProvider === null) {
- $this->schemaProvider = new OrmSchemaProvider(
- $this->getHelper('entityManager')->getEntityManager()
- );
- }
-
- return $this->schemaProvider;
- }
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php
index c1bb788742..0cc7cd880e 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/DumpSchemaCommand.php
@@ -9,9 +9,13 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use function addslashes;
+use function assert;
use function class_exists;
-use function count;
+use function is_string;
+use function key;
use function sprintf;
+use function strpos;
/**
* The DumpSchemaCommand class is responsible for dumping your current database schema to a migration class. This is
@@ -51,12 +55,30 @@ protected function configure() : void
InputOption::VALUE_NONE,
'Format the generated SQL.'
)
+ ->addOption(
+ 'namespace',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'Namespace to use for the generated migrations (defaults to the first namespace definition).'
+ )
+ ->addOption(
+ 'filter-tables',
+ null,
+ InputOption::VALUE_REQUIRED|InputOption::VALUE_IS_ARRAY,
+ 'Filter the tables to dump via Regex.'
+ )
->addOption(
'line-length',
null,
InputOption::VALUE_OPTIONAL,
'Max line length of unformatted lines.',
120
+ )
+ ->addOption(
+ 'with-down-migration',
+ null,
+ InputOption::VALUE_NONE,
+ 'Generate down() migrations.'
);
}
@@ -67,15 +89,11 @@ public function execute(
InputInterface $input,
OutputInterface $output
) : ?int {
- $formatted = (bool) $input->getOption('formatted');
- $lineLength = (int) $input->getOption('line-length');
+ $formatted = $input->getOption('formatted');
+ $lineLength = (int) $input->getOption('line-length');
+ $includeDownMigration = $input->getOption('with-down-migration');
- $schemaDumper = $this->dependencyFactory->getSchemaDumper();
- $versions = $this->migrationRepository->getVersions();
-
- if (count($versions) > 0) {
- throw SchemaDumpRequiresNoMigrations::new();
- }
+ $schemaDumper = $this->getDependencyFactory()->getSchemaDumper();
if ($formatted) {
if (! class_exists('SqlFormatter')) {
@@ -85,17 +103,31 @@ public function execute(
}
}
- $versionNumber = $this->configuration->generateVersionNumber();
+ $configuration = $this->getDependencyFactory()->getConfiguration();
+
+ $namespace = $input->getOption('namespace');
+ if ($namespace === null) {
+ $dirs = $configuration->getMigrationDirectories();
+ $namespace = key($dirs);
+ }
+ assert(is_string($namespace));
+
+ $this->checkNotTooManyMigrations($namespace);
+
+ $fqcn = $this->getDependencyFactory()->getClassNameGenerator()->generateClassName($namespace);
$path = $schemaDumper->dump(
- $versionNumber,
+ $fqcn,
+ $input->getOption('filter-tables'),
$formatted,
- $lineLength
+ $lineLength,
+ $includeDownMigration === true
);
$editorCommand = $input->getOption('editor-cmd');
if ($editorCommand !== null) {
+ assert(is_string($editorCommand));
$this->procOpen($editorCommand, $path);
}
@@ -103,13 +135,13 @@ public function execute(
sprintf('Dumped your schema to a new migration class at "%s"', $path),
'',
sprintf(
- 'To run just this migration for testing purposes, you can use migrations:execute --up %s',
- $versionNumber
+ 'To run just this migration for testing purposes, you can use migrations:execute --up \'%s\'',
+ addslashes($fqcn)
),
'',
sprintf(
- 'To revert the migration you can use migrations:execute --down %s',
- $versionNumber
+ 'To revert the migration you can use migrations:execute --down \'%s\'',
+ addslashes($fqcn)
),
'',
'To use this as a rollup migration you can use the migrations:rollup command.',
@@ -117,4 +149,14 @@ public function execute(
return 0;
}
+
+ private function checkNotTooManyMigrations(string $namespace) : void
+ {
+ $versions = $this->getDependencyFactory()->getMigrationRepository()->getMigrations();
+ foreach ($versions->getItems() as $migration) {
+ if (strpos((string) $migration->getVersion(), $namespace) !== false) {
+ throw SchemaDumpRequiresNoMigrations::new($namespace);
+ }
+ }
+ }
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php
index dd7680735f..e0efa81f10 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php
@@ -4,13 +4,15 @@
namespace Doctrine\Migrations\Tools\Console\Command;
-use Doctrine\Migrations\MigratorConfiguration;
use Doctrine\Migrations\Version\Direction;
+use Doctrine\Migrations\Version\Version;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use function getcwd;
+use function is_string;
+use function is_writable;
/**
* The ExecutCommand class is responsible for executing a single migration version up or down.
@@ -92,37 +94,45 @@ protected function configure() : void
public function execute(InputInterface $input, OutputInterface $output) : ?int
{
- $version = $input->getArgument('version');
- $timeAllQueries = (bool) $input->getOption('query-time');
- $dryRun = (bool) $input->getOption('dry-run');
- $path = $input->getOption('write-sql');
- $direction = $input->getOption('down') !== false
+ $version = $input->getArgument('version');
+ $path = $input->getOption('write-sql');
+ $direction = $input->getOption('down') !== false
? Direction::DOWN
: Direction::UP;
- $version = $this->migrationRepository->getVersion($version);
+ $migrator = $this->getDependencyFactory()->getMigrator();
+ $plan = $this->getDependencyFactory()->getMigrationPlanCalculator()->getPlanForExactVersion(new Version($version), $direction);
+
+ $migratorConfigurationFactory = $this->getDependencyFactory()->getConsoleInputMigratorConfigurationFactory();
+ $migratorConfiguration = $migratorConfigurationFactory->getMigratorConfiguration($input);
if ($path !== false) {
- $path = $path ?? getcwd();
+ $migratorConfiguration->setDryRun(true);
+ $sql = $migrator->migrate($plan, $migratorConfiguration);
+
+ $path = is_string($path) ? $path : getcwd();
+
+ if (! is_string($path) || ! is_writable($path)) {
+ $output->writeln('Path not writeable!');
- $version->writeSqlFile($path, $direction);
+ return 1;
+ }
+
+ $writer = $this->getDependencyFactory()->getQueryWriter();
+ $writer->write($path, $direction, $sql);
return 0;
}
$question = 'WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)';
- if (! $dryRun && ! $this->canExecute($question, $input, $output)) {
+ if (! $migratorConfiguration->isDryRun() && ! $this->canExecute($question, $input, $output)) {
$output->writeln('Migration cancelled!');
return 1;
}
- $migratorConfiguration = (new MigratorConfiguration())
- ->setDryRun($dryRun)
- ->setTimeAllQueries($timeAllQueries);
-
- $version->execute($direction, $migratorConfiguration);
+ $migrator->migrate($plan, $migratorConfiguration);
return 0;
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/GenerateCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/GenerateCommand.php
index 18a696c4f6..2c905dad81 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/GenerateCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/GenerateCommand.php
@@ -4,9 +4,13 @@
namespace Doctrine\Migrations\Tools\Console\Command;
+use Exception;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use function assert;
+use function is_string;
+use function key;
use function sprintf;
/**
@@ -28,6 +32,18 @@ protected function configure() : void
InputOption::VALUE_OPTIONAL,
'Open file with this command upon creation.'
)
+ ->addOption(
+ 'namespace',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'The namespace to use for the migration (must be in the list of configured namespaces)'
+ )
+ ->addOption(
+ 'with-down-migration',
+ null,
+ InputOption::VALUE_NONE,
+ 'Generate down() migrations.'
+ )
->setHelp(<<%command.name% command generates a blank migration class:
@@ -37,22 +53,42 @@ protected function configure() : void
%command.full_name% --editor-cmd=mate
EOT
- );
+ );
parent::configure();
}
public function execute(InputInterface $input, OutputInterface $output) : ?int
{
- $versionNumber = $this->configuration->generateVersionNumber();
+ $configuration = $this->getDependencyFactory()->getConfiguration();
+
+ $migrationGenerator = $this->getDependencyFactory()->getMigrationGenerator();
+
+ $namespace = $input->getOption('namespace') ?: null;
+ $includeDownMigration = $input->getOption('with-down-migration');
- $migrationGenerator = $this->dependencyFactory->getMigrationGenerator();
+ $dirs = $configuration->getMigrationDirectories();
+ if ($namespace === null) {
+ $namespace = key($dirs);
+ } elseif (! isset($dirs[$namespace])) {
+ throw new Exception(sprintf('Path not defined for the namespace %s', $namespace));
+ }
+ assert(is_string($namespace));
+
+ $fqcn = $this->getDependencyFactory()->getClassNameGenerator()->generateClassName($namespace);
- $path = $migrationGenerator->generateMigration($versionNumber);
+ $path = $migrationGenerator->generateMigration(
+ $fqcn,
+ null,
+ null,
+ null,
+ $includeDownMigration ? null : ''
+ );
$editorCommand = $input->getOption('editor-cmd');
if ($editorCommand !== null) {
+ assert(is_string($editorCommand));
$this->procOpen($editorCommand, $path);
}
@@ -60,13 +96,13 @@ public function execute(InputInterface $input, OutputInterface $output) : ?int
sprintf('Generated new migration class to "%s"', $path),
'',
sprintf(
- 'To run just this migration for testing purposes, you can use migrations:execute --up %s',
- $versionNumber
+ 'To run just this migration for testing purposes, you can use migrations:execute --up \'%s\'',
+ $fqcn
),
'',
sprintf(
- 'To revert the migration you can use migrations:execute --down %s',
- $versionNumber
+ 'To revert the migration you can use migrations:execute --down \'%s\'',
+ $fqcn
),
]);
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/LatestCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/LatestCommand.php
index 592239a878..4fa4a67514 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/LatestCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/LatestCommand.php
@@ -4,6 +4,7 @@
namespace Doctrine\Migrations\Tools\Console\Command;
+use Doctrine\Migrations\Exception\NoMigrationsToExecute;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function sprintf;
@@ -27,13 +28,20 @@ protected function configure() : void
public function execute(InputInterface $input, OutputInterface $output) : ?int
{
- $latestVersion = $this->migrationRepository->getLatestVersion();
- $version = $this->migrationRepository->getVersion($latestVersion);
- $description = $version->getMigration()->getDescription();
+ $aliasResolver = $this->getDependencyFactory()->getVersionAliasResolver();
+
+ try {
+ $version = $aliasResolver->resolveVersionAlias('latest');
+ $availableMigration = $this->getDependencyFactory()->getMigrationRepository()->getMigration($version);
+ $description = $availableMigration->getMigration()->getDescription();
+ } catch (NoMigrationsToExecute $e) {
+ $version = '0';
+ $description = '';
+ }
$output->writeln(sprintf(
'%s%s',
- $latestVersion,
+ $version,
$description !== '' ? ' - ' . $description : ''
));
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/MigrateCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/MigrateCommand.php
index 159a7575f3..5df1ac9dbd 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/MigrateCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/MigrateCommand.php
@@ -4,8 +4,9 @@
namespace Doctrine\Migrations\Tools\Console\Command;
-use Doctrine\Migrations\Migrator;
-use Doctrine\Migrations\MigratorConfiguration;
+use Doctrine\Migrations\Exception\NoMigrationsFoundWithCriteria;
+use Doctrine\Migrations\Exception\UnknownMigrationVersion;
+use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -13,6 +14,8 @@
use Symfony\Component\Console\Output\OutputInterface;
use function count;
use function getcwd;
+use function is_string;
+use function is_writable;
use function sprintf;
use function substr;
@@ -106,7 +109,7 @@ protected function configure() : void
Use the --all-or-nothing option to wrap the entire migration in a transaction.
EOT
- );
+ );
parent::configure();
}
@@ -114,80 +117,91 @@ protected function configure() : void
public function execute(InputInterface $input, OutputInterface $output) : ?int
{
$this->outputHeader($output);
-
- $version = (string) $input->getArgument('version');
+ $allowNoMigration = $input->getOption('allow-no-migration');
+ $versionAlias = $input->getArgument('version');
$path = $input->getOption('write-sql');
- $allowNoMigration = (bool) $input->getOption('allow-no-migration');
- $timeAllQueries = (bool) $input->getOption('query-time');
- $dryRun = (bool) $input->getOption('dry-run');
- $allOrNothing = $this->getAllOrNothing($input->getOption('all-or-nothing'));
-
- $this->configuration->setIsDryRun($dryRun);
- $version = $this->getVersionNameFromAlias(
- $version,
- $output
- );
+ try {
+ $version = $this->getDependencyFactory()->getVersionAliasResolver()->resolveVersionAlias($versionAlias);
+ } catch (UnknownMigrationVersion|NoMigrationsFoundWithCriteria $e) {
+ $this->getVersionNameFromAlias($versionAlias, $output);
- if ($version === '') {
return 1;
}
- if ($this->checkExecutedUnavailableMigrations($input, $output) === 1) {
+ $planCalculator = $this->getDependencyFactory()->getMigrationPlanCalculator();
+ $executedUnavailableMigrations = $planCalculator->getExecutedUnavailableMigrations();
+
+ if ($this->checkExecutedUnavailableMigrations($executedUnavailableMigrations, $input, $output) === false) {
+ return 3;
+ }
+
+ $migratorConfigurationFactory = $this->getDependencyFactory()->getConsoleInputMigratorConfigurationFactory();
+ $migratorConfiguration = $migratorConfigurationFactory->getMigratorConfiguration($input);
+
+ $plan = $planCalculator->getPlanUntilVersion($version);
+
+ if (count($plan) === 0 && ! $allowNoMigration) {
+ $output->writeln('Could not find any migrations to execute.');
+
return 1;
}
- $migrator = $this->createMigrator();
+ if (count($plan) === 0) {
+ $this->getVersionNameFromAlias($versionAlias, $output);
+ return 0;
+ }
+
+ $migrator = $this->getDependencyFactory()->getMigrator();
if ($path !== false) {
- $path = $path ?? getcwd();
+ $migratorConfiguration->setDryRun(true);
+ $sql = $migrator->migrate($plan, $migratorConfiguration);
+
+ $path = is_string($path) ? $path : getcwd();
+
+ if (! is_string($path) || ! is_writable($path)) {
+ $output->writeln('Path not writeable!');
- $migrator->writeSqlFile($path, $version);
+ return 1;
+ }
+ $writer = $this->getDependencyFactory()->getQueryWriter();
+ $writer->write($path, $plan->getDirection(), $sql);
return 0;
}
$question = 'WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)';
- if (! $dryRun && ! $this->canExecute($question, $input, $output)) {
+ if (! $migratorConfiguration->isDryRun() && ! $this->canExecute($question, $input, $output)) {
$output->writeln('Migration cancelled!');
- return 1;
+ return 3;
}
- $migratorConfiguration = (new MigratorConfiguration())
- ->setDryRun($dryRun)
- ->setTimeAllQueries($timeAllQueries)
- ->setNoMigrationException($allowNoMigration)
- ->setAllOrNothing($allOrNothing);
-
- $migrator->migrate($version, $migratorConfiguration);
+ $migrator->migrate($plan, $migratorConfiguration);
return 0;
}
- protected function createMigrator() : Migrator
- {
- return $this->dependencyFactory->getMigrator();
- }
-
private function checkExecutedUnavailableMigrations(
+ ExecutedMigrationsSet $executedUnavailableMigrations,
InputInterface $input,
OutputInterface $output
- ) : int {
- $executedUnavailableMigrations = $this->migrationRepository->getExecutedUnavailableMigrations();
-
+ ) : bool {
if (count($executedUnavailableMigrations) !== 0) {
$output->writeln(sprintf(
'WARNING! You have %s previously executed migrations in the database that are not registered migrations.',
count($executedUnavailableMigrations)
));
- foreach ($executedUnavailableMigrations as $executedUnavailableMigration) {
+ foreach ($executedUnavailableMigrations->getItems() as $executedUnavailableMigration) {
$output->writeln(sprintf(
' >> %s (%s)',
- $this->configuration->getDateTime($executedUnavailableMigration),
- $executedUnavailableMigration
+ $executedUnavailableMigration->getExecutedAt() !== null
+ ? $executedUnavailableMigration->getExecutedAt()->format('Y-m-d H:i:s')
+ : null,
+ $executedUnavailableMigration->getVersion()
));
}
@@ -196,60 +210,36 @@ private function checkExecutedUnavailableMigrations(
if (! $this->canExecute($question, $input, $output)) {
$output->writeln('Migration cancelled!');
- return 1;
+ return false;
}
}
- return 0;
+ return true;
}
private function getVersionNameFromAlias(
string $versionAlias,
OutputInterface $output
- ) : string {
- $version = $this->configuration->resolveVersionAlias($versionAlias);
-
- if ($version !== null) {
- return $version;
- }
-
- if ($versionAlias === 'prev') {
+ ) : void {
+ if ($versionAlias === 'first') {
$output->writeln('Already at first version.');
- return '';
+ return;
}
-
- if ($versionAlias === 'next') {
+ if ($versionAlias === 'next' || $versionAlias === 'latest') {
$output->writeln('Already at latest version.');
- return '';
+ return;
}
-
if (substr($versionAlias, 0, 7) === 'current') {
$output->writeln('The delta couldn\'t be reached.');
- return '';
+ return;
}
$output->writeln(sprintf(
'Unknown version: %s',
OutputFormatter::escape($versionAlias)
));
-
- return '';
- }
-
- /**
- * @param mixed $allOrNothing
- */
- private function getAllOrNothing($allOrNothing) : bool
- {
- if ($allOrNothing !== false) {
- return $allOrNothing !== null
- ? (bool) $allOrNothing
- : true;
- }
-
- return $this->configuration->isAllOrNothing();
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/RollupCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/RollupCommand.php
index 7f20cdc90e..14e5b369d6 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/RollupCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/RollupCommand.php
@@ -39,12 +39,11 @@ public function execute(
InputInterface $input,
OutputInterface $output
) : ?int {
- $version = $this->dependencyFactory
- ->getRollup()->rollup();
+ $version = $this->getDependencyFactory()->getRollup()->rollup();
$output->writeln(sprintf(
'Rolled up migrations to version %s',
- $version->getVersion()
+ (string) $version
));
return 0;
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php
index 382bc3223b..aad7a1c83e 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php
@@ -5,17 +5,14 @@
namespace Doctrine\Migrations\Tools\Console\Command;
use DateTimeImmutable;
-use Doctrine\Migrations\Version\Version;
+use Doctrine\Migrations\Metadata\AvailableMigrationsList;
+use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
-use function assert;
use function count;
-use function is_string;
-use function max;
-use function sprintf;
-use function str_repeat;
-use function strlen;
/**
* The StatusCommand class is responsible for outputting what the current state is of all your migrations. It shows
@@ -46,112 +43,91 @@ protected function configure() : void
%command.full_name% --show-versions
EOT
- );
+ );
parent::configure();
}
public function execute(InputInterface $input, OutputInterface $output) : ?int
{
- $output->writeln("\n == Configuration\n");
-
- $infos = $this->dependencyFactory->getMigrationStatusInfosHelper();
+ $storage = $this->getDependencyFactory()->getMetadataStorage();
+ $migrationRepo = $this->getDependencyFactory()->getMigrationRepository();
+ $planCalculator = $this->getDependencyFactory()->getMigrationPlanCalculator();
- foreach ($infos->getMigrationsInfos() as $name => $value) {
- assert(is_string($name));
+ $availableMigrations = $migrationRepo->getMigrations();
+ $executedMigrations = $storage->getExecutedMigrations();
- $string = (string) $value;
+ $newMigrations = $planCalculator->getNewMigrations();
+ $executedUnavailableMigrations = $planCalculator->getExecutedUnavailableMigrations();
- if ($name === 'New Migrations') {
- $string = $value > 0 ? '' . $value . '' : '0';
- }
-
- if ($name === 'Executed Unavailable Migrations') {
- $string = $value > 0 ? '' . $value . '' : '0';
- }
-
- $this->writeStatusInfosLineAligned($output, $name, $string);
- }
+ $infosHelper = $this->getDependencyFactory()->getMigrationStatusInfosHelper();
+ $infosHelper->showMigrationsInfo($output, $availableMigrations, $executedMigrations, $newMigrations, $executedUnavailableMigrations);
if ($input->getOption('show-versions') === false) {
return 0;
}
- $versions = $this->migrationRepository->getMigrations();
- $executedUnavailableMigrations = $this->migrationRepository->getExecutedUnavailableMigrations();
-
- if (count($versions) !== 0) {
- $output->writeln("\n == Available Migration Versions\n");
-
- $this->showVersions($versions, $output);
+ if (count($availableMigrations) !== 0) {
+ $this->showVersions($availableMigrations, $executedMigrations, $output);
}
- if (count($executedUnavailableMigrations) === 0) {
- return 0;
- }
-
- $output->writeln(
- "\n == Previously Executed Unavailable Migration Versions\n"
- );
-
- foreach ($executedUnavailableMigrations as $executedUnavailableMigration) {
- $output->writeln(
- sprintf(
- ' >> %s (%s)',
- $this->configuration->getDateTime($executedUnavailableMigration),
- $executedUnavailableMigration
- )
- );
+ if (count($executedUnavailableMigrations) !== 0) {
+ $this->showUnavailableVersions($output, $executedUnavailableMigrations);
}
return 0;
}
- private function writeStatusInfosLineAligned(OutputInterface $output, string $title, ?string $value) : void
+ private function showUnavailableVersions(OutputInterface $output, ExecutedMigrationsSet $executedUnavailableMigrations) : void
{
- $output->writeln(sprintf(
- ' >> %s: %s%s',
- $title,
- str_repeat(' ', 50 - strlen($title)),
- $value
- ));
+ $table = new Table($output);
+ $table->setHeaders(
+ [
+ [new TableCell('Previously Executed Unavailable Migration Versions', ['colspan' => 2])],
+ ['Migration', 'Migrated At'],
+ ]
+ );
+ foreach ($executedUnavailableMigrations->getItems() as $executedUnavailableMigration) {
+ $table->addRow([
+ (string) $executedUnavailableMigration->getVersion(),
+ $executedUnavailableMigration->getExecutedAt() !== null
+ ? $executedUnavailableMigration->getExecutedAt()->format('Y-m-d H:i:s')
+ : null,
+ ]);
+ }
+ $table->render();
}
- /**
- * @param Version[] $versions
- */
private function showVersions(
- array $versions,
+ AvailableMigrationsList $availableMigrationsSet,
+ ExecutedMigrationsSet $executedMigrationsSet,
OutputInterface $output
) : void {
- foreach ($versions as $version) {
- $executedAt = $version->getExecutedAt();
-
- $status = $version->isMigrated() ? 'migrated' : 'not migrated';
-
- $executedAtStatus = $executedAt instanceof DateTimeImmutable
- ? sprintf(' (executed at %s)', $executedAt->format('Y-m-d H:i:s'))
- : '';
-
- $migration = $version->getMigration();
- $description = $migration->getDescription();
-
- $migrationDescription = $description !== ''
- ? str_repeat(' ', 5) . $description
- : '';
-
- $versionName = $version->getVersion();
- $formattedVersion = $version->getDateTime();
-
- $output->writeln(sprintf(
- ' >> %s (%s)%s%s%s%s',
- $formattedVersion,
- $versionName,
- str_repeat(' ', max(1, 49 - strlen($formattedVersion) - strlen($versionName))),
- $status,
- $executedAtStatus,
- $migrationDescription
- ));
+ $table = new Table($output);
+ $table->setHeaders(
+ [
+ [new TableCell('Available Migration Versions', ['colspan' => 4])],
+ ['Migration', 'Migrated', 'Migrated At', 'Description'],
+ ]
+ );
+ foreach ($availableMigrationsSet->getItems() as $availableMigration) {
+ $executedMigration = $executedMigrationsSet->hasMigration($availableMigration->getVersion())
+ ? $executedMigrationsSet->getMigration($availableMigration->getVersion())
+ : null;
+
+ $executedAt = $executedMigration!==null && $executedMigration->getExecutedAt() instanceof DateTimeImmutable
+ ? $executedMigration->getExecutedAt()->format('Y-m-d H:i:s')
+ : null;
+
+ $description = $availableMigration->getMigration()->getDescription();
+
+ $table->addRow([
+ (string) $availableMigration->getVersion(),
+ $executedMigration !== null ? 'migrated' : 'not migrated',
+ (string) $executedAt,
+ $description,
+ ]);
}
+ $table->render();
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/UpToDateCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/UpToDateCommand.php
index 68344fbfd6..31a9f57c39 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/UpToDateCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/UpToDateCommand.php
@@ -37,36 +37,39 @@ protected function configure() : void
public function execute(InputInterface $input, OutputInterface $output) : ?int
{
- $migrations = count($this->migrationRepository->getMigrations());
- $migratedVersions = count($this->migrationRepository->getMigratedVersions());
- $availableMigrations = $migrations - $migratedVersions;
+ $planCalculator = $this->getDependencyFactory()->getMigrationPlanCalculator();
+ $executedUnavailableMigrations = $planCalculator->getExecutedUnavailableMigrations();
+ $newMigrations = $planCalculator->getNewMigrations();
- if ($availableMigrations === 0) {
+ $newMigrationsCount = count($newMigrations);
+ $executedUnavailableMigrationsCount = count($executedUnavailableMigrations);
+
+ if ($newMigrationsCount === 0 && $executedUnavailableMigrationsCount ===0) {
$output->writeln('Up-to-date! No migrations to execute.');
return 0;
}
- if ($availableMigrations > 0) {
+ if ($newMigrationsCount > 0) {
$output->writeln(sprintf(
'Out-of-date! %u migration%s available to execute.',
- $availableMigrations,
- $availableMigrations > 1 ? 's are' : ' is'
+ $newMigrationsCount,
+ $newMigrationsCount > 1 ? 's are' : ' is'
));
return 1;
}
// negative number means that there are unregistered migrations in the database
+ if ($executedUnavailableMigrationsCount > 0) {
+ $output->writeln(sprintf(
+ 'You have %1$u previously executed migration%3$s in the database that %2$s registered migration%3$s.',
+ $executedUnavailableMigrationsCount,
+ $executedUnavailableMigrationsCount > 1 ? 'are not' : 'is not a',
+ $executedUnavailableMigrationsCount > 1 ? 's' : ''
+ ));
+ }
- $extraMigrations = -$availableMigrations;
- $output->writeln(sprintf(
- 'You have %1$u previously executed migration%3$s in the database that %2$s registered migration%3$s.',
- $extraMigrations,
- $extraMigrations > 1 ? 'are not' : 'is not a',
- $extraMigrations > 1 ? 's' : ''
- ));
-
- return $input->getOption('fail-on-unregistered') === true ? 2 : 0;
+ return $executedUnavailableMigrationsCount > 0 && $input->getOption('fail-on-unregistered') === true ? 2 : 0;
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php
index 2244da39df..f6c47b7175 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Command/VersionCommand.php
@@ -4,10 +4,15 @@
namespace Doctrine\Migrations\Tools\Console\Command;
+use Doctrine\Migrations\Exception\MigrationClassNotFound;
use Doctrine\Migrations\Exception\UnknownMigrationVersion;
+use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
use Doctrine\Migrations\Tools\Console\Exception\InvalidOptionUsage;
use Doctrine\Migrations\Tools\Console\Exception\VersionAlreadyExists;
use Doctrine\Migrations\Tools\Console\Exception\VersionDoesNotExist;
+use Doctrine\Migrations\Version\Direction;
+use Doctrine\Migrations\Version\ExecutionResult;
+use Doctrine\Migrations\Version\Version;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -69,11 +74,11 @@ protected function configure() : void
->setHelp(<<%command.name% command allows you to manually add, delete or synchronize migration versions from the version table:
- %command.full_name% YYYYMMDDHHMMSS --add
+ %command.full_name% MIGRATION-FQCN --add
If you want to delete a version you can use the --delete option:
- %command.full_name% YYYYMMDDHHMMSS --delete
+ %command.full_name% MIGRATION-FQCN --delete
If you want to synchronize by adding or deleting all migration versions available in the version table you can use the --all option:
@@ -82,8 +87,8 @@ protected function configure() : void
If you want to synchronize by adding or deleting some range of migration versions available in the version table you can use the --range-from/--range-to option:
- %command.full_name% --add --range-from=YYYYMMDDHHMMSS --range-to=YYYYMMDDHHMMSS
- %command.full_name% --delete --range-from=YYYYMMDDHHMMSS --range-to=YYYYMMDDHHMMSS
+ %command.full_name% --add --range-from=MIGRATION-FQCN --range-to=MIGRATION-FQCN
+ %command.full_name% --delete --range-from=MIGRATION-FQCN --range-to=MIGRATION-FQCN
You can also execute this command without a warning message which you need to interact with:
@@ -103,7 +108,7 @@ public function execute(InputInterface $input, OutputInterface $output) : ?int
throw InvalidOptionUsage::new('You must specify whether you want to --add or --delete the specified version.');
}
- $this->markMigrated = (bool) $input->getOption('add');
+ $this->markMigrated = $input->getOption('add');
if ($input->isInteractive()) {
$question = 'WARNING! You are about to add, delete or synchronize migration versions from the version table that could result in data lost. Are you sure you wish to continue? (y/n)';
@@ -144,24 +149,36 @@ private function markVersions(InputInterface $input, OutputInterface $output) :
);
}
+ $executedMigrations = $this->getDependencyFactory()->getMetadataStorage()->getExecutedMigrations();
+ $availableVersions = $this->getDependencyFactory()->getMigrationRepository()->getMigrations();
if ($allOption === true) {
- $availableVersions = $this->migrationRepository->getAvailableVersions();
-
- foreach ($availableVersions as $version) {
- $this->mark($input, $output, $version, true);
+ if ($input->getOption('delete') === true) {
+ foreach ($executedMigrations->getItems() as $availableMigration) {
+ $this->mark($input, $output, $availableMigration->getVersion(), false, $executedMigrations);
+ }
+ }
+ foreach ($availableVersions->getItems() as $availableMigration) {
+ $this->mark($input, $output, $availableMigration->getVersion(), true, $executedMigrations);
}
+ } elseif ($affectedVersion !== null) {
+ $this->mark($input, $output, new Version($affectedVersion), false, $executedMigrations);
} elseif ($rangeFromOption !== null && $rangeToOption !== null) {
- $availableVersions = $this->migrationRepository->getAvailableVersions();
+ $migrate = false;
+ foreach ($availableVersions->getItems() as $availableMigration) {
+ if ((string) $availableMigration->getVersion() === $rangeFromOption) {
+ $migrate = true;
+ }
- foreach ($availableVersions as $version) {
- if ($version < $rangeFromOption || $version > $rangeToOption) {
- continue;
+ if ($migrate) {
+ $this->mark($input, $output, $availableMigration->getVersion(), true, $executedMigrations);
}
- $this->mark($input, $output, $version, true);
+ if ((string) $availableMigration->getVersion() === $rangeToOption) {
+ break;
+ }
}
} else {
- $this->mark($input, $output, $affectedVersion);
+ throw InvalidOptionUsage::new('You must specify the version or use the --all argument.');
}
}
@@ -170,11 +187,18 @@ private function markVersions(InputInterface $input, OutputInterface $output) :
* @throws VersionDoesNotExist
* @throws UnknownMigrationVersion
*/
- private function mark(InputInterface $input, OutputInterface $output, string $version, bool $all = false) : void
+ private function mark(InputInterface $input, OutputInterface $output, Version $version, bool $all, ExecutedMigrationsSet $executedMigrations) : void
{
- if (! $this->migrationRepository->hasVersion($version)) {
- if ((bool) $input->getOption('delete') === false) {
- throw UnknownMigrationVersion::new($version);
+ try {
+ $availableMigration = $this->getDependencyFactory()->getMigrationRepository()->getMigration($version);
+ } catch (MigrationClassNotFound $e) {
+ $availableMigration = null;
+ }
+
+ $storage = $this->getDependencyFactory()->getMetadataStorage();
+ if ($availableMigration === null) {
+ if ($input->getOption('delete') === false) {
+ throw UnknownMigrationVersion::new((string) $version);
}
$question =
@@ -184,22 +208,20 @@ private function mark(InputInterface $input, OutputInterface $output, string $ve
$confirmation = $this->askConfirmation($question, $input, $output);
if ($confirmation) {
- $this->migrationRepository->removeMigrationVersionFromDatabase($version);
-
+ $migrationResult = new ExecutionResult($version, Direction::DOWN);
+ $storage->complete($migrationResult);
$output->writeln(sprintf(
'%s deleted from the version table.',
- $version
+ (string) $version
));
return;
}
}
- $version = $this->migrationRepository->getVersion($version);
-
$marked = false;
- if ($this->markMigrated && $this->migrationRepository->hasVersionMigrated($version)) {
+ if ($this->markMigrated && $executedMigrations->hasMigration($version)) {
if (! $all) {
throw VersionAlreadyExists::new($version);
}
@@ -207,7 +229,7 @@ private function mark(InputInterface $input, OutputInterface $output, string $ve
$marked = true;
}
- if (! $this->markMigrated && ! $this->migrationRepository->hasVersionMigrated($version)) {
+ if (! $this->markMigrated && ! $executedMigrations->hasMigration($version)) {
if (! $all) {
throw VersionDoesNotExist::new($version);
}
@@ -220,18 +242,20 @@ private function mark(InputInterface $input, OutputInterface $output, string $ve
}
if ($this->markMigrated) {
- $version->markMigrated();
+ $migrationResult = new ExecutionResult($version, Direction::UP);
+ $storage->complete($migrationResult);
$output->writeln(sprintf(
'%s added to the version table.',
- $version->getVersion()
+ (string) $version
));
} else {
- $version->markNotMigrated();
+ $migrationResult = new ExecutionResult($version, Direction::DOWN);
+ $storage->complete($migrationResult);
$output->writeln(sprintf(
'%s deleted from the version table.',
- $version->getVersion()
+ (string) $version
));
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php b/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php
index 92fbadf6db..34ddca5b24 100644
--- a/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php
+++ b/lib/Doctrine/Migrations/Tools/Console/ConnectionLoader.php
@@ -5,52 +5,31 @@
namespace Doctrine\Migrations\Tools\Console;
use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Configuration\Connection\ConnectionLoaderInterface;
use Doctrine\Migrations\Configuration\Connection\Loader\ArrayConnectionConfigurationLoader;
-use Doctrine\Migrations\Configuration\Connection\Loader\ConnectionConfigurationChainLoader;
-use Doctrine\Migrations\Configuration\Connection\Loader\ConnectionConfigurationLoader;
use Doctrine\Migrations\Configuration\Connection\Loader\ConnectionHelperLoader;
-use Doctrine\Migrations\Tools\Console\Exception\ConnectionNotSpecified;
+use Doctrine\Migrations\Configuration\Connection\Loader\NoConnectionLoader;
+use Doctrine\Migrations\Configuration\Connection\Loader\ShardedConnectionLoader;
use Symfony\Component\Console\Helper\HelperSet;
-use Symfony\Component\Console\Input\InputInterface;
/**
* The ConnectionLoader class is responsible for loading the Doctrine\DBAL\Connection instance to use for migrations.
*
* @internal
*/
-class ConnectionLoader
+final class ConnectionLoader
{
- /** @var Configuration|null */
- private $configuration;
-
- public function __construct(?Configuration $configuration)
- {
- $this->configuration = $configuration;
- }
-
- public function getConnection(InputInterface $input, HelperSet $helperSet) : Connection
- {
- $connection = $this->createConnectionConfigurationChainLoader($input, $helperSet)
- ->chosen();
-
- if ($connection !== null) {
- return $connection;
- }
-
- throw ConnectionNotSpecified::new();
- }
-
- protected function createConnectionConfigurationChainLoader(
- InputInterface $input,
+ public function getConnection(
+ ?string $dbConfig,
+ ?string $shard,
HelperSet $helperSet
- ) : ConnectionLoaderInterface {
- return new ConnectionConfigurationChainLoader([
- new ArrayConnectionConfigurationLoader($input->getOption('db-configuration')),
- new ArrayConnectionConfigurationLoader('migrations-db.php'),
- new ConnectionHelperLoader($helperSet, 'connection'),
- new ConnectionConfigurationLoader($this->configuration),
- ]);
+ ) : Connection {
+ // create a chain of connection loaders
+ $loader = new NoConnectionLoader();
+ $loader = new ConnectionHelperLoader('connection', $loader, $helperSet);
+ $loader = new ArrayConnectionConfigurationLoader('migrations-db.php', $loader);
+ $loader = new ArrayConnectionConfigurationLoader($dbConfig, $loader);
+ $loader = new ShardedConnectionLoader($shard, $loader);
+
+ return $loader->getConnection();
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/ConsoleInputMigratorConfigurationFactory.php b/lib/Doctrine/Migrations/Tools/Console/ConsoleInputMigratorConfigurationFactory.php
new file mode 100644
index 0000000000..b6fd894e9f
--- /dev/null
+++ b/lib/Doctrine/Migrations/Tools/Console/ConsoleInputMigratorConfigurationFactory.php
@@ -0,0 +1,32 @@
+configuration = $configuration;
+ }
+
+ public function getMigratorConfiguration(InputInterface $input) : MigratorConfiguration
+ {
+ $timeAllQueries = $input->hasOption('query-time') ? (bool) $input->getOption('query-time') : false;
+ $dryRun = $input->hasOption('dry-run') ? (bool) $input->getOption('dry-run') : false;
+ $allOrNothing = $input->hasOption('all-or-nothing') ? (bool) $input->getOption('all-or-nothing') : $this->configuration->isAllOrNothing();
+
+ return (new MigratorConfiguration())
+ ->setDryRun($dryRun)
+ ->setTimeAllQueries($timeAllQueries)
+ ->setAllOrNothing($allOrNothing);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Tools/Console/ConsoleLogger.php b/lib/Doctrine/Migrations/Tools/Console/ConsoleLogger.php
new file mode 100644
index 0000000000..d0797c85d0
--- /dev/null
+++ b/lib/Doctrine/Migrations/Tools/Console/ConsoleLogger.php
@@ -0,0 +1,131 @@
+ */
+ private $verbosityLevelMap = [
+ LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
+ LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
+ LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
+ LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
+ LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
+ LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL,
+ LogLevel::INFO => OutputInterface::VERBOSITY_VERBOSE,
+ LogLevel::DEBUG => OutputInterface::VERBOSITY_VERY_VERBOSE,
+ ];
+ /** @var array */
+ private $formatLevelMap = [
+ LogLevel::EMERGENCY => self::ERROR,
+ LogLevel::ALERT => self::ERROR,
+ LogLevel::CRITICAL => self::ERROR,
+ LogLevel::ERROR => self::ERROR,
+ LogLevel::WARNING => self::INFO,
+ LogLevel::NOTICE => self::INFO,
+ LogLevel::INFO => self::INFO,
+ LogLevel::DEBUG => self::INFO,
+ ];
+
+ /**
+ * @param array $verbosityLevelMap
+ * @param array $formatLevelMap
+ */
+ public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = [])
+ {
+ $this->output = $output;
+ $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
+ $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function log($level, $message, array $context = [])
+ {
+ if (! isset($this->verbosityLevelMap[$level])) {
+ throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
+ }
+
+ $output = $this->output;
+
+ // Write to the error output if necessary and available
+ if ($this->formatLevelMap[$level] === self::ERROR) {
+ if ($this->output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+ }
+
+ // the if condition check isn't necessary -- it's the same one that $output will do internally anyway.
+ // We only do it for efficiency here as the message formatting is relatively expensive.
+ if ($output->getVerbosity() < $this->verbosityLevelMap[$level]) {
+ return;
+ }
+
+ $output->writeln(sprintf('<%1$s>[%2$s] %3$s%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]);
+ }
+
+ /**
+ * Interpolates context values into the message placeholders.
+ *
+ * @param mixed[] $context
+ */
+ private function interpolate(string $message, array $context) : string
+ {
+ if (strpos($message, '{') === false) {
+ return $message;
+ }
+
+ $replacements = [];
+ foreach ($context as $key => $val) {
+ if ($val === null || is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) {
+ $replacements["{{$key}}"] = $val;
+ } elseif ($val instanceof DateTimeInterface) {
+ $replacements["{{$key}}"] = $val->format(DateTime::RFC3339);
+ } elseif (is_object($val)) {
+ $replacements["{{$key}}"] = '[object ' . get_class($val) . ']';
+ } else {
+ $replacements["{{$key}}"] = '[' . gettype($val) . ']';
+ }
+
+ if (! isset($replacements["{{$key}}"])) {
+ continue;
+ }
+
+ $replacements["{{$key}}"] = '' . $replacements["{{$key}}"] . '';
+ }
+
+ return strtr($message, $replacements);
+ }
+}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/DependenciesNotSatisfied.php b/lib/Doctrine/Migrations/Tools/Console/Exception/DependenciesNotSatisfied.php
new file mode 100644
index 0000000000..b4e01ea715
--- /dev/null
+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/DependenciesNotSatisfied.php
@@ -0,0 +1,15 @@
+getVersion()));
+ return new self(sprintf('The version "%s" already exists in the version table.', (string) $version));
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Exception/VersionDoesNotExist.php b/lib/Doctrine/Migrations/Tools/Console/Exception/VersionDoesNotExist.php
index c2ee7f8538..6bac76396b 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Exception/VersionDoesNotExist.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Exception/VersionDoesNotExist.php
@@ -12,6 +12,6 @@ final class VersionDoesNotExist extends InvalidArgumentException implements Cons
{
public static function new(Version $version) : self
{
- return new self(sprintf('The version "%s" does not exist in the version table.', $version->getVersion()));
+ return new self(sprintf('The version "%s" does not exist in the version table.', (string) $version));
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php b/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php
index a4d21ea159..6e0b3e8ba4 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelper.php
@@ -4,55 +4,41 @@
namespace Doctrine\Migrations\Tools\Console\Helper;
-use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\ArrayConfiguration;
use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Configuration\JsonConfiguration;
-use Doctrine\Migrations\Configuration\XmlConfiguration;
-use Doctrine\Migrations\Configuration\YamlConfiguration;
+use Doctrine\Migrations\Configuration\ConfigurationLoader;
+use Doctrine\Migrations\Configuration\Exception\UnknownLoader;
use Doctrine\Migrations\Tools\Console\Exception\FileTypeNotSupported;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputInterface;
+use const PATHINFO_EXTENSION;
use function file_exists;
+use function is_string;
use function pathinfo;
/**
* The ConfigurationHelper class is responsible for getting the Configuration instance from one of the supported methods
* for defining the configuration for your migrations.
*/
-class ConfigurationHelper extends Helper implements ConfigurationHelperInterface
+final class ConfigurationHelper extends Helper implements ConfigurationHelperInterface
{
- /** @var Connection */
- private $connection;
+ /** @var ConfigurationLoader */
+ private $loader;
- /** @var Configuration|null */
- private $configuration;
-
- public function __construct(
- Connection $connection,
- ?Configuration $configuration = null
- ) {
- $this->connection = $connection;
- $this->configuration = $configuration;
+ public function __construct(?ConfigurationLoader $loader = null)
+ {
+ $this->loader = $loader ?: new ConfigurationLoader();
}
- public function getMigrationConfig(InputInterface $input) : Configuration
+ public function getConfiguration(InputInterface $input) : Configuration
{
/**
* If a configuration option is passed to the command line, use that configuration
* instead of any other one.
*/
- $configuration = $input->getOption('configuration');
+ $configurationFile = $input->getOption('configuration');
- if ($configuration !== null) {
- return $this->loadConfig($configuration);
- }
-
- /**
- * If a configuration has already been set using DI or a Setter use it.
- */
- if ($this->configuration !== null) {
- return $this->configuration;
+ if ($configurationFile !== null && is_string($configurationFile)) {
+ return $this->loadConfig($configurationFile);
}
/**
@@ -72,7 +58,7 @@ public function getMigrationConfig(InputInterface $input) : Configuration
}
}
- return new Configuration($this->connection);
+ return $this->loader->getLoader('array')->load([]);
}
private function configExists(string $config) : bool
@@ -83,28 +69,15 @@ private function configExists(string $config) : bool
/**
* @throws FileTypeNotSupported
*/
- private function loadConfig(string $config) : Configuration
+ private function loadConfig(string $configFile) : Configuration
{
- $map = [
- 'xml' => XmlConfiguration::class,
- 'yaml' => YamlConfiguration::class,
- 'yml' => YamlConfiguration::class,
- 'php' => ArrayConfiguration::class,
- 'json' => JsonConfiguration::class,
- ];
-
- $info = pathinfo($config);
+ $extension = pathinfo($configFile, PATHINFO_EXTENSION);
- // check we can support this file type
- if (! isset($map[$info['extension']])) {
+ try {
+ return $this->loader->getLoader($extension)->load($configFile);
+ } catch (UnknownLoader $e) {
throw FileTypeNotSupported::new();
}
-
- $class = $map[$info['extension']];
- $configuration = new $class($this->connection);
- $configuration->load($config);
-
- return $configuration;
}
/**
diff --git a/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelperInterface.php b/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelperInterface.php
index 38386b4de9..65cd423fc2 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelperInterface.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelperInterface.php
@@ -12,7 +12,7 @@
*/
interface ConfigurationHelperInterface
{
- public function getMigrationConfig(
+ public function getConfiguration(
InputInterface $input
) : Configuration;
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php b/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php
index d3a01ccf5c..d3b74dc133 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationDirectoryHelper.php
@@ -7,10 +7,8 @@
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Tools\Console\Exception\DirectoryDoesNotExist;
use const DIRECTORY_SEPARATOR;
-use function assert;
use function date;
use function file_exists;
-use function getcwd;
use function mkdir;
use function rtrim;
@@ -21,35 +19,22 @@
*/
class MigrationDirectoryHelper
{
- /** @var Configuration */
- private $configuration;
-
- public function __construct(Configuration $configuration)
- {
- $this->configuration = $configuration;
- }
-
/**
* @throws DirectoryDoesNotExist
*/
- public function getMigrationDirectory() : string
+ public function getMigrationDirectory(Configuration $configuration, string $dir) : string
{
- $dir = $this->configuration->getMigrationsDirectory();
- $dir = $dir ?? getcwd();
-
- assert($dir !== false, 'Unable to determine current working directory.');
-
$dir = rtrim($dir, '/');
if (! file_exists($dir)) {
throw DirectoryDoesNotExist::new($dir);
}
- if ($this->configuration->areMigrationsOrganizedByYear()) {
+ if ($configuration->areMigrationsOrganizedByYear()) {
$dir .= $this->appendDir(date('Y'));
}
- if ($this->configuration->areMigrationsOrganizedByYearAndMonth()) {
+ if ($configuration->areMigrationsOrganizedByYearAndMonth()) {
$dir .= $this->appendDir(date('m'));
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationStatusInfosHelper.php b/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationStatusInfosHelper.php
index 4b28c911ea..5fb3eba205 100644
--- a/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationStatusInfosHelper.php
+++ b/lib/Doctrine/Migrations/Tools/Console/Helper/MigrationStatusInfosHelper.php
@@ -4,10 +4,20 @@
namespace Doctrine\Migrations\Tools\Console\Helper;
-use Doctrine\Migrations\Configuration\AbstractFileConfiguration;
+use Doctrine\DBAL\Connection;
use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\MigrationRepository;
+use Doctrine\Migrations\Metadata\AvailableMigrationsList;
+use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
+use Doctrine\Migrations\Version\AliasResolverInterface;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Helper\TableCell;
+use Symfony\Component\Console\Helper\TableSeparator;
+use Symfony\Component\Console\Output\OutputInterface;
+use Throwable;
+use function array_unshift;
use function count;
+use function get_class;
use function sprintf;
/**
@@ -20,52 +30,118 @@
*/
class MigrationStatusInfosHelper
{
- /** @var Configuration */
+ /** @var Configuration */
private $configuration;
- /** @var MigrationRepository */
- private $migrationRepository;
+ /** @var Connection */
+ private $connection;
+
+ /** @var AliasResolverInterface */
+ private $aliasResolver;
public function __construct(
Configuration $configuration,
- MigrationRepository $migrationRepository
+ Connection $connection,
+ AliasResolverInterface $aliasResolver
) {
- $this->configuration = $configuration;
- $this->migrationRepository = $migrationRepository;
+ $this->configuration = $configuration;
+ $this->connection = $connection;
+ $this->aliasResolver = $aliasResolver;
}
- /** @return string[]|int[]|null[] */
- public function getMigrationsInfos() : array
- {
- $executedMigrations = $this->migrationRepository->getMigratedVersions();
- $availableMigrations = $this->migrationRepository->getAvailableVersions();
- $newMigrations = $this->migrationRepository->getNewVersions();
- $executedUnavailableMigrations = $this->migrationRepository->getExecutedUnavailableMigrations();
-
- return [
- 'Name' => $this->configuration->getName() ?? 'Doctrine Database Migrations',
- 'Database Driver' => $this->configuration->getConnection()->getDriver()->getName(),
- 'Database Host' => $this->configuration->getConnection()->getHost(),
- 'Database Name' => $this->configuration->getConnection()->getDatabase(),
- 'Configuration Source' => $this->configuration instanceof AbstractFileConfiguration ? $this->configuration->getFile() : 'manually configured',
- 'Version Table Name' => $this->configuration->getMigrationsTableName(),
- 'Version Column Name' => $this->configuration->getMigrationsColumnName(),
- 'Migrations Namespace' => $this->configuration->getMigrationsNamespace(),
- 'Migrations Directory' => $this->configuration->getMigrationsDirectory(),
- 'Previous Version' => $this->getFormattedVersionAlias('prev'),
- 'Current Version' => $this->getFormattedVersionAlias('current'),
- 'Next Version' => $this->getFormattedVersionAlias('next'),
- 'Latest Version' => $this->getFormattedVersionAlias('latest'),
- 'Executed Migrations' => count($executedMigrations),
- 'Executed Unavailable Migrations' => count($executedUnavailableMigrations),
- 'Available Migrations' => count($availableMigrations),
- 'New Migrations' => count($newMigrations),
+ public function showMigrationsInfo(
+ OutputInterface $output,
+ AvailableMigrationsList $availableMigrations,
+ ExecutedMigrationsSet $executedMigrations,
+ AvailableMigrationsList $newMigrations,
+ ExecutedMigrationsSet $executedUnavailableMigrations
+ ) : void {
+ $storage = $this->configuration->getMetadataStorageConfiguration();
+
+ $table = new Table($output);
+ $table->setHeaders(
+ [
+ [new TableCell('Configuration', ['colspan' => 3])],
+ ]
+ );
+ $data = [
+ 'Project' => $this->configuration->getName() ?? 'Doctrine Database Migrations',
+ ];
+ foreach ($data as $k => $v) {
+ $table->addRow([
+ '' . $k . '',
+ new TableCell($v, ['colspan' => 2]),
+ ]);
+ }
+ $dataGroup = [
+ 'Storage' => [
+ 'Type' => $storage!== null ? get_class($storage) : null,
+ ],
+ 'Database' => [
+ 'Driver' => $this->connection->getDriver()->getName(),
+ 'Host' => $this->connection->getHost(),
+ 'Name' => $this->connection->getDatabase(),
+ ],
+ 'Versions' => [
+ 'Previous' => $this->getFormattedVersionAlias('prev', $executedMigrations),
+ 'Current' => $this->getFormattedVersionAlias('current', $executedMigrations),
+ 'Next' => $this->getFormattedVersionAlias('next', $executedMigrations),
+ 'Latest' => $this->getFormattedVersionAlias('latest', $executedMigrations),
+ ],
+
+ 'Migrations' => [
+ 'Executed' => count($executedMigrations),
+ 'Executed Unavailable' => count($executedUnavailableMigrations) > 0 ? ('' . count($executedUnavailableMigrations) . '') : '0',
+ 'Available' => count($availableMigrations),
+ 'New' => count($newMigrations) > 0 ? ('' . count($newMigrations) . '') : '0',
+ ],
+ 'Migration Namespaces' => $this->configuration->getMigrationDirectories(),
+
];
+ if ($storage instanceof TableMetadataStorageConfiguration) {
+ $dataGroup['Storage'] += [
+ 'Table Name' => $storage->getTableName(),
+ 'Column Name' => $storage->getVersionColumnName(),
+ ];
+ $table->addRow([new TableSeparator(['colspan' => 3])]);
+ foreach ($data as $k => $v) {
+ $table->addRow([
+ '' . $k . '',
+ new TableCell($v, ['colspan' => 2]),
+ ]);
+ }
+ }
+
+ foreach ($dataGroup as $group => $dataValues) {
+ $nsRows = [];
+ foreach ($dataValues as $k => $v) {
+ $nsRows[] = [
+ $k,
+ $v,
+ ];
+ }
+ if (count($nsRows) <= 0) {
+ continue;
+ }
+
+ $table->addRow([new TableSeparator(['colspan' => 3])]);
+ array_unshift(
+ $nsRows[0],
+ new TableCell('' . $group . '', ['rowspan' => count($dataValues)])
+ );
+ $table->addRows($nsRows);
+ }
+
+ $table->render();
}
- private function getFormattedVersionAlias(string $alias) : string
+ private function getFormattedVersionAlias(string $alias, ExecutedMigrationsSet $executedMigrationsSet) : string
{
- $version = $this->configuration->resolveVersionAlias($alias);
+ try {
+ $version = $this->aliasResolver->resolveVersionAlias($alias);
+ } catch (Throwable $e) {
+ $version = null;
+ }
// No version found
if ($version === null) {
@@ -77,17 +153,18 @@ private function getFormattedVersionAlias(string $alias) : string
return 'Already at first version';
}
}
-
+ if ($alias === 'latest' && $version!== null && $executedMigrationsSet->hasMigration($version)) {
+ return 'Already at latest version';
+ }
// Before first version "virtual" version number
- if ($version === '0') {
+ if ((string) $version === '0') {
return '0';
}
// Show normal version number
return sprintf(
- '%s (%s)',
- $this->configuration->getDateTime((string) $version),
- $version
+ '%s ',
+ (string) $version
);
}
}
diff --git a/lib/Doctrine/Migrations/Tools/Console/MigratorConfigurationFactory.php b/lib/Doctrine/Migrations/Tools/Console/MigratorConfigurationFactory.php
new file mode 100644
index 0000000000..5b4c5dc823
--- /dev/null
+++ b/lib/Doctrine/Migrations/Tools/Console/MigratorConfigurationFactory.php
@@ -0,0 +1,13 @@
+schemaManager = $schemaManager;
- $this->name = $name;
- $this->columnName = $columnName;
- $this->columnLength = $columnLength;
- $this->executedAtColumnName = $executedAtColumnName;
- }
-
- public function getName() : string
- {
- return $this->name;
- }
-
- public function getColumnName() : string
- {
- return $this->columnName;
- }
-
- public function getColumnLength() : int
- {
- return $this->columnLength;
- }
-
- public function getExecutedAtColumnName() : string
- {
- return $this->executedAtColumnName;
- }
-
- public function getMigrationsColumn() : Column
- {
- return new Column(
- $this->columnName,
- Type::getType(self::MIGRATION_COLUMN_TYPE),
- ['length' => $this->columnLength]
- );
- }
-
- public function getExecutedAtColumn() : Column
- {
- return new Column(
- $this->executedAtColumnName,
- Type::getType(self::MIGRATION_EXECUTED_AT_COLUMN_TYPE)
- );
- }
-
- /**
- * @return string[]
- */
- public function getColumnNames() : array
- {
- return [
- $this->columnName,
- $this->executedAtColumnName,
- ];
- }
-
- public function getDBALTable() : Table
- {
- $executedAtColumn = $this->getExecutedAtColumn();
- $executedAtColumn->setNotnull(false);
-
- $columns = [
- $this->columnName => $this->getMigrationsColumn(),
- $this->executedAtColumnName => $executedAtColumn,
- ];
-
- return $this->createDBALTable($columns);
- }
-
- public function getNewDBALTable() : Table
- {
- $executedAtColumn = $this->getExecutedAtColumn();
- $executedAtColumn->setNotnull(true);
-
- $columns = [
- $this->columnName => $this->getMigrationsColumn(),
- $this->executedAtColumnName => $executedAtColumn,
- ];
-
- return $this->createDBALTable($columns);
- }
-
- /**
- * @param Column[] $columns
- */
- public function createDBALTable(array $columns) : Table
- {
- $schemaConfig = $this->schemaManager->createSchemaConfig();
-
- $table = new Table($this->getName(), $columns);
- $table->setPrimaryKey([$this->getColumnName()]);
-
- foreach ($schemaConfig->getDefaultTableOptions() as $name => $value) {
- $table->addOption($name, $value);
- }
-
- return $table;
- }
-}
diff --git a/lib/Doctrine/Migrations/Tracking/TableManipulator.php b/lib/Doctrine/Migrations/Tracking/TableManipulator.php
deleted file mode 100644
index 6dbbde1e8c..0000000000
--- a/lib/Doctrine/Migrations/Tracking/TableManipulator.php
+++ /dev/null
@@ -1,75 +0,0 @@
-configuration = $configuration;
- $this->schemaManager = $schemaManager;
- $this->migrationTable = $migrationTable;
- $this->migrationTableStatus = $migrationTableStatus;
- $this->migrationTableUpdater = $migrationTableUpdater;
- }
-
- public function createMigrationTable() : bool
- {
- $this->configuration->validate();
-
- if ($this->configuration->isDryRun()) {
- return false;
- }
-
- if ($this->migrationTableStatus->isCreated()) {
- if (! $this->migrationTableStatus->isUpToDate()) {
- $this->migrationTableUpdater->updateMigrationTable();
-
- $this->migrationTableStatus->setUpToDate(true);
-
- return true;
- }
-
- return false;
- }
-
- $table = $this->migrationTable->getNewDBALTable();
-
- $this->schemaManager->createTable($table);
-
- $this->migrationTableStatus->setCreated(true);
-
- return true;
- }
-}
diff --git a/lib/Doctrine/Migrations/Tracking/TableStatus.php b/lib/Doctrine/Migrations/Tracking/TableStatus.php
deleted file mode 100644
index a3b781de4f..0000000000
--- a/lib/Doctrine/Migrations/Tracking/TableStatus.php
+++ /dev/null
@@ -1,78 +0,0 @@
-schemaManager = $schemaManager;
- $this->migrationTable = $migrationTable;
- }
-
- public function setCreated(bool $created) : void
- {
- $this->created = $created;
- }
-
- public function isCreated() : bool
- {
- if ($this->created !== null) {
- return $this->created;
- }
-
- $this->created = $this->schemaManager->tablesExist([$this->migrationTable->getName()]);
-
- return $this->created;
- }
-
- public function setUpToDate(bool $upToDate) : void
- {
- $this->upToDate = $upToDate;
- }
-
- public function isUpToDate() : bool
- {
- if ($this->upToDate !== null) {
- return $this->upToDate;
- }
-
- $table = $this->schemaManager->listTableDetails($this->migrationTable->getName());
-
- $this->upToDate = true;
-
- foreach ($this->migrationTable->getColumnNames() as $columnName) {
- if ($table->hasColumn($columnName)) {
- continue;
- }
-
- $this->upToDate = false;
- break;
- }
-
- return $this->upToDate;
- }
-}
diff --git a/lib/Doctrine/Migrations/Tracking/TableUpdater.php b/lib/Doctrine/Migrations/Tracking/TableUpdater.php
deleted file mode 100644
index 66693acdf2..0000000000
--- a/lib/Doctrine/Migrations/Tracking/TableUpdater.php
+++ /dev/null
@@ -1,100 +0,0 @@
-connection = $connection;
- $this->schemaManager = $schemaManager;
- $this->migrationTable = $migrationTable;
- $this->platform = $platform;
- }
-
- public function updateMigrationTable() : void
- {
- $fromTable = $this->getFromTable();
- $toTable = $this->migrationTable->getDBALTable();
-
- $fromSchema = $this->createSchema([$fromTable]);
- $toSchema = $this->createSchema([$toTable]);
-
- $queries = $fromSchema->getMigrateToSql($toSchema, $this->platform);
-
- $this->connection->beginTransaction();
-
- try {
- foreach ($queries as $query) {
- $this->connection->executeQuery($query);
- }
- } catch (Throwable $e) {
- $this->connection->rollBack();
-
- throw $e;
- }
-
- $this->connection->commit();
- }
-
- /**
- * @param Table[] $tables
- */
- protected function createSchema(array $tables) : Schema
- {
- return new Schema($tables);
- }
-
- private function getFromTable() : Table
- {
- $tableName = $this->migrationTable->getName();
- $columnNames = $this->migrationTable->getColumnNames();
-
- $currentTable = $this->schemaManager->listTableDetails($tableName);
-
- $table = $this->migrationTable->createDBALTable($currentTable->getColumns());
-
- // remove columns from the table definition that we don't care about
- // so we don't try to drop those columns
- foreach ($table->getColumns() as $column) {
- if (in_array($column->getName(), $columnNames, true)) {
- continue;
- }
-
- $table->dropColumn($column->getName());
- }
-
- return $table;
- }
-}
diff --git a/lib/Doctrine/Migrations/Version/AliasResolver.php b/lib/Doctrine/Migrations/Version/AliasResolver.php
index e48416198d..448ab58bb4 100644
--- a/lib/Doctrine/Migrations/Version/AliasResolver.php
+++ b/lib/Doctrine/Migrations/Version/AliasResolver.php
@@ -4,7 +4,13 @@
namespace Doctrine\Migrations\Version;
+use Doctrine\Migrations\Exception\NoMigrationsFoundWithCriteria;
+use Doctrine\Migrations\Exception\NoMigrationsToExecute;
+use Doctrine\Migrations\Exception\UnknownMigrationVersion;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
+use Doctrine\Migrations\MigrationPlanCalculator;
use Doctrine\Migrations\MigrationRepository;
+use function count;
use function substr;
/**
@@ -12,7 +18,7 @@
*
* @internal
*/
-final class AliasResolver
+final class AliasResolver implements AliasResolverInterface
{
private const ALIAS_FIRST = 'first';
private const ALIAS_CURRENT = 'current';
@@ -23,9 +29,17 @@ final class AliasResolver
/** @var MigrationRepository */
private $migrationRepository;
- public function __construct(MigrationRepository $migrationRepository)
+ /** @var MetadataStorage */
+ private $metadataStorage;
+
+ /** @var MigrationPlanCalculator */
+ private $migrationPlanCalculator;
+
+ public function __construct(MigrationRepository $migrationRepository, MetadataStorage $metadataStorage, MigrationPlanCalculator $migrationPlanCalculator)
{
- $this->migrationRepository = $migrationRepository;
+ $this->migrationRepository = $migrationRepository;
+ $this->metadataStorage = $metadataStorage;
+ $this->migrationPlanCalculator = $migrationPlanCalculator;
}
/**
@@ -41,29 +55,66 @@ public function __construct(MigrationRepository $migrationRepository)
*
* If an existing version number is specified, it is returned verbatimly.
*/
- public function resolveVersionAlias(string $alias) : ?string
+ public function resolveVersionAlias(string $alias) : Version
{
- if ($this->migrationRepository->hasVersion($alias)) {
- return $alias;
- }
+ $availableMigrations = $this->migrationRepository->getMigrations();
+ $executedMigrations = $this->metadataStorage->getExecutedMigrations();
switch ($alias) {
case self::ALIAS_FIRST:
- return '0';
+ if (count($availableMigrations) === 0) {
+ throw NoMigrationsToExecute::new();
+ }
+
+ return $availableMigrations->getFirst()->getVersion();
case self::ALIAS_CURRENT:
- return $this->migrationRepository->getCurrentVersion();
+ try {
+ return $executedMigrations->getLast()->getVersion();
+ } catch (NoMigrationsFoundWithCriteria $e) {
+ return new Version('0');
+ }
+ break;
case self::ALIAS_PREV:
- return $this->migrationRepository->getPrevVersion();
+ try {
+ return $executedMigrations->getLast(-1)->getVersion();
+ } catch (NoMigrationsFoundWithCriteria $e) {
+ return new Version('0');
+ }
+ break;
case self::ALIAS_NEXT:
- return $this->migrationRepository->getNextVersion();
+ $newMigrations = $this->migrationPlanCalculator->getNewMigrations();
+
+ try {
+ return $newMigrations->getFirst()->getVersion();
+ } catch (NoMigrationsFoundWithCriteria $e) {
+ throw NoMigrationsToExecute::new($e);
+ }
+ break;
case self::ALIAS_LATEST:
- return $this->migrationRepository->getLatestVersion();
+ try {
+ return $availableMigrations->getLast()->getVersion();
+ } catch (NoMigrationsFoundWithCriteria $e) {
+ throw NoMigrationsToExecute::new($e);
+ }
+ break;
default:
- if (substr($alias, 0, 7) === self::ALIAS_CURRENT) {
- return $this->migrationRepository->getDeltaVersion(substr($alias, 7));
+ if ($availableMigrations->hasMigration(new Version($alias))) {
+ return $availableMigrations->getMigration(new Version($alias))->getVersion();
}
- return null;
+ if (substr($alias, 0, 7) === self::ALIAS_CURRENT) {
+ $val = (int) substr($alias, 7);
+ $targetMigration = null;
+ if ($val > 0) {
+ $newMigrations = $this->migrationPlanCalculator->getNewMigrations();
+
+ return $newMigrations->getFirst($val - 1)->getVersion();
+ }
+
+ return $executedMigrations->getLast($val)->getVersion();
+ }
}
+
+ throw UnknownMigrationVersion::new($alias);
}
}
diff --git a/lib/Doctrine/Migrations/Version/AliasResolverInterface.php b/lib/Doctrine/Migrations/Version/AliasResolverInterface.php
new file mode 100644
index 0000000000..c6e9bd7784
--- /dev/null
+++ b/lib/Doctrine/Migrations/Version/AliasResolverInterface.php
@@ -0,0 +1,28 @@
+sql = $sql;
- $this->params = $params;
- $this->types = $types;
+ $this->executedAt = $executedAt;
+ $this->version = $version;
+ $this->direction = $direction;
+ }
+
+ public function getDirection() : string
+ {
+ return $this->direction;
+ }
+
+ public function getExecutedAt() : ?DateTimeImmutable
+ {
+ return $this->executedAt;
+ }
+
+ public function setExecutedAt(DateTimeImmutable $executedAt) : void
+ {
+ $this->executedAt = $executedAt;
+ }
+
+ public function getVersion() : Version
+ {
+ return $this->version;
}
public function hasSql() : bool
@@ -70,10 +98,14 @@ public function getSql() : array
/**
* @param string[] $sql
+ * @param mixed[] $params
+ * @param int[] $types
*/
- public function setSql(array $sql) : void
+ public function setSql(array $sql, array $params = [], array $types = []) : void
{
- $this->sql = $sql;
+ $this->sql = $sql;
+ $this->params = $params;
+ $this->types = $types;
}
/**
@@ -84,14 +116,6 @@ public function getParams() : array
return $this->params;
}
- /**
- * @param mixed[] $params
- */
- public function setParams(array $params) : void
- {
- $this->params = $params;
- }
-
/**
* @return mixed[]
*/
@@ -100,14 +124,6 @@ public function getTypes() : array
return $this->types;
}
- /**
- * @param mixed[] $types
- */
- public function setTypes(array $types) : void
- {
- $this->types = $types;
- }
-
public function getTime() : ?float
{
return $this->time;
@@ -138,9 +154,10 @@ public function isSkipped() : bool
return $this->skipped;
}
- public function setError(bool $error) : void
+ public function setError(bool $error, ?Throwable $exception = null) : void
{
- $this->error = $error;
+ $this->error = $error;
+ $this->exception = $exception;
}
public function hasError() : bool
@@ -148,11 +165,6 @@ public function hasError() : bool
return $this->error;
}
- public function setException(Throwable $exception) : void
- {
- $this->exception = $exception;
- }
-
public function getException() : ?Throwable
{
return $this->exception;
@@ -171,4 +183,14 @@ public function getToSchema() : Schema
return $this->toSchema;
}
+
+ public function getState() : int
+ {
+ return $this->state;
+ }
+
+ public function setState(int $state) : void
+ {
+ $this->state = $state;
+ }
}
diff --git a/lib/Doctrine/Migrations/Version/Executor.php b/lib/Doctrine/Migrations/Version/Executor.php
index 76d2798e12..cd5a016859 100644
--- a/lib/Doctrine/Migrations/Version/Executor.php
+++ b/lib/Doctrine/Migrations/Version/Executor.php
@@ -4,22 +4,23 @@
namespace Doctrine\Migrations\Version;
+use DateTimeImmutable;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\EventDispatcher;
use Doctrine\Migrations\Events;
use Doctrine\Migrations\Exception\SkipMigration;
+use Doctrine\Migrations\Metadata\MigrationPlan;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\MigratorConfiguration;
-use Doctrine\Migrations\OutputWriter;
use Doctrine\Migrations\ParameterFormatterInterface;
-use Doctrine\Migrations\Provider\SchemaDiffProviderInterface;
+use Doctrine\Migrations\Provider\SchemaDiffProvider;
use Doctrine\Migrations\Stopwatch;
use Doctrine\Migrations\Tools\BytesFormatter;
+use Psr\Log\LoggerInterface;
use Throwable;
use function count;
-use function rtrim;
-use function sprintf;
use function ucfirst;
/**
@@ -29,25 +30,19 @@
*/
final class Executor implements ExecutorInterface
{
- /** @var Configuration */
- private $configuration;
-
/** @var Connection */
private $connection;
- /** @var SchemaDiffProviderInterface */
+ /** @var SchemaDiffProvider */
private $schemaProvider;
- /** @var OutputWriter */
- private $outputWriter;
-
/** @var ParameterFormatterInterface */
private $parameterFormatter;
/** @var Stopwatch */
private $stopwatch;
- /** @var string[] */
+ /** @var array */
private $sql = [];
/** @var mixed[] */
@@ -56,20 +51,31 @@ final class Executor implements ExecutorInterface
/** @var mixed[] */
private $types = [];
+ /** @var MetadataStorage */
+ private $metadataStorage;
+
+ /** @var LoggerInterface */
+ private $logger;
+
+ /** @var EventDispatcher */
+ private $dispatcher;
+
public function __construct(
- Configuration $configuration,
+ MetadataStorage $metadataStorage,
+ EventDispatcher $dispatcher,
Connection $connection,
- SchemaDiffProviderInterface $schemaProvider,
- OutputWriter $outputWriter,
+ SchemaDiffProvider $schemaProvider,
+ LoggerInterface $logger,
ParameterFormatterInterface $parameterFormatter,
Stopwatch $stopwatch
) {
- $this->configuration = $configuration;
$this->connection = $connection;
$this->schemaProvider = $schemaProvider;
- $this->outputWriter = $outputWriter;
$this->parameterFormatter = $parameterFormatter;
$this->stopwatch = $stopwatch;
+ $this->metadataStorage = $metadataStorage;
+ $this->logger = $logger;
+ $this->dispatcher = $dispatcher;
}
/**
@@ -112,69 +118,51 @@ public function addSql(string $sql, array $params = [], array $types = []) : voi
}
public function execute(
- Version $version,
- AbstractMigration $migration,
- string $direction,
- ?MigratorConfiguration $migratorConfiguration = null
+ MigrationPlan $plan,
+ MigratorConfiguration $configuration
) : ExecutionResult {
- $migratorConfiguration = $migratorConfiguration ?? new MigratorConfiguration();
-
- $versionExecutionResult = new ExecutionResult();
+ $result = new ExecutionResult($plan->getVersion(), $plan->getDirection(), new DateTimeImmutable());
- $this->startMigration($version, $migration, $direction, $migratorConfiguration);
+ $this->startMigration($plan, $configuration);
try {
$this->executeMigration(
- $version,
- $migration,
- $versionExecutionResult,
- $direction,
- $migratorConfiguration
+ $plan,
+ $result,
+ $configuration
);
- $versionExecutionResult->setSql($this->sql);
- $versionExecutionResult->setParams($this->params);
- $versionExecutionResult->setTypes($this->types);
+ $result->setSql($this->sql, $this->params, $this->types);
} catch (SkipMigration $e) {
- $this->skipMigration(
- $e,
- $version,
- $migration,
- $direction,
- $migratorConfiguration
- );
+ $result->setSkipped(true);
- $versionExecutionResult->setSkipped(true);
+ $this->migrationEnd($e, $plan, $result, $configuration);
} catch (Throwable $e) {
- $this->migrationError($e, $version, $migration);
+ $result->setError(true, $e);
- $versionExecutionResult->setError(true);
- $versionExecutionResult->setException($e);
+ $this->migrationEnd($e, $plan, $result, $configuration);
throw $e;
}
- return $versionExecutionResult;
+ return $result;
}
private function startMigration(
- Version $version,
- AbstractMigration $migration,
- string $direction,
- MigratorConfiguration $migratorConfiguration
+ MigrationPlan $plan,
+ MigratorConfiguration $configuration
) : void {
$this->sql = [];
$this->params = [];
$this->types = [];
- $this->configuration->dispatchVersionEvent(
- $version,
+ $this->dispatcher->dispatchVersionEvent(
Events::onMigrationsVersionExecuting,
- $direction,
- $migratorConfiguration->isDryRun()
+ $plan,
+ $configuration
);
- if (! $migration->isTransactional()) {
+ if (! $plan->getMigration()->isTransactional()) {
return;
}
@@ -183,74 +171,72 @@ private function startMigration(
}
private function executeMigration(
- Version $version,
- AbstractMigration $migration,
- ExecutionResult $versionExecutionResult,
- string $direction,
- MigratorConfiguration $migratorConfiguration
+ MigrationPlan $plan,
+ ExecutionResult $result,
+ MigratorConfiguration $configuration
) : ExecutionResult {
$stopwatchEvent = $this->stopwatch->start('execute');
- $version->setState(State::PRE);
+ $migration = $plan->getMigration();
+ $direction = $plan->getDirection();
+
+ $result->setState(State::PRE);
- $fromSchema = $this->getFromSchema($migratorConfiguration);
+ $fromSchema = $this->getFromSchema($configuration);
$migration->{'pre' . ucfirst($direction)}($fromSchema);
- $this->outputWriter->write("\n" . $this->getMigrationHeader($version, $migration, $direction) . "\n");
+ $this->logger->info(...$this->getMigrationHeader($plan, $migration, $direction));
- $version->setState(State::EXEC);
+ $result->setState(State::EXEC);
$toSchema = $this->schemaProvider->createToSchema($fromSchema);
- $versionExecutionResult->setToSchema($toSchema);
+ $result->setToSchema($toSchema);
$migration->$direction($toSchema);
+ foreach ($migration->getSql() as $sqlData) {
+ $this->addSql(...$sqlData);
+ }
+
foreach ($this->schemaProvider->getSqlDiffToMigrate($fromSchema, $toSchema) as $sql) {
$this->addSql($sql);
}
if (count($this->sql) !== 0) {
- if (! $migratorConfiguration->isDryRun()) {
- $this->executeVersionExecutionResult($version, $migratorConfiguration);
+ if (! $configuration->isDryRun()) {
+ $this->executeResult($configuration);
} else {
foreach ($this->sql as $idx => $query) {
$this->outputSqlQuery($idx, $query);
}
}
} else {
- $this->outputWriter->write(sprintf(
- 'Migration %s was executed but did not result in any SQL statements.',
- $version->getVersion()
- ));
+ $this->logger->warning('Migration {version} was executed but did not result in any SQL statements.', [
+ 'version' => (string) $plan->getVersion(),
+ ]);
}
- $version->setState(State::POST);
+ $result->setState(State::POST);
$migration->{'post' . ucfirst($direction)}($toSchema);
+ $stopwatchEvent->stop();
- if (! $migratorConfiguration->isDryRun()) {
- $version->markVersion($direction);
- }
+ $result->setTime($stopwatchEvent->getDuration());
+ $result->setMemory($stopwatchEvent->getMemory());
- $stopwatchEvent->stop();
+ $params = [
+ 'version' => (string) $plan->getVersion(),
+ 'time' => $stopwatchEvent->getDuration(),
+ 'memory' => BytesFormatter::formatBytes($stopwatchEvent->getMemory()),
+ 'direction' => $direction === Direction::UP ? 'migrated' : 'reverted',
+ ];
- $versionExecutionResult->setTime($stopwatchEvent->getDuration());
- $versionExecutionResult->setMemory($stopwatchEvent->getMemory());
+ $this->logger->info('Migration {version} {direction} (took {time}ms, used {memory} memory)', $params);
- if ($direction === Direction::UP) {
- $this->outputWriter->write(sprintf(
- "\n ++ migrated (took %sms, used %s memory)",
- $stopwatchEvent->getDuration(),
- BytesFormatter::formatBytes($stopwatchEvent->getMemory())
- ));
- } else {
- $this->outputWriter->write(sprintf(
- "\n -- reverted (took %sms, used %s memory)",
- $stopwatchEvent->getDuration(),
- BytesFormatter::formatBytes($stopwatchEvent->getMemory())
- ));
+ if (! $configuration->isDryRun()) {
+ $this->metadataStorage->complete($result);
}
if ($migration->isTransactional()) {
@@ -258,104 +244,107 @@ private function executeMigration(
$this->connection->commit();
}
- $version->setState(State::NONE);
+ $plan->markAsExecuted($result);
+ $result->setState(State::NONE);
- $this->configuration->dispatchVersionEvent(
- $version,
+ $this->dispatcher->dispatchVersionEvent(
Events::onMigrationsVersionExecuted,
- $direction,
- $migratorConfiguration->isDryRun()
+ $plan,
+ $configuration
);
- return $versionExecutionResult;
+ return $result;
}
- private function getMigrationHeader(Version $version, AbstractMigration $migration, string $direction) : string
+ /**
+ * @return mixed[]
+ */
+ private function getMigrationHeader(MigrationPlan $planItem, AbstractMigration $migration, string $direction) : array
{
- $versionInfo = $version->getVersion();
+ $versionInfo = (string) $planItem->getVersion();
$description = $migration->getDescription();
if ($description !== '') {
$versionInfo .= ' (' . $description . ')';
}
+ $params = ['version_name' => $versionInfo];
+
if ($direction === Direction::UP) {
- return sprintf(' ++ migrating %s', $versionInfo);
+ return ['++ migrating {version_name}', $params];
}
- return sprintf(' -- reverting %s', $versionInfo);
+ return ['++ reverting {version_name}', $params];
}
- private function skipMigration(
- SkipMigration $e,
- Version $version,
- AbstractMigration $migration,
- string $direction,
- MigratorConfiguration $migratorConfiguration
- ) : void {
+ private function migrationEnd(Throwable $e, MigrationPlan $plan, ExecutionResult $result, MigratorConfiguration $configuration) : void
+ {
+ $migration = $plan->getMigration();
if ($migration->isTransactional()) {
//only rollback transaction if in transactional mode
$this->connection->rollBack();
}
- if (! $migratorConfiguration->isDryRun()) {
- $version->markVersion($direction);
- }
-
- $this->outputWriter->write(sprintf("\n SS skipped (Reason: %s)", $e->getMessage()));
-
- $version->setState(State::NONE);
-
- $this->configuration->dispatchVersionEvent(
- $version,
+ $plan->markAsExecuted($result);
+ $this->logResult($e, $result, $plan);
+ $this->dispatcher->dispatchVersionEvent(
Events::onMigrationsVersionSkipped,
- $direction,
- $migratorConfiguration->isDryRun()
+ $plan,
+ $configuration
);
+
+ if ($configuration->isDryRun() || $result->isSkipped() || $result->hasError()) {
+ return;
+ }
+
+ $this->metadataStorage->complete($result);
}
- /**
- * @throws Throwable
- */
- private function migrationError(Throwable $e, Version $version, AbstractMigration $migration) : void
+ private function logResult(Throwable $e, ExecutionResult $result, MigrationPlan $plan) : void
{
- $this->outputWriter->write(sprintf(
- 'Migration %s failed during %s. Error %s',
- $version->getVersion(),
- $version->getExecutionState(),
- $e->getMessage()
- ));
-
- if ($migration->isTransactional()) {
- //only rollback transaction if in transactional mode
- $this->connection->rollBack();
+ if ($result->isSkipped()) {
+ $this->logger->error(
+ 'Migration {version} skipped during {state}. Reason: "{reason}"',
+ [
+ 'version' => (string) $plan->getVersion(),
+ 'reason' => $e->getMessage(),
+ 'state' => $this->getExecutionStateAsString($result->getState()),
+ ]
+ );
+ } elseif ($result->hasError()) {
+ $this->logger->error(
+ 'Migration {version} failed during {state}. Error: "{error}"',
+ [
+ 'version' => (string) $plan->getVersion(),
+ 'error' => $e->getMessage(),
+ 'state' => $this->getExecutionStateAsString($result->getState()),
+ ]
+ );
}
-
- $version->setState(State::NONE);
}
- private function executeVersionExecutionResult(
- Version $version,
- MigratorConfiguration $migratorConfiguration
- ) : void {
+ private function executeResult(MigratorConfiguration $configuration) : void
+ {
foreach ($this->sql as $key => $query) {
$stopwatchEvent = $this->stopwatch->start('query');
$this->outputSqlQuery($key, $query);
if (! isset($this->params[$key])) {
- $this->connection->executeQuery($query);
+ $this->connection->executeUpdate($query);
} else {
- $this->connection->executeQuery($query, $this->params[$key], $this->types[$key]);
+ $this->connection->executeUpdate($query, $this->params[$key], $this->types[$key]);
}
$stopwatchEvent->stop();
- if (! $migratorConfiguration->getTimeAllQueries()) {
+ if (! $configuration->getTimeAllQueries()) {
continue;
}
- $this->outputWriter->write(sprintf(' %sms', $stopwatchEvent->getDuration()));
+ $this->logger->debug('{duration}ms', [
+ 'duration' => $stopwatchEvent->getDuration(),
+ ]);
}
}
@@ -377,20 +366,33 @@ private function outputSqlQuery(int $idx, string $query) : void
$this->types[$idx] ?? []
);
- $this->outputWriter->write(rtrim(sprintf(
- ' -> %s %s',
- $query,
- $params
- )));
+ $this->logger->debug('{query} {params}', [
+ 'query' => $query,
+ 'params' => $params,
+ ]);
}
- private function getFromSchema(MigratorConfiguration $migratorConfiguration) : Schema
+ private function getFromSchema(MigratorConfiguration $configuration) : Schema
{
// if we're in a dry run, use the from Schema instead of reading the schema from the database
- if ($migratorConfiguration->isDryRun() && $migratorConfiguration->getFromSchema() !== null) {
- return $migratorConfiguration->getFromSchema();
+ if ($configuration->isDryRun() && $configuration->getFromSchema() !== null) {
+ return $configuration->getFromSchema();
}
return $this->schemaProvider->createFromSchema();
}
+
+ private function getExecutionStateAsString(int $state) : string
+ {
+ switch ($state) {
+ case State::PRE:
+ return 'Pre-Checks';
+ case State::POST:
+ return 'Post-Checks';
+ case State::EXEC:
+ return 'Execution';
+ default:
+ return 'No State';
+ }
+ }
}
diff --git a/lib/Doctrine/Migrations/Version/ExecutorInterface.php b/lib/Doctrine/Migrations/Version/ExecutorInterface.php
index 5d132566ad..7f3f38ddc6 100644
--- a/lib/Doctrine/Migrations/Version/ExecutorInterface.php
+++ b/lib/Doctrine/Migrations/Version/ExecutorInterface.php
@@ -4,7 +4,7 @@
namespace Doctrine\Migrations\Version;
-use Doctrine\Migrations\AbstractMigration;
+use Doctrine\Migrations\Metadata\MigrationPlan;
use Doctrine\Migrations\MigratorConfiguration;
/**
@@ -20,10 +20,5 @@ interface ExecutorInterface
*/
public function addSql(string $sql, array $params = [], array $types = []) : void;
- public function execute(
- Version $version,
- AbstractMigration $migration,
- string $direction,
- ?MigratorConfiguration $migratorConfiguration = null
- ) : ExecutionResult;
+ public function execute(MigrationPlan $plan, MigratorConfiguration $migratorConfiguration) : ExecutionResult;
}
diff --git a/lib/Doctrine/Migrations/Version/Factory.php b/lib/Doctrine/Migrations/Version/Factory.php
deleted file mode 100644
index 9e25c09313..0000000000
--- a/lib/Doctrine/Migrations/Version/Factory.php
+++ /dev/null
@@ -1,38 +0,0 @@
-configuration = $configuration;
- $this->versionExecutor = $versionExecutor;
- }
-
- public function createVersion(string $version, string $migrationClassName) : Version
- {
- return new Version(
- $this->configuration,
- $version,
- $migrationClassName,
- $this->versionExecutor
- );
- }
-}
diff --git a/lib/Doctrine/Migrations/Version/MigrationFactory.php b/lib/Doctrine/Migrations/Version/MigrationFactory.php
new file mode 100644
index 0000000000..eb4c65346e
--- /dev/null
+++ b/lib/Doctrine/Migrations/Version/MigrationFactory.php
@@ -0,0 +1,38 @@
+connection = $connection;
+ $this->logger = $logger;
+ }
+
+ public function createVersion(string $migrationClassName) : AbstractMigration
+ {
+ return new $migrationClassName(
+ $this->connection,
+ $this->logger
+ );
+ }
+}
diff --git a/lib/Doctrine/Migrations/Version/Version.php b/lib/Doctrine/Migrations/Version/Version.php
index 160bf81125..5f10112d25 100644
--- a/lib/Doctrine/Migrations/Version/Version.php
+++ b/lib/Doctrine/Migrations/Version/Version.php
@@ -4,237 +4,26 @@
namespace Doctrine\Migrations\Version;
-use DateTimeImmutable;
-use DateTimeZone;
-use Doctrine\DBAL\Connection;
-use Doctrine\DBAL\Types\Type;
-use Doctrine\Migrations\AbstractMigration;
-use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Exception\MigrationNotConvertibleToSql;
-use Doctrine\Migrations\MigratorConfiguration;
-use Doctrine\Migrations\OutputWriter;
-use Doctrine\Migrations\Tracking\TableDefinition;
-use function assert;
-use function count;
-use function date_default_timezone_get;
-use function in_array;
-use function str_replace;
-
-/**
- * The Version class represents a single migration version. It wraps around your migration class
- * that extends the AbstractMigration class.
- *
- * @internal
- */
-class Version
+final class Version
{
- /** @var Configuration */
- private $configuration;
-
- /** @var OutputWriter */
- private $outputWriter;
-
/** @var string */
private $version;
- /** @var AbstractMigration */
- private $migration;
-
- /** @var Connection */
- private $connection;
-
- /** @var string */
- private $class;
-
- /** @var int */
- private $state = State::NONE;
-
- /** @var ExecutorInterface */
- private $versionExecutor;
-
- public function __construct(
- Configuration $configuration,
- string $version,
- string $class,
- ExecutorInterface $versionExecutor
- ) {
- $this->configuration = $configuration;
- $this->outputWriter = $configuration->getOutputWriter();
- $this->class = $class;
- $this->connection = $configuration->getConnection();
- $this->migration = new $class($this);
- $this->version = $version;
- $this->versionExecutor = $versionExecutor;
- }
-
- public function __toString() : string
+ public function __construct(string $version)
{
- return $this->version;
+ $this->version = $version;
}
- public function getVersion() : string
+ public function __toString()
{
return $this->version;
}
- public function getDateTime() : string
- {
- $datetime = str_replace('Version', '', $this->version);
- $datetime = DateTimeImmutable::createFromFormat('YmdHis', $datetime);
-
- if ($datetime === false) {
- return '';
- }
-
- return $datetime->format('Y-m-d H:i:s');
- }
-
- public function getConfiguration() : Configuration
- {
- return $this->configuration;
- }
-
- public function getMigration() : AbstractMigration
- {
- return $this->migration;
- }
-
- public function isMigrated() : bool
- {
- return $this->configuration->hasVersionMigrated($this);
- }
-
- public function getExecutedAt() : ?DateTimeImmutable
- {
- $versionData = $this->configuration->getVersionData($this);
- $executedAtColumnName = $this->configuration->getMigrationsExecutedAtColumnName();
-
- if (! isset($versionData[$executedAtColumnName])) {
- return null;
- }
-
- return (new DateTimeImmutable($versionData[$executedAtColumnName], new DateTimeZone('UTC')))
- ->setTimezone(new DateTimeZone(date_default_timezone_get()));
- }
-
- public function setState(int $state) : void
- {
- assert(in_array($state, State::STATES, true));
-
- $this->state = $state;
- }
-
- public function getExecutionState() : string
- {
- switch ($this->state) {
- case State::PRE:
- return 'Pre-Checks';
- case State::POST:
- return 'Post-Checks';
- case State::EXEC:
- return 'Execution';
- default:
- return 'No State';
- }
- }
-
/**
- * @param mixed[] $params
- * @param mixed[] $types
+ * @param mixed $object
*/
- public function addSql(string $sql, array $params = [], array $types = []) : void
- {
- $this->versionExecutor->addSql($sql, $params, $types);
- }
-
- public function writeSqlFile(
- string $path,
- string $direction = Direction::UP
- ) : bool {
- $versionExecutionResult = $this->execute(
- $direction,
- $this->getWriteSqlFileMigratorConfig()
- );
-
- if (count($versionExecutionResult->getParams()) !== 0) {
- throw MigrationNotConvertibleToSql::new($this->class);
- }
-
- $this->outputWriter->write("\n-- Version " . $this->version . "\n");
-
- $sqlQueries = [$this->version => $versionExecutionResult->getSql()];
-
- /*
- * Since the configuration object changes during the creation we cannot inject things
- * properly, so I had to violate LoD here (so please, let's find a way to solve it on v2).
- */
- return $this->configuration
- ->getQueryWriter()
- ->write($path, $direction, $sqlQueries);
- }
-
- public function execute(
- string $direction,
- ?MigratorConfiguration $migratorConfiguration = null
- ) : ExecutionResult {
- return $this->versionExecutor->execute(
- $this,
- $this->migration,
- $direction,
- $migratorConfiguration
- );
- }
-
- public function markMigrated() : void
- {
- $this->markVersion(Direction::UP);
- }
-
- public function markNotMigrated() : void
- {
- $this->markVersion(Direction::DOWN);
- }
-
- public function markVersion(string $direction) : void
- {
- $this->configuration->createMigrationTable();
-
- $migrationsColumnName = $this->configuration
- ->getQuotedMigrationsColumnName();
-
- $migrationsExecutedAtColumnName = $this->configuration
- ->getQuotedMigrationsExecutedAtColumnName();
-
- if ($direction === Direction::UP) {
- $this->connection->insert(
- $this->configuration->getMigrationsTableName(),
- [
- $migrationsColumnName => $this->version,
- $migrationsExecutedAtColumnName => $this->getExecutedAtDatabaseValue(),
- ]
- );
-
- return;
- }
-
- $this->connection->delete(
- $this->configuration->getMigrationsTableName(),
- [
- $migrationsColumnName => $this->version,
- ]
- );
- }
-
- private function getWriteSqlFileMigratorConfig() : MigratorConfiguration
- {
- return (new MigratorConfiguration())->setDryRun(true);
- }
-
- private function getExecutedAtDatabaseValue() : string
+ public function equals($object) : bool
{
- return Type::getType(TableDefinition::MIGRATION_EXECUTED_AT_COLUMN_TYPE)->convertToDatabaseValue(
- (new DateTimeImmutable('now'))->setTimezone(new DateTimeZone('UTC')),
- $this->connection->getDatabasePlatform()
- );
+ return $object instanceof self && $object->version === $this->version;
}
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 4ea840a08c..6e8795ba88 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -15,11 +15,6 @@
-
- lib/Doctrine/Migrations/FileQueryWriter.php
- tests/Doctrine/Migrations/Tests/realpath.php
-
-
*/tests/*
@@ -36,8 +31,13 @@
lib/Doctrine/Migrations/MigrationsVersion.php
-
- lib/Doctrine/Migrations/Configuration/AbstractFileConfiguration.php
+
+ tests/Doctrine/Migrations/Tests/TestLogger.php
+ lib/Doctrine/Migrations/Tools/Console/ConsoleLogger.php
+
+
+
+ lib/Doctrine/Migrations/Version/Version.php
@@ -47,17 +47,18 @@
lib/Doctrine/Migrations/AbstractMigration.php
tests/Doctrine/Migrations/Tests/Configuration/AbstractConfigurationTest.php
tests/Doctrine/Migrations/Tests/Tools/Console/Command/AbstractCommandTest.php
+ tests/Doctrine/Migrations/Tests/Configuration/Loader/AbstractLoaderTest.php
+ lib/Doctrine/Migrations/Configuration/Loader/AbstractFileLoader.php
lib/Doctrine/Migrations/Configuration/Connection/ConnectionLoaderInterface.php
- lib/Doctrine/Migrations/Provider/SchemaDiffProviderInterface.php
- lib/Doctrine/Migrations/Provider/SchemaProviderInterface.php
lib/Doctrine/Migrations/Tools/Console/Helper/ConfigurationHelperInterface.php
lib/Doctrine/Migrations/Finder/MigrationFinderInterface.php
- lib/Doctrine/Migrations/Finder/MigrationDeepFinderInterface.php
lib/Doctrine/Migrations/Version/ExecutorInterface.php
lib/Doctrine/Migrations/ParameterFormatterInterface.php
- lib/Doctrine/Migrations/Version/VersionInterface.php
+ lib/Doctrine/Migrations/MigratorInterface.php
+ lib/Doctrine/Migrations/Generator/FileBuilderInterface.php
+ lib/Doctrine/Migrations/Version/AliasResolverInterface.php
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 1722859116..b6626b3243 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -6,19 +6,28 @@ parameters:
autoload_directories:
- %currentWorkingDirectory%/tests/Doctrine/Migrations/Tests/Finder/_features
- %currentWorkingDirectory%/tests/Doctrine/Migrations/Tests/Finder/_files
- - %currentWorkingDirectory%/tests/Doctrine/Migrations/Tests/Finder/_regression
- - %currentWorkingDirectory%/tests/Doctrine/Migrations/Tests/Functional/_files
- autoload_files:
+ excludes_analyse:
- %currentWorkingDirectory%/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationTestSource/Migrations/Version123.php
- - %currentWorkingDirectory%/tests/Doctrine/Migrations/Tests/realpath.php
ignoreErrors:
# Ignore proxy manager magic
- '~ProxyManager\\Proxy\\VirtualProxyInterface~'
- - '~^Parameter #1 \$files of method Doctrine\\Migrations\\Finder\\Finder::loadMigrationClasses\(\) expects array, array given\.\z~'
- - '~^Class Doctrine\\Migrations\\Tests\\DoesNotExistAtAll not found\.\z~'
+ - '~Variable method call on Doctrine\\Migrations\\AbstractMigration~'
+ -
+ message: '~^Variable property access on mixed\.$~'
+ path: %currentWorkingDirectory%/lib/Doctrine/Migrations/Configuration/Loader/XmlFileLoader.php
+ -
+ message: '~^Call to function is_bool\(\) with bool will always evaluate to true\.$~'
+ path: %currentWorkingDirectory%/lib/Doctrine/Migrations/ParameterFormatter.php
+ -
+ message: '~^Call to an undefined method Symfony\\Component\\Console\\Output\\OutputInterface\:\:getErrorOutput\(\)\.$~'
+ path: %currentWorkingDirectory%/lib/Doctrine/Migrations/Tools/Console/ConsoleLogger.php
+
+ symfony:
+ console_application_loader: %currentWorkingDirectory%/tests/Doctrine/Migrations/Tests/doctrine-migrations-phpstan-app.php
includes:
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
- vendor/phpstan/phpstan-strict-rules/rules.neon
+ - vendor/phpstan/phpstan-symfony/extension.neon
diff --git a/tests/Doctrine/Migrations/Tests/AbstractMigrationTest.php b/tests/Doctrine/Migrations/Tests/AbstractMigrationTest.php
index e674d9b70f..c2bbfa7964 100644
--- a/tests/Doctrine/Migrations/Tests/AbstractMigrationTest.php
+++ b/tests/Doctrine/Migrations/Tests/AbstractMigrationTest.php
@@ -4,49 +4,24 @@
namespace Doctrine\Migrations\Tests;
-use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Exception\AbortMigration;
use Doctrine\Migrations\Exception\IrreversibleMigration;
use Doctrine\Migrations\Exception\SkipMigration;
-use Doctrine\Migrations\OutputWriter;
use Doctrine\Migrations\Tests\Stub\AbstractMigrationStub;
-use Doctrine\Migrations\Tests\Stub\VersionDummy;
-use Doctrine\Migrations\Version\ExecutorInterface;
-use Doctrine\Migrations\Version\Version;
-use function sys_get_temp_dir;
class AbstractMigrationTest extends MigrationTestCase
{
- /** @var Configuration */
- private $config;
-
- /** @var Version */
- private $version;
-
/** @var AbstractMigrationStub */
private $migration;
- /** @var OutputWriter */
- private $outputWriter;
+ /** @var TestLogger */
+ private $logger;
protected function setUp() : void
{
- $this->outputWriter = $this->getOutputWriter();
-
- $this->config = new Configuration($this->getSqliteConnection(), $this->outputWriter);
- $this->config->setMigrationsDirectory(sys_get_temp_dir());
- $this->config->setMigrationsNamespace('DoctrineMigrations\\');
-
- $versionExecutor = $this->createMock(ExecutorInterface::class);
-
- $this->version = new Version(
- $this->config,
- 'Dummy',
- VersionDummy::class,
- $versionExecutor
- );
+ $this->logger = new TestLogger();
- $this->migration = new AbstractMigrationStub($this->version);
+ $this->migration = new AbstractMigrationStub($this->getSqliteConnection(), $this->logger);
}
public function testGetDescriptionReturnsEmptyString() : void
@@ -54,28 +29,36 @@ public function testGetDescriptionReturnsEmptyString() : void
self::assertSame('', $this->migration->getDescription());
}
+ public function testAddSql() : void
+ {
+ $this->migration->exposedAddSql('SELECT 1', [1], [2]);
+
+ self::assertSame([['SELECT 1', [1], [2]]], $this->migration->getSql());
+ }
+
public function testWarnIfOutputMessage() : void
{
$this->migration->warnIf(true, 'Warning was thrown');
- self::assertContains('Warning during No State: Warning was thrown', $this->getOutputStreamContent($this->output));
+
+ self::assertContains('Warning was thrown', $this->getLogOutput($this->logger));
}
public function testWarnIfAddDefaultMessage() : void
{
$this->migration->warnIf(true);
- self::assertContains('Warning during No State: Unknown Reason', $this->getOutputStreamContent($this->output));
+ self::assertContains('Unknown Reason', $this->getLogOutput($this->logger));
}
public function testWarnIfDontOutputMessageIfFalse() : void
{
$this->migration->warnIf(false, 'trallala');
- self::assertSame('', $this->getOutputStreamContent($this->output));
+ self::assertSame('', $this->getLogOutput($this->logger));
}
public function testWriteInvokesOutputWriter() : void
{
$this->migration->exposedWrite('Message');
- self::assertContains('Message', $this->getOutputStreamContent($this->output));
+ self::assertContains('Message', $this->getLogOutput($this->logger));
}
public function testAbortIfThrowsException() : void
diff --git a/tests/Doctrine/Migrations/Tests/BoxPharCompileTest.php b/tests/Doctrine/Migrations/Tests/BoxPharCompileTest.php
index 364dfa0319..4197405b41 100644
--- a/tests/Doctrine/Migrations/Tests/BoxPharCompileTest.php
+++ b/tests/Doctrine/Migrations/Tests/BoxPharCompileTest.php
@@ -27,7 +27,12 @@ public function testCompile() : void
assert($boxPharPath !== false);
- $process = new Process(['php', $boxPharPath, 'compile', '-vvv']);
+ $process = new Process([
+ 'php',
+ $boxPharPath,
+ 'compile',
+ '-vvv',
+ ]);
$process->run();
$doctrinePharPath = realpath(__DIR__ . '/../../../../build/doctrine-migrations.phar');
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/AbstractConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Configuration/AbstractConfigurationTest.php
deleted file mode 100644
index 86b8c433e5..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/AbstractConfigurationTest.php
+++ /dev/null
@@ -1,193 +0,0 @@
-loadConfiguration();
- self::assertSame(__DIR__ . DIRECTORY_SEPARATOR . '_files', $config->getMigrationsDirectory());
- }
-
- public function testMigrationNamespace() : void
- {
- $config = $this->loadConfiguration();
- self::assertSame('DoctrineMigrationsTest', $config->getMigrationsNamespace());
- }
-
- public function testMigrationName() : void
- {
- $config = $this->loadConfiguration();
- self::assertSame('Doctrine Sandbox Migrations', $config->getName());
- }
-
- public function testMigrationsTable() : void
- {
- $config = $this->loadConfiguration();
- self::assertSame('doctrine_migration_versions_test', $config->getMigrationsTableName());
- }
-
- public function testMigrationsColumnName() : void
- {
- $config = $this->loadConfiguration();
- self::assertSame('doctrine_migration_column_test', $config->getMigrationsColumnName());
- }
-
- public function testMigrationsColumnLength() : void
- {
- $config = $this->loadConfiguration();
- self::assertSame(200, $config->getMigrationsColumnLength());
- }
-
- public function testAllOrNothing() : void
- {
- $config = $this->loadConfiguration();
-
- self::assertTrue($config->isAllOrNothing());
- }
-
- public function testMigrationsExecutedAtColumnName() : void
- {
- $config = $this->loadConfiguration();
- self::assertSame('doctrine_migration_executed_at_column_test', $config->getMigrationsExecutedAtColumnName());
- }
-
- public function testFinderIsIncompatibleWithConfiguration() : void
- {
- $this->expectException(MigrationException::class);
-
- $this->loadConfiguration('organize_by_year', null, new GlobFinder());
- }
-
- public function testSetMigrationFinder() : void
- {
- $migrationFinderProphecy = $this->prophesize(MigrationFinder::class);
- /** @var MigrationFinder $migrationFinder */
- $migrationFinder = $migrationFinderProphecy->reveal();
-
- $config = $this->loadConfiguration();
- $config->setMigrationsFinder($migrationFinder);
-
- $migrationFinderPropertyReflected = new ReflectionProperty(
- Configuration::class,
- 'migrationFinder'
- );
- $migrationFinderPropertyReflected->setAccessible(true);
- self::assertSame($migrationFinder, $migrationFinderPropertyReflected->getValue($config));
- }
-
- public function testThrowExceptionIfAlreadyLoaded() : void
- {
- $config = $this->loadConfiguration();
- $this->expectException(MigrationException::class);
- $config->load($config->getFile());
- }
-
- public function testVersionsOrganizationNoConfig() : void
- {
- $config = $this->loadConfiguration();
- self::assertFalse($config->areMigrationsOrganizedByYear());
- self::assertFalse($config->areMigrationsOrganizedByYearAndMonth());
- }
-
- public function testVersionsOrganizationByYear() : void
- {
- $config = $this->loadConfiguration('organize_by_year');
- self::assertTrue($config->areMigrationsOrganizedByYear());
- self::assertFalse($config->areMigrationsOrganizedByYearAndMonth());
- }
-
- public function testVersionsOrganizationByYearAndMonth() : void
- {
- $config = $this->loadConfiguration('organize_by_year_and_month');
- self::assertTrue($config->areMigrationsOrganizedByYear());
- self::assertTrue($config->areMigrationsOrganizedByYearAndMonth());
- }
-
- public function testVersionsOrganizationInvalid() : void
- {
- $this->expectException(MigrationException::class);
-
- $this->loadConfiguration('organize_invalid');
- }
-
- public function testCustomTemplate() : void
- {
- $config = $this->loadConfiguration('custom_template');
-
- self::assertSame('template.tpl', $config->getCustomTemplate());
- }
-
- public function testVersionsOrganizationIncompatibleFinder() : void
- {
- $this->expectException(MigrationException::class);
-
- $config = $this->loadConfiguration('organize_by_year_and_month');
- $config->setMigrationsFinder(new GlobFinder());
- }
-
- public function testConfigurationWithInvalidOption() : void
- {
- $this->expectException(MigrationException::class);
- $this->expectExceptionCode(10);
-
- $this->loadConfiguration('invalid');
- }
-
- public function testConfigurationFileNotExists() : void
- {
- $this->expectException(InvalidArgumentException::class);
-
- $this->loadConfiguration('file_not_exists');
- }
-
- public function testLoadMigrationsList() : void
- {
- $configuration1 = $this->loadConfiguration('migrations_list');
-
- self::assertContains('migrations_list', $configuration1->getFile());
-
- $configuration2 = $this->loadConfiguration('migrations_list2');
-
- self::assertContains('migrations_list2', $configuration2->getFile());
- }
-
- /**
- * @dataProvider getConfigWithKeysInVariousOrder
- */
- public function testThatTheOrderOfConfigKeysDoesNotMatter(string $file) : void
- {
- $configuration = $this->loadConfiguration($file);
-
- self::assertContains($file, $configuration->getFile());
- }
-
- /** @return string[][] */
- public function getConfigWithKeysInVariousOrder() : array
- {
- return [
- ['order_1'],
- ['order_2'],
- ];
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/AbstractFileConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Configuration/AbstractFileConfigurationTest.php
deleted file mode 100644
index bc6d733cc4..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/AbstractFileConfigurationTest.php
+++ /dev/null
@@ -1,160 +0,0 @@
-fileConfiguration->load($file);
-
- self::assertSame(__DIR__ . '/' . $file, $this->fileConfiguration->getFile());
-
- chdir($cwd);
- }
-
- public function testSetConfiguration() : void
- {
- $fileConfiguration = $this->createPartialMock(TestAbstractFileConfiguration::class, [
- 'setMigrationsNamespace',
- 'setMigrationsTableName',
- 'setMigrationsColumnName',
- 'setMigrationsColumnLength',
- 'setMigrationsExecutedAtColumnName',
- 'setMigrationsAreOrganizedByYearAndMonth',
- 'setName',
- 'setMigrationsDirectory',
- 'registerMigrationsFromDirectory',
- 'registerMigration',
- 'setCustomTemplate',
- 'setAllOrNothing',
- 'setCheckDatabasePlatform',
- ]);
-
- $fileConfiguration->expects(self::once())
- ->method('setMigrationsNamespace')
- ->with('Doctrine');
-
- $fileConfiguration->expects(self::once())
- ->method('setMigrationsTableName')
- ->with('migration_version');
-
- $fileConfiguration->expects(self::once())
- ->method('setMigrationsColumnName')
- ->with('version_number');
-
- $fileConfiguration->expects(self::once())
- ->method('setMigrationsColumnLength')
- ->with(200);
-
- $fileConfiguration->expects(self::once())
- ->method('setMigrationsExecutedAtColumnName')
- ->with('executed_at');
-
- $fileConfiguration->expects(self::once())
- ->method('setMigrationsAreOrganizedByYearAndMonth');
-
- $fileConfiguration->expects(self::once())
- ->method('setName')
- ->with('Migrations Test');
-
- $fileConfiguration->expects(self::once())
- ->method('setMigrationsDirectory')
- ->with('migrations_directory');
-
- $fileConfiguration->expects(self::once())
- ->method('registerMigrationsFromDirectory')
- ->with('migrations_directory');
-
- $fileConfiguration->expects(self::once())
- ->method('registerMigration')
- ->with('001', 'Test');
-
- $fileConfiguration->expects(self::once())
- ->method('setCustomTemplate')
- ->with('custom_template');
-
- $fileConfiguration->expects(self::once())
- ->method('setAllOrNothing')
- ->with(true);
-
- $fileConfiguration->expects(self::once())
- ->method('setCheckDatabasePlatform')
- ->with(false);
-
- $fileConfiguration->setTestConfiguration([
- 'migrations_namespace' => 'Doctrine',
- 'table_name' => 'migration_version',
- 'column_name' => 'version_number',
- 'column_length' => 200,
- 'executed_at_column_name' => 'executed_at',
- 'organize_migrations' => 'year_and_month',
- 'name' => 'Migrations Test',
- 'migrations_directory' => 'migrations_directory',
- 'migrations' => [
- [
- 'version' => '001',
- 'class' => 'Test',
- ],
- ],
- 'custom_template' => 'custom_template',
- 'all_or_nothing' => true,
- 'check_database_platform' => false,
- ]);
- }
-
- public function testSetConfigurationThrowsInvalidConfigurationKey() : void
- {
- $this->expectException(InvalidConfigurationKey::class);
- $this->expectExceptionMessage('Migrations configuration key "unknown" does not exist.');
-
- $this->fileConfiguration->setTestConfiguration(['unknown' => 'value']);
- }
-
- protected function setUp() : void
- {
- $this->connection = $this->createMock(Connection::class);
-
- $this->fileConfiguration = new TestAbstractFileConfiguration($this->connection);
- }
-}
-
-class TestAbstractFileConfiguration extends AbstractFileConfiguration
-{
- /**
- * @param mixed[] $config
- */
- public function setTestConfiguration(array $config) : void
- {
- $this->setConfiguration($config);
- }
-
- protected function doLoad(string $file) : void
- {
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/ArrayConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Configuration/ArrayConfigurationTest.php
deleted file mode 100644
index 8924682614..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/ArrayConfigurationTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-getSqliteConnection(), $outputWriter, $migrationFinder);
- $config->load(__DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $configFile);
-
- return $config;
- }
-
- /**
- * Test that config file not exists exception
- */
- public function testThrowExceptionIfFileNotExist() : void
- {
- $this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage('Given config file does not exist');
-
- $config = new ArrayConfiguration($this->getSqliteConnection());
- $config->load(__DIR__ . '/_files/none.php');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationLoaderTest.php
new file mode 100644
index 0000000000..05b21af59a
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationLoaderTest.php
@@ -0,0 +1,57 @@
+loader = new ConfigurationLoader();
+ }
+
+ public function testAdd() : void
+ {
+ $loader = $this->createMock(Loader::class);
+ $this->loader->addLoader('foo', $loader);
+
+ self::assertSame($loader, $this->loader->getLoader('foo'));
+ }
+
+ public function testUnknownLoader() : void
+ {
+ $this->expectException(UnknownLoader::class);
+ $this->expectExceptionMessage('Unknown configuration loader "foo".');
+ $this->loader->getLoader('foo');
+ }
+
+ public function testDefaults() : void
+ {
+ $defaults = [
+ 'array' => ArrayLoader::class,
+ 'xml' => XmlFileLoader::class,
+ 'yaml' => YamlFileLoader::class,
+ 'yml' => YamlFileLoader::class,
+ 'php' => PhpFileLoader::class,
+ 'json' => JsonFileLoader::class,
+ ];
+
+ foreach ($defaults as $name => $class) {
+ self::assertInstanceOf($class, $this->loader->getLoader($name));
+ }
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationTest.php
index 9bdd32d817..ce94dbed78 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationTest.php
+++ b/tests/Doctrine/Migrations/Tests/Configuration/ConfigurationTest.php
@@ -4,370 +4,80 @@
namespace Doctrine\Migrations\Tests\Configuration;
-use DateTime;
-use DateTimeZone;
-use Doctrine\DBAL\Connection;
-use Doctrine\DBAL\Connections\MasterSlaveConnection;
-use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
-use Doctrine\DBAL\Platforms\AbstractPlatform;
-use Doctrine\DBAL\Platforms\Keywords\KeywordList;
-use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\DependencyFactory;
-use Doctrine\Migrations\MigrationRepository;
-use Doctrine\Migrations\Migrator;
-use Doctrine\Migrations\OutputWriter;
-use Doctrine\Migrations\QueryWriter;
-use Doctrine\Migrations\Stopwatch;
-use Doctrine\Migrations\Tests\MigrationTestCase;
-use Doctrine\Migrations\Tests\Stub\Configuration\AutoloadVersions\Version1Test;
-use Doctrine\Migrations\Version\Version;
-use PHPUnit_Framework_MockObject_MockObject;
-use Symfony\Component\Stopwatch\Stopwatch as SymfonyStopwatch;
-use function array_keys;
-use function call_user_func_array;
-use function sprintf;
-use function str_replace;
+use Doctrine\Migrations\Configuration\Exception\MissingNamespaceConfiguration;
+use Doctrine\Migrations\Configuration\Exception\UnknownConfigurationValue;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorageConfigration;
+use PHPUnit\Framework\TestCase;
-class ConfigurationTest extends MigrationTestCase
+class ConfigurationTest extends TestCase
{
- public function testConstructorSetsOutputWriter() : void
+ public function testBase() : void
{
- $outputWriter = $this->getOutputWriterMock();
+ $storage = $this->createMock(MetadataStorageConfigration::class);
- $configuration = new Configuration(
- $this->getConnectionMock(),
- $outputWriter
- );
+ $config = new Configuration();
+ $config->addMigrationsDirectory('foo', 'bar');
+ $config->addMigrationsDirectory('a', 'b');
- self::assertSame($outputWriter, $configuration->getOutputWriter());
- }
-
- public function testOutputWriterIsCreatedIfNotInjected() : void
- {
- $dependencyFactory = $this->createMock(DependencyFactory::class);
+ $config->addMigrationClass('Foo');
+ $config->addMigrationClass('Bar');
- $outputWriter = $this->getOutputWriterMock();
+ $config->setName('test migration');
+ $config->setAllOrNothing(false);
+ $config->setCheckDatabasePlatform(false);
+ $config->setMetadataStorageConfiguration($storage);
+ $config->setIsDryRun(true);
+ $config->setCustomTemplate('aaa.php');
- $dependencyFactory->expects(self::once())
- ->method('getOutputWriter')
- ->willReturn($outputWriter);
+ self::assertSame([
+ 'foo' => 'bar',
+ 'a' => 'b',
+ ], $config->getMigrationDirectories());
- $configuration = new Configuration($this->getConnectionMock(), null, null, null, $dependencyFactory);
+ self::assertSame(['Foo', 'Bar'], $config->getMigrationClasses());
+ self::assertSame('test migration', $config->getName());
+ self::assertSame($storage, $config->getMetadataStorageConfiguration());
+ self::assertFalse($config->isAllOrNothing());
+ self::assertFalse($config->isDatabasePlatformChecked());
+ self::assertTrue($config->isDryRun());
+ self::assertSame('aaa.php', $config->getCustomTemplate());
- self::assertSame($outputWriter, $configuration->getOutputWriter());
+ self::assertFalse($config->areMigrationsOrganizedByYearAndMonth());
+ self::assertFalse($config->areMigrationsOrganizedByYear());
}
- public function testOutputWriterCanBeSet() : void
+ public function testNoNamespaceConfigured() : void
{
- $outputWriter = $this->getOutputWriterMock();
+ $this->expectException(MissingNamespaceConfiguration::class);
+ $this->expectExceptionMessage('There are no namespaces configured.');
- $configuration = new Configuration($this->getConnectionMock());
- $configuration->setOutputWriter($outputWriter);
-
- self::assertSame($outputWriter, $configuration->getOutputWriter());
+ $config = new Configuration();
+ $config->validate();
}
- public function testGetSetMigrationsColumnName() : void
+ public function testMigrationOrganizationByYear() : void
{
- $configuration = new Configuration($this->getConnectionMock());
-
- self::assertSame('version', $configuration->getMigrationsColumnName());
-
- $configuration->setMigrationsColumnName('foobar');
- self::assertSame('foobar', $configuration->getMigrationsColumnName());
- }
-
- /**
- * @param mixed[] $args
- * @param mixed $expectedResult
- *
- * @dataProvider methodsThatNeedsVersionsLoaded
- */
- public function testVersionsTryToGetLoadedIfNotAlreadyLoadedWhenAccessingMethodThatNeedThem(
- string $method,
- array $args,
- $expectedResult
- ) : void {
- $configuration = new Configuration($this->getSqliteConnection());
- $configuration->setMigrationsNamespace(str_replace('\Version1Test', '', Version1Test::class));
- $configuration->setMigrationsDirectory(__DIR__ . '/../Stub/Configuration/AutoloadVersions');
-
- $result = $configuration->$method(...$args);
-
- if ($method === 'getMigrationsToExecute') {
- $result = array_keys($result);
- }
-
- self::assertSame($expectedResult, $result);
- }
-
- /**
- * @param mixed[] $args
- * @param mixed $expectedResult
- *
- * @dataProvider methodsThatNeedsVersionsLoadedWithAlreadyMigratedMigrations
- */
- public function testVersionsTryToGetLoadedIfNotAlreadyLoadedWhenAccessingMethodThatNeedThemEvenIfSomeMigrationsAreAlreadyMigrated(
- string $method,
- array $args,
- $expectedResult
- ) : void {
- $configuration = new Configuration($this->getSqliteConnection());
- $configuration->setMigrationsNamespace(str_replace('\Version1Test', '', Version1Test::class));
- $configuration->setMigrationsDirectory(__DIR__ . '/../Stub/Configuration/AutoloadVersions');
-
- $dependencyFactory = $configuration->getDependencyFactory();
-
- $symfonyStopwatch = new SymfonyStopwatch(true);
- $stopwatch = new Stopwatch($symfonyStopwatch);
-
- $migrator = new Migrator(
- $configuration,
- $dependencyFactory->getMigrationRepository(),
- $dependencyFactory->getOutputWriter(),
- $stopwatch
- );
- $migrator->migrate('3Test');
-
- /** @var callable $callable */
- $callable = [$configuration, $method];
+ $config = new Configuration();
+ $config->setMigrationOrganization(Configuration::VERSIONS_ORGANIZATION_BY_YEAR);
- $result = call_user_func_array($callable, $args);
-
- if ($method === 'getMigrationsToExecute') {
- $result = array_keys($result);
- }
-
- self::assertSame($expectedResult, $result);
+ self::assertFalse($config->areMigrationsOrganizedByYearAndMonth());
+ self::assertTrue($config->areMigrationsOrganizedByYear());
}
- public function testGenerateVersionNumberFormatsTheDatePassedIn() : void
+ public function testMigrationOrganizationByYearAndMonth() : void
{
- $configuration = new Configuration($this->getSqliteConnection());
- $now = new DateTime('2016-07-05 01:00:00');
-
- $version = $configuration->generateVersionNumber($now);
-
- self::assertSame('20160705010000', $version);
- }
-
- /**
- * We don't actually test the full "time" part of this, since that would fail
- * intermittently. Instead we just verify that we get a version number back
- * that has the current date, hour, and minute. We're really just testing
- * the `?: new DateTime(...)` bit of generateVersionNumber
- */
- public function testGenerateVersionNumberWithoutNowUsesTheCurrentTime() : void
- {
- $configuration = new Configuration($this->getSqliteConnection());
-
- $now = new DateTime('now', new DateTimeZone('UTC'));
- $version = $configuration->generateVersionNumber();
-
- self::assertRegExp(sprintf('/^%s\d{2}$/', $now->format('YmdHi')), $version);
- }
-
- /**
- * Connection is tested via the `getMigratedVersions` method which is the
- * simplest to set up for.
- *
- * @see https://github.com/doctrine/migrations/issues/336
- */
- public function testMasterSlaveConnectionAlwaysConnectsToMaster() : void
- {
- $connection = $this->createMock(MasterSlaveConnection::class);
-
- $connection->expects(self::once())
- ->method('connect')
- ->with('master')
- ->willReturn(true);
-
- $configuration = new Configuration($connection);
- $configuration->setMigrationsNamespace(str_replace('\Version1Test', '', Version1Test::class));
- $configuration->setMigrationsDirectory(__DIR__ . '/../Stub/Configuration/AutoloadVersions');
-
- self::assertTrue($configuration->connect());
- }
-
- /** @return mixed[] */
- public function methodsThatNeedsVersionsLoadedWithAlreadyMigratedMigrations() : array
- {
- return [
- ['hasVersion', ['4Test'], true],
- ['getAvailableVersions', [], ['1Test', '2Test', '3Test', '4Test', '5Test']],
- ['getCurrentVersion', [], '3Test'],
- ['getRelativeVersion', ['3Test', -1], '2Test'],
- ['getNumberOfAvailableMigrations', [], 5],
- ['getLatestVersion', [], '5Test'],
- [
- 'getMigrationsToExecute',
- ['up', '5'],
- [
- '4Test',
- '5Test',
- ],
- ],
- [
- 'getMigrationsToExecute',
- ['up', '4'],
- ['4Test'],
- ],
- [
- 'getMigrationsToExecute',
- ['down', '0'],
- [
- '3Test',
- '2Test',
- '1Test',
- ],
- ],
- [
- 'getMigrationsToExecute',
- ['down', '2'],
- ['3Test'],
- ],
- ];
- }
-
- /** @return mixed[] */
- public function methodsThatNeedsVersionsLoaded() : array
- {
- return [
- ['hasVersion', ['3Test'], true],
- ['getAvailableVersions', [], ['1Test', '2Test', '3Test', '4Test', '5Test']],
- ['getCurrentVersion', [], '0'],
- ['getRelativeVersion', ['3Test', -1], '2Test'],
- ['getNumberOfAvailableMigrations', [], 5],
- ['getLatestVersion', [], '5Test'],
- [
- 'getMigrationsToExecute',
- ['up', '5'],
- [
- '1Test',
- '2Test',
- '3Test',
- '4Test',
- '5Test',
- ],
- ],
- ['getMigrationsToExecute', ['down', '0'], []],
- ['getMigrationsToExecute', ['down', '2'], []],
- ];
- }
-
- public function testGetQueryWriterCreatesAnInstanceIfItWasNotConfigured() : void
- {
- $dp = $this->getMockForAbstractClass(AbstractPlatform::class, [], '', false, true, true, ['getReservedKeywordsClass']);
-
- $dp->method('getReservedKeywordsClass')
- ->willReturn(EmptyKeywordList::class);
-
- $conn = $this->getConnectionMock();
- $conn->method('getDatabasePlatform')
- ->willReturn($dp);
+ $config = new Configuration();
+ $config->setMigrationOrganization(Configuration::VERSIONS_ORGANIZATION_BY_YEAR_AND_MONTH);
- $schemaManager = $this->createMock(AbstractSchemaManager::class);
-
- $conn->expects(self::any())
- ->method('getSchemaManager')
- ->willReturn($schemaManager);
-
- $configuration = new Configuration($conn);
- $queryWriter = $configuration->getQueryWriter();
-
- self::assertAttributeSame($configuration->getOutputWriter(), 'outputWriter', $queryWriter);
- }
-
- public function testGetQueryWriterShouldReturnTheObjectGivenOnTheConstructor() : void
- {
- $queryWriter = $this->createMock(QueryWriter::class);
- $configuration = new Configuration($this->getConnectionMock(), null, null, $queryWriter);
-
- self::assertSame($queryWriter, $configuration->getQueryWriter());
- }
-
- public function testDBWhereVersionIsKeywordReturnsColumnNameWithQuotes() : void
- {
- $config = new Configuration(new Connection([], new DB2Driver()));
-
- self::assertSame('"version"', $config->getQuotedMigrationsColumnName());
- }
-
- public function testGetVersionData() : void
- {
- $dependencyFactory = $this->createMock(DependencyFactory::class);
- $migrationRepository = $this->createMock(MigrationRepository::class);
- $version = $this->createMock(Version::class);
-
- $versionData = [
- 'version' => '1234',
- 'executed_at' => '2018-05-16 11:14:40',
- ];
-
- $dependencyFactory->expects(self::once())
- ->method('getMigrationRepository')
- ->willReturn($migrationRepository);
-
- $migrationRepository->expects(self::once())
- ->method('getVersionData')
- ->with($version)
- ->willReturn($versionData);
-
- $configuration = new Configuration($this->getConnectionMock(), null, null, null, $dependencyFactory);
-
- self::assertSame($versionData, $configuration->getVersionData($version));
- }
-
- public function testGetSetAllOrNothing() : void
- {
- $configuration = $this->createPartialMock(Configuration::class, []);
-
- self::assertFalse($configuration->isAllOrNothing());
-
- $configuration->setAllOrNothing(true);
-
- self::assertTrue($configuration->isAllOrNothing());
- }
-
- public function testGetSetCheckDatabasePlatform() : void
- {
- $configuration = $this->createPartialMock(Configuration::class, []);
-
- self::assertTrue($configuration->isDatabasePlatformChecked());
-
- $configuration->setCheckDatabasePlatform(false);
-
- self::assertFalse($configuration->isDatabasePlatformChecked());
- }
-
- /**
- * @return PHPUnit_Framework_MockObject_MockObject|Connection
- */
- private function getConnectionMock()
- {
- return $this->createMock(Connection::class);
- }
-
- /**
- * @return PHPUnit_Framework_MockObject_MockObject|OutputWriter
- */
- private function getOutputWriterMock()
- {
- return $this->createMock(OutputWriter::class);
- }
-}
-
-final class EmptyKeywordList extends KeywordList
-{
- /** @return string[] */
- protected function getKeywords() : array
- {
- return [];
+ self::assertTrue($config->areMigrationsOrganizedByYearAndMonth());
+ self::assertTrue($config->areMigrationsOrganizedByYear());
}
- public function getName() : string
+ public function testMigrationOrganizationWithWrongValue() : void
{
- return 'EMPTY';
+ $this->expectException(UnknownConfigurationValue::class);
+ $config = new Configuration();
+ $config->setMigrationOrganization('foo');
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/ConnectionConfigurationLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/ConnectionConfigurationLoaderTest.php
deleted file mode 100644
index ea0cea4677..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/ConnectionConfigurationLoaderTest.php
+++ /dev/null
@@ -1,45 +0,0 @@
-chosen());
- }
-
- public function testChosenReturnsConfigurationConnection() : void
- {
- $connection = $this->createMock(Connection::class);
-
- $this->configuration->expects(self::once())
- ->method('getConnection')
- ->willReturn($connection);
-
- self::assertSame($connection, $this->connectionConfigurationLoader->chosen());
- }
-
- protected function setUp() : void
- {
- $this->configuration = $this->createMock(Configuration::class);
-
- $this->connectionConfigurationLoader = new ConnectionConfigurationLoader($this->configuration);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/ConnectionLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/ConnectionLoaderTest.php
new file mode 100644
index 0000000000..18060a60b6
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/ConnectionLoaderTest.php
@@ -0,0 +1,78 @@
+expectException(ConnectionNotSpecified::class);
+ $loader = new NoConnectionLoader();
+ $loader->getConnection();
+ }
+
+ public function testArrayConnectionConfigurationLoader() : void
+ {
+ $loader = new ArrayConnectionConfigurationLoader(__DIR__ . '/sqlite-connection.php', new NoConnectionLoader());
+ $conn = $loader->getConnection();
+
+ self::assertInstanceOf(SqlitePlatform::class, $conn->getDatabasePlatform());
+ }
+
+ public function testArrayConnectionConfigurationLoaderInvalid() : void
+ {
+ $this->expectException(InvalidConfiguration::class);
+ $loader = new ArrayConnectionConfigurationLoader(__DIR__ . '/sqlite-connection-invalid.php', new NoConnectionLoader());
+ $loader->getConnection();
+ }
+
+ public function testArrayConnectionConfigurationLoaderNotFound() : void
+ {
+ $this->expectException(ConnectionNotSpecified::class);
+ $loader = new ArrayConnectionConfigurationLoader(__DIR__ . '/not-found.php', new NoConnectionLoader());
+ $loader->getConnection();
+ }
+
+ public function testArrayConnectionConfigurationLoaderNoFile() : void
+ {
+ $this->expectException(ConnectionNotSpecified::class);
+ $loader = new ArrayConnectionConfigurationLoader(null, new NoConnectionLoader());
+ $loader->getConnection();
+ }
+
+ public function testConnectionHelperLoader() : void
+ {
+ $connection = $this->createMock(Connection::class);
+
+ $helper = $this->createMock(ConnectionHelper::class);
+ $helper->expects(self::once())->method('getConnection')->willReturn($connection);
+
+ $helperSet = new HelperSet();
+ $helperSet->set($helper, 'connection');
+ $loader = new ConnectionHelperLoader('connection', new NoConnectionLoader(), $helperSet);
+ $conn = $loader->getConnection();
+
+ self::assertSame($connection, $conn);
+ }
+
+ public function testConnectionHelperLoaderNoHelper() : void
+ {
+ $this->expectException(ConnectionNotSpecified::class);
+ $helperSet = new HelperSet();
+ $loader = new ConnectionHelperLoader('connection', new NoConnectionLoader(), $helperSet);
+ $loader->getConnection();
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/sqlite-connection-invalid.php b/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/sqlite-connection-invalid.php
new file mode 100644
index 0000000000..174d7fd709
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Connection/Loader/sqlite-connection-invalid.php
@@ -0,0 +1,3 @@
+ 'pdo_sqlite', 'memory' => true];
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/JsonConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Configuration/JsonConfigurationTest.php
deleted file mode 100644
index 24c482158e..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/JsonConfigurationTest.php
+++ /dev/null
@@ -1,53 +0,0 @@
-getSqliteConnection(), $outputWriter, $migrationFinder);
- $config->load(__DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $configFile);
-
- return $config;
- }
-
- /**
- * Test that config file not exists exception
- */
- public function testThrowExceptionIfFileNotExist() : void
- {
- $config = new JsonConfiguration($this->getSqliteConnection());
-
- $this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage('Given config file does not exist');
-
- $config->load(__DIR__ . '/_files/none.json');
- }
-
- public function testInvalid() : void
- {
- $this->expectException(JsonNotValid::class);
-
- $this->loadConfiguration('malformed');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Loader/AbstractLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Loader/AbstractLoaderTest.php
new file mode 100644
index 0000000000..9a47763df2
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Loader/AbstractLoaderTest.php
@@ -0,0 +1,106 @@
+load('minimal');
+
+ self::assertNull($config->getName());
+ self::assertSame(['DoctrineMigrationsTest' => dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files'], $config->getMigrationDirectories());
+
+ self::assertSame([], $config->getMigrationClasses());
+
+ $storage = $config->getMetadataStorageConfiguration();
+ self::assertInstanceOf(TableMetadataStorageConfiguration::class, $storage);
+
+ self::assertSame('doctrine_migration_versions', $storage->getTableName());
+ self::assertSame('version', $storage->getVersionColumnName());
+ self::assertSame(1024, $storage->getVersionColumnLength());
+ self::assertSame('execution_time', $storage->getExecutionTimeColumnName());
+ self::assertSame('executed_at', $storage->getExecutedAtColumnName());
+ }
+
+ public function testLoad() : void
+ {
+ $config = $this->load();
+
+ self::assertSame('Doctrine Sandbox Migrations', $config->getName());
+ self::assertSame(['DoctrineMigrationsTest' => dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files'], $config->getMigrationDirectories());
+
+ self::assertSame(['Foo', 'Bar'], $config->getMigrationClasses());
+
+ $storage = $config->getMetadataStorageConfiguration();
+ self::assertInstanceOf(TableMetadataStorageConfiguration::class, $storage);
+
+ self::assertSame('doctrine_migration_versions_test', $storage->getTableName());
+ self::assertSame('doctrine_migration_column_test', $storage->getVersionColumnName());
+ self::assertSame(2000, $storage->getVersionColumnLength());
+ self::assertSame('doctrine_migration_execution_time_column_test', $storage->getExecutionTimeColumnName());
+ self::assertSame('doctrine_migration_executed_at_column_test', $storage->getExecutedAtColumnName());
+ }
+
+ public function testConfigurationFileNotExists() : void
+ {
+ $this->expectException(InvalidArgumentException::class);
+
+ $this->load('not_existent');
+ }
+
+ public function testCustomTemplate() : void
+ {
+ $config = $this->load('custom_template');
+
+ self::assertSame('template.tpl', $config->getCustomTemplate());
+ }
+
+ public function testConfigurationWithInvalidOption() : void
+ {
+ $this->expectException(InvalidConfigurationKey::class);
+
+ $this->load('invalid');
+ }
+
+ public function testVersionsOrganizationNoConfig() : void
+ {
+ $config = $this->load();
+ self::assertFalse($config->areMigrationsOrganizedByYear());
+ self::assertFalse($config->areMigrationsOrganizedByYearAndMonth());
+ }
+
+ public function testVersionsOrganizationByYear() : void
+ {
+ $config = $this->load('organize_by_year');
+ self::assertTrue($config->areMigrationsOrganizedByYear());
+ self::assertFalse($config->areMigrationsOrganizedByYearAndMonth());
+ }
+
+ public function testVersionsOrganizationByYearAndMonth() : void
+ {
+ $config = $this->load('organize_by_year_and_month');
+ self::assertTrue($config->areMigrationsOrganizedByYear());
+ self::assertTrue($config->areMigrationsOrganizedByYearAndMonth());
+ }
+
+ public function testVersionsOrganizationInvalid() : void
+ {
+ $this->expectException(MigrationException::class);
+
+ $this->load('organize_invalid');
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Loader/ArrayLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Loader/ArrayLoaderTest.php
new file mode 100644
index 0000000000..047c2fca02
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Loader/ArrayLoaderTest.php
@@ -0,0 +1,37 @@
+expectException(UnableToLoadResource::class);
+ $this->expectExceptionMessage('The provided resource can not be loaded by the loader "Doctrine\Migrations\Configuration\Loader\ArrayLoader".');
+ $loader = new ArrayLoader();
+ $loader->load(null);
+ }
+
+ public function testInvalidKey() : void
+ {
+ $this->expectException(InvalidConfigurationKey::class);
+ $this->expectExceptionMessage('Migrations configuration key "foo" does not exist');
+ $loader = new ArrayLoader();
+ $loader->load(['foo' => 'aaa']);
+ }
+
+ public function testInvalidKeyInteger() : void
+ {
+ $this->expectException(InvalidConfigurationKey::class);
+ $this->expectExceptionMessage('Migrations configuration key "0" does not exist.');
+ $loader = new ArrayLoader();
+ $loader->load(['aaa']);
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Loader/JsonLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Loader/JsonLoaderTest.php
new file mode 100644
index 0000000000..323fe49ef0
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Loader/JsonLoaderTest.php
@@ -0,0 +1,25 @@
+load(__DIR__ . '/../_files/config' . ($prefix!==''? ('_' . $prefix) : '') . '.json');
+ }
+
+ public function testMalformed() : void
+ {
+ $this->expectException(JsonNotValid::class);
+ $this->load('malformed');
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Loader/PhpLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Loader/PhpLoaderTest.php
new file mode 100644
index 0000000000..f76cc622c8
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Loader/PhpLoaderTest.php
@@ -0,0 +1,25 @@
+load(__DIR__ . '/../_files/config' . ($prefix!==''? ('_' . $prefix) : '') . '.php');
+ }
+
+ public function testLoadInline() : void
+ {
+ $config = $this->load('instance');
+
+ self::assertSame('inline', $config->getName());
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Loader/XmlLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Loader/XmlLoaderTest.php
new file mode 100644
index 0000000000..4be6592830
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Loader/XmlLoaderTest.php
@@ -0,0 +1,33 @@
+load(__DIR__ . '/../_files/config' . ($prefix!==''? ('_' . $prefix) : '') . '.xml');
+ }
+
+ public function testConfigurationWithInvalidOption() : void
+ {
+ $this->expectException(XmlNotValid::class);
+
+ $this->load('invalid');
+ }
+
+ public function testMalformed() : void
+ {
+ $this->expectException(XmlNotValid::class);
+
+ $this->load('malformed');
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/Loader/YamlLoaderTest.php b/tests/Doctrine/Migrations/Tests/Configuration/Loader/YamlLoaderTest.php
new file mode 100644
index 0000000000..4c8548a100
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/Loader/YamlLoaderTest.php
@@ -0,0 +1,26 @@
+load(__DIR__ . '/../_files/config' . ($prefix!==''? ('_' . $prefix) : '') . '.yml');
+ }
+
+ public function testMalformed() : void
+ {
+ $this->expectException(YamlNotValid::class);
+
+ $this->load('malformed');
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/XmlConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Configuration/XmlConfigurationTest.php
deleted file mode 100644
index 854c97ab39..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/XmlConfigurationTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-getSqliteConnection(), $outputWriter, $migrationFinder);
- $configFileSuffix->load(__DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $configFile);
-
- return $configFileSuffix;
- }
-
- public function testInvalid() : void
- {
- $this->expectException(XmlNotValid::class);
-
- $this->loadConfiguration('malformed');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/YamlConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Configuration/YamlConfigurationTest.php
deleted file mode 100644
index e2d6a453bb..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/YamlConfigurationTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-getSqliteConnection(), $outputWriter, $migrationFinder);
- $configFileSuffix->load(__DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $configFile);
-
- return $configFileSuffix;
- }
-
- public function testInvalid() : void
- {
- $this->expectException(YamlNotValid::class);
-
- $this->loadConfiguration('malformed');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.json b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.json
index 59ebf9d837..8054c59373 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.json
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.json
@@ -1,11 +1,15 @@
{
"name" : "Doctrine Sandbox Migrations",
- "migrations_namespace" : "DoctrineMigrationsTest",
- "table_name" : "doctrine_migration_versions_test",
- "column_name" : "doctrine_migration_column_test",
- "column_length" : 200,
- "executed_at_column_name" : "doctrine_migration_executed_at_column_test",
- "migrations_directory" : ".",
- "migrations" : [],
+ "migrations_paths" : {
+ "DoctrineMigrationsTest": "."
+ },
+ "migrations" : ["Foo", "Bar"],
+ "table_storage" :{
+ "table_name" : "doctrine_migration_versions_test",
+ "version_column_name" : "doctrine_migration_column_test",
+ "version_column_length" : 2000,
+ "executed_at_column_name" : "doctrine_migration_executed_at_column_test",
+ "execution_time_column_name" : "doctrine_migration_execution_time_column_test"
+ },
"all_or_nothing" : true
}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.php b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.php
index 0b42782fc2..37bb3f4dd9 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.php
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.php
@@ -4,13 +4,18 @@
return [
'name' => 'Doctrine Sandbox Migrations',
- 'migrations_namespace' => 'DoctrineMigrationsTest',
- 'table_name' => 'doctrine_migration_versions_test',
- 'column_name' => 'doctrine_migration_column_test',
- 'column_length' => 200,
- 'executed_at_column_name' => 'doctrine_migration_executed_at_column_test',
- 'migrations_directory' => '.',
- 'migrations' => [],
+
+ 'table_storage' => [
+ 'table_name' => 'doctrine_migration_versions_test',
+ 'version_column_name' => 'doctrine_migration_column_test',
+ 'version_column_length' => 2000,
+ 'executed_at_column_name' => 'doctrine_migration_executed_at_column_test',
+ 'execution_time_column_name' => 'doctrine_migration_execution_time_column_test',
+ ],
+
+ 'migrations_paths' => ['DoctrineMigrationsTest' => '.'],
+ 'migrations' => ['Foo', 'Bar'],
+
'all_or_nothing' => true,
'check_database_platform' => false,
];
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.xml
index 043f16ad37..2c4f37f633 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.xml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.xml
@@ -1,14 +1,31 @@
-
-
- Doctrine Sandbox Migrations
- DoctrineMigrationsTest
-
- .
- true
- true
+
+Doctrine Sandbox Migrations
+
+
+ .
+
+
+
+
+
+
+ Foo
+ Bar
+
+
+true
+true
+
+
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.yml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.yml
index 240d1c6d0f..14b758fc80 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config.yml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config.yml
@@ -1,11 +1,16 @@
---
name: Doctrine Sandbox Migrations
-migrations_namespace: DoctrineMigrationsTest
-table_name: doctrine_migration_versions_test
-column_name: doctrine_migration_column_test
-column_length: 200
-executed_at_column_name: doctrine_migration_executed_at_column_test
-migrations_directory: .
-migrations: []
+
+table_storage:
+ table_name: doctrine_migration_versions_test
+ version_column_name: doctrine_migration_column_test
+ version_column_length: 2000
+ executed_at_column_name: doctrine_migration_executed_at_column_test
+ execution_time_column_name : doctrine_migration_execution_time_column_test
+
+migrations_paths:
+ DoctrineMigrationsTest: .
+migrations : ["Foo", "Bar"]
all_or_nothing: true
check_database_platform: true
+
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_custom_template.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_custom_template.xml
index a81b572dff..19585f33d6 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_custom_template.xml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_custom_template.xml
@@ -1,8 +1,8 @@
-
+ xsi:schemaLocation="http://doctrine-project.org/schemas/migrations/configuration/3.0
+ http://doctrine-project.org/schemas/migrations/configuration/3.0.xsd">
template.tpl
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_instance.php b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_instance.php
new file mode 100644
index 0000000000..1d8cac73cf
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_instance.php
@@ -0,0 +1,10 @@
+setName('inline');
+
+return $c;
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_invalid.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_invalid.xml
index daade9bc44..2115ea76b2 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_invalid.xml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_invalid.xml
@@ -1,8 +1,8 @@
-
+ xsi:schemaLocation="http://doctrine-project.org/schemas/migrations/configuration/3.0
+ http://doctrine-project.org/schemas/migrations/configuration/3.0.xsd">
Doctrine Sandbox Migrations
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.json b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.json
deleted file mode 100644
index d4dfaa4b45..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name" : "Doctrine Sandbox Migrations",
- "table_name" : "doctrine_migration_versions_test",
- "migrations" : [
- {
- "class": "Doctrine\\Migrations\\Tests\\Stub\\Version1Test",
- "version": "Version1Test"
- },
- {
- "class": "Doctrine\\Migrations\\Tests\\Stub\\Version2Test",
- "version": "Version2Test"
- },
- {
- "class": "Doctrine\\Migrations\\Tests\\Stub\\Version3Test",
- "version": "Version3Test"
- }
- ]
-}
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.php b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.php
deleted file mode 100644
index 42d0faf060..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.php
+++ /dev/null
@@ -1,22 +0,0 @@
- 'Doctrine Sandbox Migrations',
- 'table_name' => 'doctrine_migration_versions_test',
- 'migrations' => [
- [
- 'class' => 'Doctrine\\Migrations\\Tests\\Stub\\Version1Test',
- 'version' => 'Version1Test',
- ],
- [
- 'class' => 'Doctrine\\Migrations\\Tests\\Stub\\Version2Test',
- 'version' => 'Version2Test',
- ],
- [
- 'class' => 'Doctrine\\Migrations\\Tests\\Stub\\Version3Test',
- 'version' => 'Version3Test',
- ],
- ],
-];
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.xml
deleted file mode 100644
index 32decd608b..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- Doctrine Sandbox Migrations
-
-
-
-
-
-
-
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.yml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.yml
deleted file mode 100644
index 03916f2cd3..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: Doctrine Sandbox Migrations
-table_name: doctrine_migration_versions_test
-migrations:
- - { 'class': 'Doctrine\Migrations\Tests\Stub\Version1Test', 'version': 'Version1Test' }
- - { 'class': 'Doctrine\Migrations\Tests\Stub\Version2Test', 'version': 'Version2Test' }
- - { 'class': 'Doctrine\Migrations\Tests\Stub\Version3Test', 'version': 'Version3Test' }
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.json b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.json
deleted file mode 100644
index 8efcaae91b..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name" : "Doctrine Sandbox Migrations",
- "table_name" : "doctrine_migration_versions_test",
- "migrations" : {
- "migration1":
- {
- "class": "Doctrine\\Migrations\\Tests\\Stub\\Version1Test",
- "version": "Version1Test"
- },
- "migration2":
- {
- "class": "Doctrine\\Migrations\\Tests\\Stub\\Version2Test",
- "version": "Version2Test"
- },
- "migration3":
- {
- "class": "Doctrine\\Migrations\\Tests\\Stub\\Version3Test",
- "version": "Version3Test"
- }
- }
-}
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.php b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.php
deleted file mode 100644
index 121c7617c6..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.php
+++ /dev/null
@@ -1,25 +0,0 @@
- 'Doctrine Sandbox Migrations',
- 'table_name' => 'doctrine_migration_versions_test',
- 'migrations' => [
- 'migration1' =>
- [
- 'class' => 'Doctrine\\Migrations\\Tests\\Stub\\Version1Test',
- 'version' => 'Version1Test',
- ],
- 'migration2' =>
- [
- 'class' => 'Doctrine\\Migrations\\Tests\\Stub\\Version2Test',
- 'version' => 'Version2Test',
- ],
- 'migration3' =>
- [
- 'class' => 'Doctrine\\Migrations\\Tests\\Stub\\Version3Test',
- 'version' => 'Version3Test',
- ],
- ],
-];
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.xml
deleted file mode 100644
index 32decd608b..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- Doctrine Sandbox Migrations
-
-
-
-
-
-
-
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.yml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.yml
deleted file mode 100644
index 7889f2fc89..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_migrations_list2.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-name: Doctrine Sandbox Migrations
-table_name: doctrine_migration_versions_test
-migrations:
- migration1:
- version: Version1Test
- class: Doctrine\Migrations\Tests\Stub\Version1Test
- migration2:
- version: Version2Test
- class: Doctrine\Migrations\Tests\Stub\Version2Test
- migration3:
- version: Version3Test
- class: Doctrine\Migrations\Tests\Stub\Version3Test
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.json b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.json
new file mode 100644
index 0000000000..d5861dd17e
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.json
@@ -0,0 +1,5 @@
+{
+ "migrations_paths" : {
+ "DoctrineMigrationsTest": "."
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.php b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.php
new file mode 100644
index 0000000000..ca06bba022
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.php
@@ -0,0 +1,7 @@
+ ['DoctrineMigrationsTest' => '.'],
+];
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.xml
new file mode 100644
index 0000000000..32ab1b831f
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ .
+
+
+
+
+
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.yml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.yml
new file mode 100644
index 0000000000..f2479c9caa
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_minimal.yml
@@ -0,0 +1,3 @@
+---
+migrations_paths:
+ DoctrineMigrationsTest: .
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.json b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.json
deleted file mode 100644
index 26468b108a..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name" : "Doctrine Sandbox Migrations",
- "migrations_namespace": "DoctrineMigrationsTest",
- "table_name" : "doctrine_migration_versions_test",
- "migrations_directory": ".",
- "migrations" : []
-}
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.php b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.php
deleted file mode 100644
index 0a74e5e2f0..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.php
+++ /dev/null
@@ -1,11 +0,0 @@
- 'Doctrine Sandbox Migrations',
- 'migrations_namespace' => 'DoctrineMigrationsTest',
- 'table_name' => 'doctrine_migration_versions_test',
- 'migrations_directory' => '.',
- 'migrations' => [],
-];
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.xml
deleted file mode 100644
index 900b17711c..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
- Doctrine Sandbox Migrations
- DoctrineMigrationsTest
-
- .
-
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.yml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.yml
deleted file mode 100644
index 1abfa2ee11..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_1.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-name: Doctrine Sandbox Migrations
-migrations_namespace: DoctrineMigrationsTest
-table_name: doctrine_migration_versions_test
-migrations_directory: .
-migrations:
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.json b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.json
deleted file mode 100644
index 2eb066e38d..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name" : "Doctrine Sandbox Migrations",
- "migrations_directory": ".",
- "migrations_namespace": "DoctrineMigrationsTest",
- "table_name" : "doctrine_migration_versions_test",
- "migrations" : []
-}
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.xml
deleted file mode 100644
index 38759c0bb7..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
- Doctrine Sandbox Migrations
- .
- DoctrineMigrationsTest
-
-
-
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.yml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.yml
deleted file mode 100644
index f6e0f685e1..0000000000
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-name: Doctrine Sandbox Migrations
-migrations_directory: .
-migrations_namespace: DoctrineMigrationsTest
-table_name: doctrine_migration_versions_test
-migrations:
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year.xml
index f04df6675c..b0a4783408 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year.xml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year.xml
@@ -1,9 +1,9 @@
-
+ xsi:schemaLocation="http://doctrine-project.org/schemas/migrations/configuration/3.0
+ http://doctrine-project.org/schemas/migrations/configuration/3.0.xsd">
- YEaR
+ year
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.json b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.json
index 7dd69999a5..bd6f659d20 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.json
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.json
@@ -1,3 +1,3 @@
{
- "organize_migrations" : "year_AND_MOnth"
+ "organize_migrations" : "year_and_month"
}
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.php b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.php
index 407fb83b87..d93a021e11 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.php
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.php
@@ -2,4 +2,4 @@
declare(strict_types=1);
-return ['organize_migrations' => 'year_AND_MOnth'];
+return ['organize_migrations' => 'year_and_month'];
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.xml
index d1feb437a3..1b5cd3e8e8 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.xml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.xml
@@ -1,9 +1,9 @@
-
+ xsi:schemaLocation="http://doctrine-project.org/schemas/migrations/configuration/3.0
+ http://doctrine-project.org/schemas/migrations/configuration/3.0.xsd">
- YEAR_and_mONth
+ year_and_month
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.yml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.yml
index caa431297e..bf43210d6c 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.yml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_by_year_and_month.yml
@@ -1,2 +1,2 @@
---
-organize_migrations: "year_AND_MOnth"
+organize_migrations: "year_and_month"
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_invalid.xml b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_invalid.xml
index df666a786c..52b1e3294b 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_invalid.xml
+++ b/tests/Doctrine/Migrations/Tests/Configuration/_files/config_organize_invalid.xml
@@ -1,8 +1,8 @@
-
+ xsi:schemaLocation="http://doctrine-project.org/schemas/migrations/configuration/3.0
+ http://doctrine-project.org/schemas/migrations/configuration/3.0.xsd">
bar-foo
diff --git a/tests/Doctrine/Migrations/Tests/ConfigurationTest.php b/tests/Doctrine/Migrations/Tests/ConfigurationTest.php
deleted file mode 100644
index db1b39c029..0000000000
--- a/tests/Doctrine/Migrations/Tests/ConfigurationTest.php
+++ /dev/null
@@ -1,465 +0,0 @@
-getSqliteConnection();
- $config = new Configuration($conn);
-
- self::assertSame($conn, $config->getConnection());
- }
-
- public function testValidateMigrationsNamespaceRequired() : void
- {
- $config = new Configuration($this->getSqliteConnection());
-
- $this->expectException(MigrationException::class);
- $this->expectExceptionMessage('Migrations namespace must be configured in order to use Doctrine migrations.');
- $config->validate();
- }
-
- public function testValidateMigrationsDirectoryRequired() : void
- {
- $config = new Configuration($this->getSqliteConnection());
- $config->setMigrationsNamespace('DoctrineMigrations\\');
-
- $this->expectException(MigrationException::class);
- $this->expectExceptionMessage('Migrations directory must be configured in order to use Doctrine migrations.');
-
- $config->validate();
- }
-
- public function testValidateMigrations() : void
- {
- $config = new Configuration($this->getSqliteConnection());
- $config->setMigrationsNamespace('DoctrineMigrations\\');
- $config->setMigrationsDirectory(sys_get_temp_dir());
-
- $config->validate();
-
- $this->addToAssertionCount(1);
- }
-
- public function testSetGetName() : void
- {
- $config = new Configuration($this->getSqliteConnection());
- $config->setName('Test');
-
- self::assertSame('Test', $config->getName());
- }
-
- public function testMigrationsTable() : void
- {
- $config = new Configuration($this->getSqliteConnection());
-
- self::assertSame('doctrine_migration_versions', $config->getMigrationsTableName());
- }
-
- public function testSetGetMigrationsColumnLength() : void
- {
- $config = new Configuration($this->getSqliteConnection());
-
- self::assertSame(14, $config->getMigrationsColumnLength());
-
- $config->setMigrationsColumnLength(200);
-
- self::assertSame(200, $config->getMigrationsColumnLength());
- }
-
- public function testSetGetSetMigrationsExecutedAtColumnName() : void
- {
- $config = new Configuration($this->getSqliteConnection());
-
- self::assertSame('executed_at', $config->getMigrationsExecutedAtColumnName());
-
- $config->setMigrationsExecutedAtColumnName('executedAt');
-
- self::assertSame('executedAt', $config->getMigrationsExecutedAtColumnName());
- }
-
- public function testGetQuotedMigrationsExecutedAtColumnName() : void
- {
- $config = new Configuration($this->getSqliteConnection());
-
- self::assertSame('executed_at', $config->getQuotedMigrationsExecutedAtColumnName());
- }
-
- public function testEmptyProjectDefaults() : void
- {
- $config = $this->getSqliteConfiguration();
- self::assertNull($config->getPrevVersion(), 'no prev version');
- self::assertNull($config->getNextVersion(), 'no next version');
- self::assertSame('0', $config->getCurrentVersion(), 'current version 0');
- self::assertSame('0', $config->getLatestVersion(), 'latest version 0');
- self::assertSame(0, $config->getNumberOfAvailableMigrations(), 'number of available migrations 0');
- self::assertSame(0, $config->getNumberOfExecutedMigrations(), 'number of executed migrations 0');
- self::assertSame([], $config->getMigrations());
- }
-
- public function testGetUnknownVersion() : void
- {
- $config = $this->getSqliteConfiguration();
-
- $this->expectException(MigrationException::class);
- $this->expectExceptionMessage('Could not find migration version 1234');
-
- $config->getVersion('1234');
- }
-
- public function testRegisterMigration() : void
- {
- $config = $this->getSqliteConfiguration();
- $config->registerMigration('1234', Version1Test::class);
-
- self::assertCount(1, $config->getMigrations(), 'One Migration registered.');
- self::assertTrue($config->hasVersion('1234'));
-
- $version = $config->getVersion('1234');
- self::assertSame('1234', $version->getVersion());
- self::assertFalse($version->isMigrated());
- }
-
- public function testRegisterMigrations() : void
- {
- $config = $this->getSqliteConfiguration();
- $config->registerMigrations([
- '1234' => Version1Test::class,
- '1235' => Version2Test::class,
- ]);
-
- self::assertCount(2, $config->getMigrations(), 'Two Migration registered.');
-
- $version = $config->getVersion('1234');
- self::assertSame('1234', $version->getVersion());
-
- $version = $config->getVersion('1235');
- self::assertSame('1235', $version->getVersion());
- }
-
- public function testRegisterDuplicateVersion() : void
- {
- $config = $this->getSqliteConfiguration();
-
- $config->registerMigration('1234', Version1Test::class);
-
- $this->expectException(MigrationException::class);
- $this->expectExceptionMessage(
- 'Migration version 1234 already registered with class Doctrine\Migrations\Version'
- );
- $config->registerMigration('1234', Version1Test::class);
- }
-
- public function testRelativeVersion() : void
- {
- $config = $this->getSqliteConfiguration();
- $config->registerMigrations([
- '0initial' => Version1Test::class,
- '1' => Version2Test::class,
- 'final' => Version3Test::class,
- ]);
-
- // Relative to nonexistent version
- self::assertNull($config->getRelativeVersion('nonexistent', -1));
- self::assertNull($config->getRelativeVersion('nonexistent', 0));
- self::assertNull($config->getRelativeVersion('nonexistent', 1));
-
- // Relative to version '0' as int
- self::assertNull($config->getRelativeVersion('0', -1));
- self::assertSame('0', $config->getRelativeVersion('0', 0));
- self::assertSame('0initial', $config->getRelativeVersion('0', 1));
- self::assertSame('1', $config->getRelativeVersion('0', 2));
- self::assertSame('final', $config->getRelativeVersion('0', 3));
- self::assertNull($config->getRelativeVersion('0', 4));
-
- // Relative to version '0' as string
- self::assertNull($config->getRelativeVersion('0', -1));
- self::assertSame('0', $config->getRelativeVersion('0', 0));
- self::assertSame('0initial', $config->getRelativeVersion('0', 1));
- self::assertSame('1', $config->getRelativeVersion('0', 2));
- self::assertSame('final', $config->getRelativeVersion('0', 3));
- self::assertNull($config->getRelativeVersion('0', 4));
-
- // Relative to version '0initial'
- self::assertNull($config->getRelativeVersion('0initial', -2));
- self::assertSame('0', $config->getRelativeVersion('0initial', -1));
- self::assertSame('0initial', $config->getRelativeVersion('0initial', 0));
- self::assertSame('1', $config->getRelativeVersion('0initial', 1));
- self::assertSame('final', $config->getRelativeVersion('0initial', 2));
- self::assertNull($config->getRelativeVersion('0initial', 3));
-
- // Relative to version '1' as int
- self::assertNull($config->getRelativeVersion('1', -3));
- self::assertSame('0', $config->getRelativeVersion('1', -2));
- self::assertSame('0initial', $config->getRelativeVersion('1', -1));
- self::assertSame('1', $config->getRelativeVersion('1', 0));
- self::assertSame('final', $config->getRelativeVersion('1', 1));
- self::assertNull($config->getRelativeVersion('1', 2));
-
- // Relative to version '1' as string
- self::assertNull($config->getRelativeVersion('1', -3));
- self::assertSame('0', $config->getRelativeVersion('1', -2));
- self::assertSame('0initial', $config->getRelativeVersion('1', -1));
- self::assertSame('1', $config->getRelativeVersion('1', 0));
- self::assertSame('final', $config->getRelativeVersion('1', 1));
- self::assertNull($config->getRelativeVersion('1', 2));
-
- // Relative to version 'final'
- self::assertNull($config->getRelativeVersion('final', -4));
- self::assertSame('0', $config->getRelativeVersion('final', -3));
- self::assertSame('0initial', $config->getRelativeVersion('final', -2));
- self::assertSame('1', $config->getRelativeVersion('final', -1));
- self::assertSame('final', $config->getRelativeVersion('final', 0));
- self::assertNull($config->getRelativeVersion('final', 1));
- }
-
- public function testPreviousCurrentNextLatestVersion() : void
- {
- $config = $this->getSqliteConfiguration();
- $config->registerMigrations([
- '1234' => Version1Test::class,
- '1235' => Version2Test::class,
- '1236' => Version3Test::class,
- ]);
-
- self::assertNull($config->getPrevVersion(), 'no prev version');
- self::assertSame('0', $config->getCurrentVersion(), 'current version 0');
- self::assertSame('1234', $config->getNextVersion(), 'next version 1234');
- self::assertSame('1236', $config->getLatestVersion(), 'latest version 1236');
-
- $config->getVersion('1234')->markMigrated();
-
- self::assertSame('0', $config->getPrevVersion(), 'prev version 0');
- self::assertSame('1234', $config->getCurrentVersion(), 'current version 1234');
- self::assertSame('1235', $config->getNextVersion(), 'next version 1235');
- self::assertSame('1236', $config->getLatestVersion(), 'latest version 1236');
-
- $config->getVersion('1235')->markMigrated();
-
- self::assertSame('1234', $config->getPrevVersion(), 'prev version 1234');
- self::assertSame('1235', $config->getCurrentVersion(), 'current version 1235');
- self::assertSame('1236', $config->getNextVersion(), 'next version is 1236');
- self::assertSame('1236', $config->getLatestVersion(), 'latest version 1236');
-
- self::assertSame('0', $config->resolveVersionAlias('first'), 'first version 0');
- self::assertSame('1234', $config->resolveVersionAlias('prev'), 'prev version 1234');
- self::assertSame('1235', $config->resolveVersionAlias('current'), 'current version 1235');
- self::assertSame('1236', $config->resolveVersionAlias('next'), 'next version is 1236');
- self::assertSame('1236', $config->resolveVersionAlias('latest'), 'latest version 1236');
- self::assertSame('1236', $config->resolveVersionAlias('1236'), 'identical version');
- self::assertNull($config->resolveVersionAlias('123678'), 'unknown version');
-
- $config->getVersion('1236')->markMigrated();
-
- self::assertSame('1235', $config->getPrevVersion(), 'prev version 1235');
- self::assertSame('1236', $config->getCurrentVersion(), 'current version 1236');
- self::assertNull($config->getNextVersion(), 'no next version');
- self::assertSame('1236', $config->getLatestVersion(), 'latest version 1236');
- }
-
- public function testDeltaVersion() : void
- {
- $config = $this->getSqliteConfiguration();
- $config->registerMigrations([
- '1234' => Version1Test::class,
- '1235' => Version2Test::class,
- '1236' => Version3Test::class,
- ]);
-
- self::assertNull($config->getDeltaVersion('-1'), 'no current-1 version');
- self::assertSame('1234', $config->getDeltaVersion('+1'), 'current+1 is 1234');
- self::assertSame('1235', $config->getDeltaVersion('+2'), 'current+2 is 1235');
- self::assertSame('1236', $config->getDeltaVersion('+3'), 'current+3 is 1236');
- self::assertNull($config->getDeltaVersion('+4'), 'no current+4 version');
-
- $config->getVersion('1234')->markMigrated();
-
- self::assertNull($config->getDeltaVersion('-2'), 'no current-2 version');
- self::assertSame('0', $config->getDeltaVersion('-1'), 'current-1 is 0');
- self::assertSame('1235', $config->getDeltaVersion('+1'), 'current+1 is 1235');
- self::assertSame('1236', $config->getDeltaVersion('+2'), 'current+2 is 1236');
- self::assertNull($config->getDeltaVersion('+3'), 'no current+3');
-
- $config->getVersion('1235')->markMigrated();
-
- self::assertNull($config->getDeltaVersion('-3'), 'no current-3 version');
- self::assertSame('0', $config->getDeltaVersion('-2'), 'current-2 is 0');
- self::assertSame('1234', $config->getDeltaVersion('-1'), 'current-1 is 1234');
- self::assertSame('1236', $config->getDeltaVersion('+1'), 'current+1 is 1236');
- self::assertNull($config->getDeltaVersion('+2'), 'no current+2');
-
- $config->getVersion('1236')->markMigrated();
-
- self::assertNull($config->getDeltaVersion('-4'), 'no current-4 version');
- self::assertSame('0', $config->getDeltaVersion('-3'), 'current-3 is 0');
- self::assertSame('1234', $config->getDeltaVersion('-2'), 'current-2 is 1234');
- self::assertSame('1235', $config->getDeltaVersion('-1'), 'current-1 is 1235');
- self::assertNull($config->getDeltaVersion('+1'), 'no current+1');
- }
-
- public function testGetAvailableVersions() : void
- {
- $config = $this->getSqliteConfiguration();
-
- $config->registerMigration('1234', Version1Test::class);
- self::assertSame(['1234'], $config->getAvailableVersions());
- }
-
- public function testDispatchEventProxiesToConnectionsEventManager() : void
- {
- $config = $this->getSqliteConfiguration();
- $config->getConnection()
- ->getEventManager()
- ->addEventSubscriber($listener = new EventVerificationListener());
-
- $config->dispatchEvent(
- Events::onMigrationsMigrating,
- $ea = new MigrationsEventArgs($config, 'up', false)
- );
-
- self::assertArrayHasKey(Events::onMigrationsMigrating, $listener->events);
- self::assertSame($ea, $listener->events[Events::onMigrationsMigrating][0]);
- }
-
- /**
- * @dataProvider autoloadVersionProvider
- */
- public function testGetVersionAutoloadVersion(string $version) : void
- {
- $config = $this->getSqliteConfiguration();
- $config->setMigrationsNamespace('Doctrine\Migrations\Tests\Stub\Configuration\AutoloadVersions');
- $config->setMigrationsDirectory(__DIR__ . '/Stub/Configuration/AutoloadVersions');
-
- $result = $config->getVersion($version);
-
- self::assertSame($version, $result->getVersion());
- }
-
- public function testGetVersionNotFound() : void
- {
- $config = $this->getSqliteConfiguration();
-
- $this->expectException(MigrationException::class);
-
- $config->getVersion('foo');
- }
-
- /**
- * @dataProvider versionProvider
- */
- public function testGetDatetime(string $version, string $return) : void
- {
- $config = $this->getSqliteConfiguration();
-
- self::assertSame($return, $config->getDateTime($version));
- }
-
- public function testDryRunMigratedAndCurrentVersions() : void
- {
- // migrations table created
- $config1 = $this->getSqliteConfiguration();
- $config1->setIsDryRun(false);
-
- self::assertSame('0', $config1->getCurrentVersion(), 'current version 0');
- self::assertTrue($config1->getConnection()->getSchemaManager()->tablesExist([$config1->getMigrationsTableName()]));
-
- // migrations table created
- $config2 = $this->getSqliteConfiguration();
- $config2->setIsDryRun(false);
-
- self::assertSame([], $config2->getMigratedVersions());
- self::assertTrue($config2->getConnection()->getSchemaManager()->tablesExist([$config2->getMigrationsTableName()]));
-
- // no migrations table created
- $config3 = $this->getSqliteConfiguration();
- $config3->setIsDryRun(true);
-
- self::assertSame('0', $config3->getCurrentVersion(), 'current version 0');
- self::assertFalse($config3->getConnection()->getSchemaManager()->tablesExist([$config3->getMigrationsTableName()]));
-
- self::assertSame([], $config3->getMigratedVersions());
- self::assertFalse($config3->getConnection()->getSchemaManager()->tablesExist([$config3->getMigrationsTableName()]));
-
- // gets the correct migration from the table, if the table exists
- $config = $this->getSqliteConfiguration();
- $config->registerMigrations([
- 1234 => Version1Test::class,
- 1235 => Version2Test::class,
- ]);
-
- $config->getVersion('1234')->markMigrated();
- $config->setIsDryRun(true);
-
- self::assertSame('1234', $config->getCurrentVersion(), 'current version 1234');
- self::assertSame('1235', $config->getNextVersion(), 'next version 1235');
-
- self::assertSame(['1234'], $config->getMigratedVersions());
- self::assertTrue($config->getConnection()->getSchemaManager()->tablesExist([$config->getMigrationsTableName()]));
- }
-
- /**
- * @return string[][]
- */
- public function versionProvider() : array
- {
- return [
- ['20150101123545Version', '2015-01-01 12:35:45'],
- ['tralalaVersion', ''],
- ['0000254Version', ''],
- ['0000254BaldlfqjdVersion', ''],
- ['20130101123545Version', '2013-01-01 12:35:45'],
- ['20150202042811', '2015-02-02 04:28:11'],
- ['20150202162811', '2015-02-02 16:28:11'],
- ];
- }
-
- /**
- * @return string[][]
- */
- public function autoloadVersionProvider() : array
- {
- return [
- ['1Test'],
- ['2Test'],
- ['3Test'],
- ['4Test'],
- ['5Test'],
- ];
- }
-
- /**
- * @dataProvider validCustomTemplates
- */
- public function testSetCustomTemplateShould(?string $template) : void
- {
- $config = new Configuration($this->getSqliteConnection());
- $config->setCustomTemplate($template);
-
- self::assertSame($template, $config->getCustomTemplate());
- }
-
- /**
- * @return string[][]|null[][]
- */
- public function validCustomTemplates() : array
- {
- return [
- 'null template' => [null],
- 'shiny template' => ['my-awesome-template.php'],
- ];
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/DependencyFactoryTest.php b/tests/Doctrine/Migrations/Tests/DependencyFactoryTest.php
new file mode 100644
index 0000000000..bf6c913c8c
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/DependencyFactoryTest.php
@@ -0,0 +1,54 @@
+connection = $this->createMock(Connection::class);
+ }
+
+ public function testFinderForYearMonthStructure() : void
+ {
+ $conf = new Configuration();
+ $conf->setMigrationsAreOrganizedByYearAndMonth(true);
+
+ $di = new DependencyFactory($conf, $this->connection);
+ $finder = $di->getMigrationsFinder();
+
+ self::assertInstanceOf(RecursiveRegexFinder::class, $finder);
+ }
+
+ public function testFinderForYearStructure() : void
+ {
+ $conf = new Configuration();
+ $conf->setMigrationsAreOrganizedByYear(true);
+
+ $di = new DependencyFactory($conf, $this->connection);
+ $finder = $di->getMigrationsFinder();
+
+ self::assertInstanceOf(RecursiveRegexFinder::class, $finder);
+ }
+
+ public function testFinder() : void
+ {
+ $conf = new Configuration();
+ $di = new DependencyFactory($conf, $this->connection);
+ $finder = $di->getMigrationsFinder();
+
+ self::assertInstanceOf(GlobFinder::class, $finder);
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Event/EventArgsTest.php b/tests/Doctrine/Migrations/Tests/Event/EventArgsTest.php
new file mode 100644
index 0000000000..68a9e03d0f
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Event/EventArgsTest.php
@@ -0,0 +1,56 @@
+connection = $this->createMock(Connection::class);
+ $this->config = $this->createMock(MigratorConfiguration::class);
+ $migration = $this->createMock(AbstractMigration::class);
+ $this->plan = new MigrationPlan(new Version('1'), $migration, Direction::UP);
+ }
+
+ public function testMigrationsVersionEventArgs() : void
+ {
+ $event = new MigrationsVersionEventArgs($this->connection, $this->plan, $this->config);
+
+ self::assertSame($this->connection, $event->getConnection());
+ self::assertSame($this->config, $event->getMigratorConfiguration());
+ self::assertSame($this->plan, $event->getPlan());
+ }
+
+ public function testMigrationsEventArgs() : void
+ {
+ $plan = new MigrationPlanList([], Direction::UP);
+ $event = new MigrationsEventArgs($this->connection, $plan, $this->config);
+
+ self::assertSame($this->connection, $event->getConnection());
+ self::assertSame($this->config, $event->getMigratorConfiguration());
+ self::assertSame($plan, $event->getPlan());
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Event/Listeners/AutoCommitListenerTest.php b/tests/Doctrine/Migrations/Tests/Event/Listeners/AutoCommitListenerTest.php
index c03df1851c..4b15b8e0a8 100644
--- a/tests/Doctrine/Migrations/Tests/Event/Listeners/AutoCommitListenerTest.php
+++ b/tests/Doctrine/Migrations/Tests/Event/Listeners/AutoCommitListenerTest.php
@@ -5,10 +5,12 @@
namespace Doctrine\Migrations\Tests\Event\Listeners;
use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Event\Listeners\AutoCommitListener;
use Doctrine\Migrations\Event\MigrationsEventArgs;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
+use Doctrine\Migrations\MigratorConfiguration;
use Doctrine\Migrations\Tests\MigrationTestCase;
+use Doctrine\Migrations\Version\Direction;
use PHPUnit\Framework\MockObject\MockObject;
class AutoCommitListenerTest extends MigrationTestCase
@@ -64,6 +66,11 @@ private function willNotCommit() : void
private function createArgs(bool $isDryRun) : MigrationsEventArgs
{
- return new MigrationsEventArgs(new Configuration($this->conn), 'up', $isDryRun);
+ $plan = new MigrationPlanList([], Direction::UP);
+
+ $configsMigration = new MigratorConfiguration();
+ $configsMigration->setDryRun($isDryRun);
+
+ return new MigrationsEventArgs($this->conn, $plan, $configsMigration);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/FileQueryWriterTest.php b/tests/Doctrine/Migrations/Tests/FileQueryWriterTest.php
index 2d484828f9..cb753f07c1 100644
--- a/tests/Doctrine/Migrations/Tests/FileQueryWriterTest.php
+++ b/tests/Doctrine/Migrations/Tests/FileQueryWriterTest.php
@@ -4,53 +4,55 @@
namespace Doctrine\Migrations\Tests;
-use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\Migrations\FileQueryWriter;
-use Doctrine\Migrations\Generator\FileBuilder;
-use Doctrine\Migrations\OutputWriter;
+use Doctrine\Migrations\Generator\FileBuilderInterface;
use Doctrine\Migrations\Version\Direction;
+use Psr\Log\LoggerInterface;
use function file_get_contents;
-use function sprintf;
+use function glob;
+use function is_dir;
+use function is_file;
+use function realpath;
+use function sys_get_temp_dir;
use function unlink;
final class FileQueryWriterTest extends MigrationTestCase
{
- private const TABLE_NAME = 'migration_versions';
- private const COLUMN_NAME = 'version';
- private const EXECUTED_AT_COLUMN_NAME = 'executedAt';
- private const UP_QUERY = 'INSERT INTO %s (%s, %s) VALUES (\'1\', CURRENT_TIMESTAMP)';
- private const DOWN_QUERY = 'DELETE FROM %s WHERE %s = \'1\'';
+ /** @return string[] */
+ private function getSqlFilesList(string $path) : array
+ {
+ if (is_dir($path)) {
+ return glob(realpath($path) . '/*.sql') ?: [];
+ }
- /**
- * @param string[][] $queries
- *
- * @dataProvider writeProvider
- */
- public function testWrite(
- string $path,
- string $direction,
- array $queries,
- OutputWriter $outputWriter
- ) : void {
- $platform = $this->createMock(AbstractPlatform::class);
+ if (is_file($path)) {
+ return [$path];
+ }
- $migrationFileBuilder = new FileBuilder(
- $platform,
- self::TABLE_NAME,
- self::COLUMN_NAME,
- self::EXECUTED_AT_COLUMN_NAME
- );
+ return [];
+ }
+
+ public function testWrite() : void
+ {
+ $path = sys_get_temp_dir();
+ $migrationFileBuilder = $this->createMock(FileBuilderInterface::class);
+ $migrationFileBuilder
+ ->expects(self::atLeastOnce())
+ ->method('buildMigrationFile')
+ ->with(['A'], Direction::UP)
+ ->willReturn('foo');
+
+ $logger = $this->createMock(LoggerInterface::class);
+ $logger->expects(self::atLeastOnce())
+ ->method('info')
+ ->with(self::isType('string'));
$writer = new FileQueryWriter(
- $outputWriter,
- $migrationFileBuilder
+ $migrationFileBuilder,
+ $logger
);
- $platform->expects(self::any())
- ->method('getCurrentTimestampSQL')
- ->willReturn('CURRENT_TIMESTAMP');
-
- self::assertTrue($writer->write($path, $direction, $queries));
+ self::assertTrue($writer->write($path, Direction::UP, ['A']));
$files = $this->getSqlFilesList($path);
@@ -58,45 +60,10 @@ public function testWrite(
foreach ($files as $file) {
$contents = file_get_contents($file);
-
unlink($file);
- if ($direction === Direction::UP) {
- $expectedQuery = self::UP_QUERY;
-
- $expectedSql = sprintf(
- $expectedQuery,
- self::TABLE_NAME,
- self::COLUMN_NAME,
- self::EXECUTED_AT_COLUMN_NAME
- );
- } else {
- $expectedQuery = self::DOWN_QUERY;
-
- $expectedSql = sprintf(
- $expectedQuery,
- self::TABLE_NAME,
- self::COLUMN_NAME
- );
- }
-
self::assertNotEmpty($contents);
- self::assertContains($expectedSql, $contents);
+ self::assertContains('foo', $contents);
}
}
-
- /** @return mixed[][] */
- public function writeProvider() : array
- {
- $outputWriter = $this->createMock(OutputWriter::class);
-
- $outputWriter->expects(self::atLeastOnce())
- ->method('write')
- ->with(self::isType('string'));
-
- return [
- [__DIR__, Direction::UP, ['1' => ['SHOW DATABASES']], $outputWriter],
- [__DIR__, Direction::DOWN, ['1' => ['SHOW DATABASES']], $outputWriter],
- ];
- }
}
diff --git a/tests/Doctrine/Migrations/Tests/Finder/FinderTestCase.php b/tests/Doctrine/Migrations/Tests/Finder/FinderTestCase.php
index 184f7ce2b4..02db09de03 100644
--- a/tests/Doctrine/Migrations/Tests/Finder/FinderTestCase.php
+++ b/tests/Doctrine/Migrations/Tests/Finder/FinderTestCase.php
@@ -14,12 +14,10 @@ abstract class FinderTestCase extends MigrationTestCase
public function testClassesInMultipleNamespacesCanBeLoadedByTheFinder() : void
{
- $versions = $this->finder->findMigrations(__DIR__ . '/_features/MultiNamespace');
+ $versions = $this->finder->findMigrations(__DIR__ . '/_features/MultiNamespace', 'TestMigrations');
- self::assertSame([
- '0001' => 'TestMigrations\\Test\\Version0001',
- '0002' => 'TestMigrations\\TestOther\\Version0002',
- ], $versions);
+ self::assertContains('TestMigrations\\Test\\Version0001', $versions);
+ self::assertContains('TestMigrations\\TestOther\\Version0002', $versions);
}
public function testOnlyClassesInTheProvidedNamespaceAreLoadedWhenNamespaceIsProvided() : void
@@ -29,6 +27,6 @@ public function testOnlyClassesInTheProvidedNamespaceAreLoadedWhenNamespaceIsPro
'TestMigrations\\Test'
);
- self::assertSame(['0001' => 'TestMigrations\\Test\\Version0001'], $versions);
+ self::assertSame(['TestMigrations\\Test\\Version0001'], $versions);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Finder/GlobFinderTest.php b/tests/Doctrine/Migrations/Tests/Finder/GlobFinderTest.php
index 6dcdce18fa..6b6e10ae8b 100644
--- a/tests/Doctrine/Migrations/Tests/Finder/GlobFinderTest.php
+++ b/tests/Doctrine/Migrations/Tests/Finder/GlobFinderTest.php
@@ -27,10 +27,8 @@ public function testFindMigrationsReturnsTheExpectedFilesFromDirectory() : void
{
$migrations = $this->finder->findMigrations(__DIR__ . '/_files');
- self::assertArrayHasKey('20150502000000', $migrations);
- self::assertSame('TestMigrations\\Version20150502000000', $migrations['20150502000000']);
- self::assertArrayHasKey('20150502000001', $migrations);
- self::assertSame('TestMigrations\\Version20150502000001', $migrations['20150502000001']);
+ self::assertContains('TestMigrations\\Version20150502000000', $migrations);
+ self::assertContains('TestMigrations\\Version20150502000001', $migrations);
}
protected function setUp() : void
diff --git a/tests/Doctrine/Migrations/Tests/Finder/RecursiveRegexFinderTest.php b/tests/Doctrine/Migrations/Tests/Finder/RecursiveRegexFinderTest.php
index 2d60622f2c..4918712055 100644
--- a/tests/Doctrine/Migrations/Tests/Finder/RecursiveRegexFinderTest.php
+++ b/tests/Doctrine/Migrations/Tests/Finder/RecursiveRegexFinderTest.php
@@ -7,19 +7,13 @@
use Doctrine\Migrations\Finder\RecursiveRegexFinder;
use InvalidArgumentException;
use const PHP_OS;
-use function asort;
use function count;
+use function in_array;
+use function sort;
use function stripos;
class RecursiveRegexFinderTest extends FinderTestCase
{
- public function testVersionNameCausesErrorWhen0() : void
- {
- $this->expectException(InvalidArgumentException::class);
-
- $this->finder->findMigrations(__DIR__ . '/_regression/NoVersionNamed0');
- }
-
public function testBadFilenameCausesErrorWhenFindingMigrations() : void
{
$this->expectException(InvalidArgumentException::class);
@@ -39,28 +33,24 @@ public function testFindMigrationsReturnsTheExpectedFilesFromDirectory() : void
$migrations = $this->finder->findMigrations(__DIR__ . '/_files');
$tests = [
- '20150502000000' => 'TestMigrations\\Version20150502000000',
- '20150502000001' => 'TestMigrations\\Version20150502000001',
- '20150502000003' => 'TestMigrations\\Version20150502000003',
- '20150502000004' => 'TestMigrations\\Version20150502000004',
- '20150502000005' => 'TestMigrations\\Version20150502000005',
- '1ResetVersions' => 'TestMigrations\\Version1ResetVersions',
+ 'TestMigrations\\Version20150502000000',
+ 'TestMigrations\\Version20150502000001',
+ 'TestMigrations\\Version20150502000003',
+ 'TestMigrations\\Version20150502000004',
+ 'TestMigrations\\Version20150502000005',
+ 'TestMigrations\\Version1ResetVersions',
+ 'TestMigrations\\DifferentNamingSchema',
];
if (stripos(PHP_OS, 'Win') === false) {
- $tests['1SymlinkedFile'] = 'TestMigrations\\Version1SymlinkedFile';
+ $tests[] = 'TestMigrations\\Version1SymlinkedFile';
}
self::assertCount(count($tests), $migrations); // Windows does not support symlinks
- foreach ($tests as $version => $namespace) {
- self::assertArrayHasKey($version, $migrations);
- self::assertSame($namespace, $migrations[$version]);
+ foreach ($tests as $fqcn) {
+ self::assertTrue(in_array($fqcn, $migrations, true));
}
- $migrationsForTestSort = $migrations;
-
- asort($migrationsForTestSort);
- self::assertSame($migrations, $migrationsForTestSort, 'Finder have to return sorted list of the files.');
self::assertArrayNotHasKey('InvalidVersion20150502000002', $migrations);
self::assertArrayNotHasKey('Version20150502000002', $migrations);
self::assertArrayNotHasKey('20150502000002', $migrations);
@@ -73,10 +63,15 @@ public function testFindMigrationsCanLocateClassesInNestedNamespacesAndDirectori
{
$versions = $this->finder->findMigrations(__DIR__ . '/_features/MultiNamespaceNested');
- self::assertSame([
- '0001' => 'TestMigrations\\MultiNested\\Version0001',
- '0002' => 'TestMigrations\\MultiNested\\Deep\\Version0002',
- ], $versions);
+ $expectedVersions = [
+ 'TestMigrations\\MultiNested\\Version0001',
+ 'TestMigrations\\MultiNested\\Deep\\Version0002',
+ ];
+
+ sort($expectedVersions);
+ sort($versions);
+
+ self::assertSame($expectedVersions, $versions);
}
public function testMigrationsInSubnamespaceAreLoadedIfNamespaceIsParentNamespace() : void
@@ -86,10 +81,15 @@ public function testMigrationsInSubnamespaceAreLoadedIfNamespaceIsParentNamespac
'TestMigrations\\MultiNested'
);
- self::assertSame([
- '0001' => 'TestMigrations\MultiNested\Version0001',
- '0002' => 'TestMigrations\MultiNested\Deep\Version0002',
- ], $versions);
+ $expectedVersions = [
+ 'TestMigrations\MultiNested\Version0001',
+ 'TestMigrations\MultiNested\Deep\Version0002',
+ ];
+
+ sort($expectedVersions);
+ sort($versions);
+
+ self::assertSame($expectedVersions, $versions);
}
public function testOnlyMigrationsInTheProvidedNamespacesAreLoadedIfNamespaceIsProvided() : void
@@ -99,7 +99,7 @@ public function testOnlyMigrationsInTheProvidedNamespacesAreLoadedIfNamespaceIsP
'TestMigrations\\MultiNested\\Deep'
);
- self::assertSame(['0002' => 'TestMigrations\MultiNested\Deep\Version0002'], $versions);
+ self::assertSame(['TestMigrations\MultiNested\Deep\Version0002'], $versions);
}
protected function setUp() : void
diff --git a/tests/Doctrine/Migrations/Tests/Finder/_regression/NoVersionNamed0/Version0.php b/tests/Doctrine/Migrations/Tests/Finder/_files/DifferentNamingSchema.php
similarity index 70%
rename from tests/Doctrine/Migrations/Tests/Finder/_regression/NoVersionNamed0/Version0.php
rename to tests/Doctrine/Migrations/Tests/Finder/_files/DifferentNamingSchema.php
index 6542df135d..c86db651ac 100644
--- a/tests/Doctrine/Migrations/Tests/Finder/_regression/NoVersionNamed0/Version0.php
+++ b/tests/Doctrine/Migrations/Tests/Finder/_files/DifferentNamingSchema.php
@@ -2,12 +2,12 @@
declare(strict_types=1);
-namespace Doctrine\Migrations\Tests\Finder\Regression\NoVersionNamed0;
+namespace TestMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-class Version0 extends AbstractMigration
+class DifferentNamingSchema extends AbstractMigration
{
public function up(Schema $schema) : void
{
diff --git a/tests/Doctrine/Migrations/Tests/Functional/CliTest.php b/tests/Doctrine/Migrations/Tests/Functional/CliTest.php
deleted file mode 100644
index dc57cbd0e5..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/CliTest.php
+++ /dev/null
@@ -1,382 +0,0 @@
-expectException(RuntimeException::class);
- $this->expectExceptionMessage('Delete any previous migrations before dumping your schema.');
-
- $this->executeCommand('migrations:dump-schema');
- }
-
- public function testRollup() : void
- {
- $output = $this->executeCommand('migrations:rollup');
-
- self::assertRegExp('/Rolled up migrations to version 20150426000000/', $output);
- }
-
- public function testMigrationLifecycleFromCommandLine() : void
- {
- $output = $this->executeCommand('migrations:status');
- self::assertSuccessfulExit();
- self::assertRegExp('/available migrations:\s+1/im', $output);
- self::assertRegExp('/new migrations:\s+1/im', $output);
-
- $output = $this->executeCommand('migrations:latest');
- self::assertContains('20150426000000', $output);
-
- $this->executeCommand('migrations:migrate', 'config.yml', ['--no-interaction']);
- self::assertSuccessfulExit();
-
- $output = $this->executeCommand('migrations:status');
- self::assertSuccessfulExit();
- self::assertRegExp('/^.*available migrations:\s+1/im', $output);
- self::assertRegExp('/^.*new migrations:\s+0/im', $output);
- }
-
- public function testGenerateCommandAddsNewVersion() : void
- {
- self::assertVersionCount(0, 'Should start with no versions');
- $this->executeCommand('migrations:generate');
- self::assertSuccessfulExit();
- self::assertVersionCount(1, 'generate command should add one version');
-
- $output = $this->executeCommand('migrations:status');
- self::assertSuccessfulExit();
- self::assertRegExp('/available migrations:\s+2/im', $output);
- }
-
- public function testGenerateCommandAddsNewMigrationOrganizedByYearAndMonth() : void
- {
- self::assertVersionCount(0, 'Should start with no versions');
- $this->executeCommand('migrations:generate', 'config_organize_by_year_and_month.xml');
- self::assertSuccessfulExit();
- self::assertVersionCount(1, 'generate command should add one version');
-
- $output = $this->executeCommand('migrations:status', 'config_organize_by_year_and_month.xml');
- self::assertSuccessfulExit();
- self::assertRegExp('/available migrations:\s+1/im', $output);
- }
-
- public function testMigrationDiffWritesNewMigrationWithExpectedSql() : void
- {
- $this->withDiffCommand(new StubSchemaProvider($this->getSchema()));
- self::assertVersionCount(0, 'should start with no versions');
- $this->executeCommand('migrations:diff');
- self::assertSuccessfulExit();
- self::assertVersionCount(1, 'diff command should add one version');
-
- $output = $this->executeCommand('migrations:status');
- self::assertSuccessfulExit();
- self::assertRegExp('/available migrations:\s+2/im', $output);
-
- $versionClassContents = $this->getFileContentsForLatestVersion();
-
- self::assertContains('CREATE TABLE bar', $versionClassContents);
- self::assertContains('DROP TABLE bar', $versionClassContents);
- }
-
- public function testMigrationDiffWritesNewMigrationWithFormattedSql() : void
- {
- $this->withDiffCommand(new StubSchemaProvider($this->getSchema()));
- self::assertVersionCount(0, 'should start with no versions');
- $this->executeCommand(
- 'migrations:diff',
- 'config.yml',
- [
- '--formatted' => null,
- '--line-length' => 50,
- ]
- );
- self::assertSuccessfulExit();
- self::assertVersionCount(1, 'diff command should add one version');
-
- $output = $this->executeCommand('migrations:status');
- self::assertSuccessfulExit();
- self::assertRegExp('/available migrations:\s+2/im', $output);
-
- $versionClassContents = $this->getFileContentsForLatestVersion();
-
- self::assertContains("CREATE TABLE foo (\n", $versionClassContents);
- self::assertContains('DROP TABLE bar', $versionClassContents);
- }
-
- public function testMigrationDiffWithEntityManagerGeneratesMigrationFromEntities() : void
- {
- $config = OrmSetup::createXMLMetadataConfiguration([__DIR__ . '/_files/entities'], true);
- $entityManager = EntityManager::create($this->conn, $config);
- $this->application->getHelperSet()->set(
- new EntityManagerHelper($entityManager),
- 'em'
- );
- $this->withDiffCommand();
-
- self::assertVersionCount(0, 'should start with no versions');
- $this->executeCommand('migrations:diff');
- self::assertSuccessfulExit();
- self::assertVersionCount(1, 'diff command should add one version');
-
- $output = $this->executeCommand('migrations:status');
- self::assertSuccessfulExit();
- self::assertRegExp('/available migrations:\s+2/im', $output);
-
- $versionClassContents = $this->getFileContentsForLatestVersion();
- self::assertContains('CREATE TABLE sample_entity', $versionClassContents);
- self::assertContains('DROP TABLE sample_entity', $versionClassContents);
- }
-
- public function testDiffCommandWithSchemaFilterOnlyWorksWithTablesThatMatchFilter() : void
- {
- $this->conn->getConfiguration()->setSchemaAssetsFilter(
- static function ($assetName) {
- if ($assetName instanceof AbstractAsset) {
- $assetName = $assetName->getName();
- }
-
- return preg_match('/^bar$/', $assetName);
- }
- );
-
- $this->withDiffCommand(new StubSchemaProvider($this->getSchema()));
- self::assertVersionCount(0, 'should start with no versions');
- $this->executeCommand('migrations:diff');
- self::assertSuccessfulExit();
- self::assertVersionCount(1, 'diff command should add one version');
-
- $versionClassContents = $this->getFileContentsForLatestVersion();
- self::assertContains('CREATE TABLE bar', $versionClassContents);
- self::assertContains('DROP TABLE bar', $versionClassContents);
- self::assertNotContains(
- 'CREATE TABLE foo',
- $versionClassContents,
- 'should ignore the "foo" table due to schema asset filter'
- );
- }
-
- /**
- * @see https://github.com/doctrine/migrations/issues/179
- *
- * @group regression
- */
- public function testDiffCommandSchemaFilterAreCaseSensitive() : void
- {
- $this->conn->getConfiguration()->setSchemaAssetsFilter(
- static function ($assetName) {
- if ($assetName instanceof AbstractAsset) {
- $assetName = $assetName->getName();
- }
-
- return preg_match('/^FOO$/', $assetName);
- }
- );
-
- $schema = new Schema();
- $t = $schema->createTable('FOO');
- $t->addColumn('id', 'integer', ['autoincrement' => true]);
- $t->setPrimaryKey(['id']);
-
- $this->withDiffCommand(new StubSchemaProvider($schema));
- self::assertVersionCount(0, 'should start with no versions');
- $output = $this->executeCommand('migrations:diff');
- self::assertSuccessfulExit();
- self::assertVersionCount(1, 'diff command should add one version');
-
- $versionClassContents = $this->getFileContentsForLatestVersion();
- self::assertContains('CREATE TABLE FOO', $versionClassContents);
- self::assertContains('DROP TABLE FOO', $versionClassContents);
- }
-
- protected function setUp() : void
- {
- $migrationsDbFilePath =
- __DIR__ . DIRECTORY_SEPARATOR . '_files ' . DIRECTORY_SEPARATOR . 'migrations.db';
- if (file_exists($migrationsDbFilePath)) {
- @unlink($migrationsDbFilePath);
- }
- Helper::deleteDir(
- __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'migrations'
- );
-
- $this->conn = $this->getSqliteConnection();
- $this->application = new Application('Doctrine Migrations Test', Versions::getVersion('doctrine/migrations'));
- $this->application->setCatchExceptions(false);
- $this->application->setAutoExit(false);
- $this->application->getHelperSet()->set(
- new ConnectionHelper($this->conn),
- 'connection'
- );
- $this->application->addCommands([
- new MigrationCommands\DumpSchemaCommand(),
- new MigrationCommands\ExecuteCommand(),
- new MigrationCommands\GenerateCommand(),
- new MigrationCommands\LatestCommand(),
- new MigrationCommands\MigrateCommand(),
- new MigrationCommands\RollupCommand(),
- new MigrationCommands\StatusCommand(),
- new MigrationCommands\VersionCommand(),
- ]);
- }
-
- protected function withDiffCommand(?SchemaProviderInterface $provider = null) : void
- {
- $this->application->add(new MigrationCommands\DiffCommand($provider));
- }
-
- /**
- * @param mixed[] $args
- */
- protected function executeCommand(
- string $commandName,
- string $configFile = 'config.yml',
- array $args = []
- ) : string {
- $input = new ArrayInput(array_merge(
- [
- 'command' => $commandName,
- '--no-ansi' => null,
- '--configuration' => __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . $configFile,
- ],
- $args
- ));
-
- $output = $this->getOutputStream();
-
- $this->lastExit = $this->application->run($input, $output);
-
- return $this->getOutputStreamContent($output);
- }
-
- protected function assertSuccessfulExit(string $msg = '') : void
- {
- self::assertSame(0, $this->lastExit, $msg);
- }
-
- protected function assertVersionCount(int $count, string $msg = '') : void
- {
- self::assertCount($count, $this->findMigrations(), $msg);
- }
-
- protected function getSchema() : Schema
- {
- $schema = new Schema();
-
- $table = $schema->createTable('foo');
- $table->addColumn('id', 'integer', ['autoincrement' => true]);
- $table->setPrimaryKey(['id']);
-
- $table = $schema->createTable('bar');
- $table->addColumn('id', 'integer', ['autoincrement' => true]);
- $table->setPrimaryKey(['id']);
-
- return $schema;
- }
-
- /**
- * @return string[]
- */
- private function findMigrations() : array
- {
- $finder = new RecursiveRegexFinder();
-
- return $finder->findMigrations(
- __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'migrations'
- );
- }
-
- /**
- * @return string file content for latest version
- */
- private function getFileContentsForLatestVersion() : string
- {
- $versions = $this->findMigrations();
- self::assertCount(
- 1,
- $versions,
- 'This method is designed to work for one existing version, you have ' . count($versions) . ' versions'
- );
-
- $versionClassName = reset($versions);
- $versionClassReflected = new ReflectionClass($versionClassName);
-
- $fileName = $versionClassReflected->getFileName();
-
- assert($fileName !== false);
-
- $contents = file_get_contents($fileName);
-
- assert($contents !== false);
-
- return $contents;
- }
-}
-
-class FirstMigration extends AbstractMigration
-{
- public function up(Schema $schema) : void
- {
- $this->addSql('CREATE TABLE foo (id INTEGER AUTO_INCREMENT, PRIMARY KEY (id))');
- }
-
- public function down(Schema $schema) : void
- {
- $this->addSql('DROP TABLE foo');
- }
-}
-
-class SampleEntity
-{
- /** @var int|null */
- private $id;
-
- public function getId() : ?int
- {
- return $this->id;
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Functional/FunctionalTest.php b/tests/Doctrine/Migrations/Tests/Functional/FunctionalTest.php
deleted file mode 100644
index 98092caaca..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/FunctionalTest.php
+++ /dev/null
@@ -1,618 +0,0 @@
-connection = $this->getSqliteConnection();
- $this->config = self::createConfiguration($this->connection);
- }
-
- /**
- * @requires OS Linux|Darwin
- */
- public function testDoctrineMigrationsBin() : void
- {
- $process = new Process([__DIR__ . '/../../../../../bin/doctrine-migrations']);
- $process->run();
-
- self::assertTrue($process->isSuccessful());
-
- $output = $process->getOutput();
-
- self::assertNotEmpty($output);
-
- self::assertContains('migrations:execute', $output);
- self::assertContains('migrations:generate', $output);
- self::assertContains('migrations:latest', $output);
- self::assertContains('migrations:migrate', $output);
- self::assertContains('migrations:status', $output);
- self::assertContains('migrations:up-to-date', $output);
- self::assertContains('migrations:version', $output);
- }
-
- public function testMigrateUp() : void
- {
- $version = $this->createTestVersion($this->config, '1', MigrationMigrateUp::class);
-
- self::assertFalse($this->config->hasVersionMigrated($version));
- $version->execute('up');
-
- $schema = $this->connection->getSchemaManager()->createSchema();
- self::assertTrue($schema->hasTable('foo'));
- self::assertTrue($schema->getTable('foo')->hasColumn('id'));
- self::assertTrue($this->config->hasVersionMigrated($version));
- }
-
- public function testMigrateDown() : void
- {
- $version = $this->createTestVersion($this->config, '1', MigrationMigrateUp::class);
-
- self::assertFalse($this->config->hasVersionMigrated($version));
- $version->execute('up');
-
- $schema = $this->connection->getSchemaManager()->createSchema();
- self::assertTrue($schema->hasTable('foo'));
- self::assertTrue($schema->getTable('foo')->hasColumn('id'));
- self::assertTrue($this->config->hasVersionMigrated($version));
-
- $version->execute('down');
- $schema = $this->connection->getSchemaManager()->createSchema();
- self::assertFalse($schema->hasTable('foo'));
- self::assertFalse($this->config->hasVersionMigrated($version));
- }
-
- public function testSkipMigrateUp() : void
- {
- $version = $this->createTestVersion($this->config, '1', MigrationSkipMigration::class);
-
- self::assertFalse($this->config->hasVersionMigrated($version));
- $version->execute('up');
-
- $schema = $this->connection->getSchemaManager()->createSchema();
- self::assertFalse($schema->hasTable('foo'));
-
- self::assertTrue($this->config->hasVersionMigrated($version));
- }
-
- public function testMigrateSeveralSteps() : void
- {
- $this->config->registerMigration('1', MigrationMigrateUp::class);
- $this->config->registerMigration('2', MigrationSkipMigration::class);
- $this->config->registerMigration('3', MigrationMigrateFurther::class);
-
- self::assertSame('0', $this->config->getCurrentVersion());
- $migrations = $this->config->getMigrationsToExecute('up', '3');
-
- self::assertCount(3, $migrations);
- self::assertInstanceOf(MigrationMigrateUp::class, $migrations['1']->getMigration());
- self::assertInstanceOf(MigrationSkipMigration::class, $migrations['2']->getMigration());
- self::assertInstanceOf(MigrationMigrateFurther::class, $migrations['3']->getMigration());
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate('3');
-
- $schema = $this->config->getConnection()->getSchemaManager()->createSchema();
- self::assertTrue($schema->hasTable('foo'));
- self::assertTrue($schema->hasTable('bar'));
-
- self::assertSame('3', $this->config->getCurrentVersion());
- self::assertTrue($migrations['1']->isMigrated());
- self::assertTrue($migrations['2']->isMigrated());
- self::assertTrue($migrations['3']->isMigrated());
- }
-
- public function testMigrateToLastVersion() : void
- {
- $this->config->registerMigration('1', MigrationMigrateUp::class);
- $this->config->registerMigration('2', MigrationSkipMigration::class);
- $this->config->registerMigration('3', MigrationMigrateFurther::class);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate();
-
- self::assertSame('3', $this->config->getCurrentVersion());
- $migrations = $this->config->getMigrations();
- self::assertTrue($migrations['1']->isMigrated());
- self::assertTrue($migrations['2']->isMigrated());
- self::assertTrue($migrations['3']->isMigrated());
- }
-
- public function testDryRunMigration() : void
- {
- $this->config->registerMigration('1', MigrationMigrateUp::class);
- $this->config->registerMigration('2', MigrationSkipMigration::class);
- $this->config->registerMigration('3', MigrationMigrateFurther::class);
-
- $migratorConfiguration = (new MigratorConfiguration())
- ->setDryRun(true);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate('3', $migratorConfiguration);
-
- $schema = $this->config->getConnection()->getSchemaManager()->createSchema();
- self::assertFalse($schema->hasTable('foo'));
- self::assertFalse($schema->hasTable('bar'));
-
- self::assertSame('0', $this->config->getCurrentVersion());
- $migrations = $this->config->getMigrations();
- self::assertFalse($migrations['1']->isMigrated());
- self::assertFalse($migrations['2']->isMigrated());
- self::assertFalse($migrations['3']->isMigrated());
- }
-
- public function testDryRunWithTableCreatedWithSchemaInFirstMigration() : void
- {
- $this->config->registerMigration('1', DryRun1::class);
- $this->config->registerMigration('2', DryRun2::class);
-
- $migratorConfiguration = (new MigratorConfiguration())
- ->setDryRun(true);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate('2', $migratorConfiguration);
-
- $schema = $migratorConfiguration->getFromSchema();
-
- self::assertInstanceOf(Schema::class, $schema);
- self::assertTrue($schema->hasTable('foo'));
-
- $table = $schema->getTable('foo');
- self::assertTrue($table->hasColumn('bar'));
- }
-
- public function testMigrateDownSeveralSteps() : void
- {
- $this->config->registerMigration('1', MigrationMigrateUp::class);
- $this->config->registerMigration('2', MigrationSkipMigration::class);
- $this->config->registerMigration('3', MigrationMigrateFurther::class);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate('3');
-
- self::assertSame('3', $this->config->getCurrentVersion());
- $migrator->migrate('0');
-
- $schema = $this->config->getConnection()->getSchemaManager()->createSchema();
- self::assertFalse($schema->hasTable('foo'));
- self::assertFalse($schema->hasTable('bar'));
-
- self::assertSame('0', $this->config->getCurrentVersion());
- $migrations = $this->config->getMigrations();
- self::assertFalse($migrations['1']->isMigrated());
- self::assertFalse($migrations['2']->isMigrated());
- self::assertFalse($migrations['3']->isMigrated());
- }
-
- public function testAddSql() : void
- {
- $this->config->registerMigration('1', MigrateAddSqlTest::class);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate('1');
-
- $migrations = $this->config->getMigrations();
- self::assertTrue($migrations['1']->isMigrated());
-
- $schema = $this->config->getConnection()->getSchemaManager()->createSchema();
- self::assertTrue($schema->hasTable('test_add_sql_table'));
- $check = $this->config->getConnection()->fetchAll('select * from test_add_sql_table');
- self::assertNotEmpty($check);
- self::assertSame('test', $check[0]['test']);
-
- $migrator->migrate('0');
- self::assertFalse($migrations['1']->isMigrated());
- $schema = $this->config->getConnection()->getSchemaManager()->createSchema();
- self::assertFalse($schema->hasTable('test_add_sql_table'));
- }
-
- public function testAddSqlInPostUp() : void
- {
- $this->config->registerMigration('1', MigrateAddSqlPostAndPreUpAndDownTest::class);
- $tableName = MigrateAddSqlPostAndPreUpAndDownTest::TABLE_NAME;
-
- $this->config->getConnection()->executeQuery(sprintf('CREATE TABLE IF NOT EXISTS %s (test INT)', $tableName));
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate('1');
-
- $migrations = $this->config->getMigrations();
- self::assertTrue($migrations['1']->isMigrated());
-
- $check = $this->config->getConnection()->fetchColumn(
- sprintf('select SUM(test) as sum from %s', $tableName)
- );
-
- self::assertNotEmpty($check);
- self::assertSame('3', $check);
-
- $migrator->migrate('0');
- self::assertFalse($migrations['1']->isMigrated());
-
- $check = $this->config->getConnection()->fetchColumn(
- sprintf('select SUM(test) as sum from %s', $tableName)
- );
-
- self::assertNotEmpty($check);
- self::assertSame('12', $check);
-
- $this->config->getConnection()->executeQuery(sprintf('DROP TABLE %s ', $tableName));
- }
-
- public function testVersionInDatabaseWithoutRegisteredMigrationStillMigrates() : void
- {
- $this->config->registerMigration('1', MigrateAddSqlTest::class);
- $this->config->registerMigration('10', MigrationMigrateFurther::class);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate();
-
- $config = new Configuration($this->connection);
- $config->setMigrationsNamespace('Doctrine\Migrations\Tests\Functional');
- $config->setMigrationsDirectory('.');
- $config->registerMigration('1', MigrateAddSqlTest::class);
- $config->registerMigration('2', MigrationMigrateUp::class);
- $config->setMigrationsTableName('test_migrations_table');
- $config->setMigrationsColumnName('current_version');
-
- $migrator = $this->createTestMigrator($config);
- $migrator->migrate();
-
- $migrations = $config->getMigrations();
- self::assertTrue($migrations['1']->isMigrated());
- self::assertTrue($migrations['2']->isMigrated());
-
- self::assertSame('2', $config->getCurrentVersion());
- }
-
- public function testInterweavedMigrationsAreExecuted() : void
- {
- $this->config->registerMigration('1', MigrateAddSqlTest::class);
- $this->config->registerMigration('3', MigrationMigrateFurther::class);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate();
-
- $migrations = $this->config->getMigrations();
- self::assertTrue($migrations['1']->isMigrated());
- self::assertTrue($migrations['3']->isMigrated());
- self::assertSame('3', $this->config->getCurrentVersion());
-
- $config = new Configuration($this->connection);
- $config->setMigrationsNamespace('Doctrine\Migrations\Tests\Functional');
- $config->setMigrationsDirectory('.');
- $config->registerMigration('1', MigrateAddSqlTest::class);
- $config->registerMigration('2', MigrationMigrateUp::class);
- $config->registerMigration('3', MigrationMigrateFurther::class);
- $config->setMigrationsTableName('test_migrations_table');
- $config->setMigrationsColumnName('current_version');
-
- self::assertCount(1, $config->getMigrationsToExecute('up', '3'));
- $migrations = $config->getMigrationsToExecute('up', '3');
- self::assertArrayHasKey(2, $migrations);
- self::assertSame('2', $migrations['2']->getVersion());
-
- $migrator = $this->createTestMigrator($config);
- $migrator->migrate();
-
- $migrations = $config->getMigrations();
- self::assertTrue($migrations['1']->isMigrated());
- self::assertTrue($migrations['2']->isMigrated());
- self::assertTrue($migrations['3']->isMigrated());
-
- self::assertSame('3', $config->getCurrentVersion());
- }
-
- public function testMigrateToCurrentVersionReturnsEmpty() : void
- {
- $this->config->registerMigration('1', MigrateAddSqlTest::class);
- $this->config->registerMigration('2', MigrationMigrateFurther::class);
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate();
-
- $sql = $migrator->migrate();
-
- self::assertSame([], $sql);
- }
-
- /**
- * @see https://github.com/doctrine/migrations/issues/61
- *
- * @param string[] $migrations
- *
- * @group regression
- * @dataProvider provideTestMigrationNames
- */
- public function testMigrateExecutesOlderVersionsThatHaveNetYetBeenMigrated(array $migrations) : void
- {
- foreach ($migrations as $key => $class) {
- $migrator = $this->createTestMigrator($this->config);
- $this->config->registerMigration((string) $key, $class);
- $sql = $migrator->migrate();
- self::assertCount(1, $sql, 'should have executed one migration');
- }
- }
-
- public function testSchemaChangeAreNotTakenIntoAccountInPreAndPostMethod() : void
- {
- $version = $this->createTestVersion($this->config, '1', MigrationModifySchemaInPreAndPost::class);
-
- self::assertFalse($this->config->hasVersionMigrated($version));
- $queries = $version->execute('up')->getSql();
-
- $schema = $this->connection->getSchemaManager()->createSchema();
- self::assertTrue($schema->hasTable('foo'), 'The table foo is not present');
- self::assertFalse($schema->hasTable('bar'), 'The table bar is present');
- self::assertFalse($schema->hasTable('bar2'), 'The table bar2 is present');
-
- foreach ($queries as $query) {
- self::assertNotContains('bar', $query);
- self::assertNotContains('bar2', $query);
- }
-
- $queries = $version->execute('down')->getSql();
-
- $schema = $this->connection->getSchemaManager()->createSchema();
- self::assertFalse($schema->hasTable('foo'), 'The table foo is present');
- self::assertFalse($schema->hasTable('bar'), 'The table bar is present');
- self::assertFalse($schema->hasTable('bar2'), 'The table bar2 is present');
-
- foreach ($queries as $query) {
- self::assertNotContains('bar', $query);
- self::assertNotContains('bar2', $query);
- }
- }
-
- /**
- * @return mixed[][]
- */
- public function provideTestMigrationNames() : array
- {
- return [
- [
- [
- '20120228123443' => MigrateAddSqlTest::class,
- '20120228114838' => MigrationMigrateFurther::class,
- ],
- ],
- [
- [
- '002Test' => MigrateAddSqlTest::class,
- '001Test' => MigrationMigrateFurther::class,
- ],
- ],
- ];
- }
-
- public function testMigrationWorksWhenNoCallsAreMadeToTheSchema() : void
- {
- $schema = $this->createMock(Schema::class);
- $schemaDiffProvider = $this->createMock(SchemaDiffProviderInterface::class);
-
- $schemaDiffProvider->method('createFromSchema')->willReturn($schema);
- $schemaDiffProvider->method('getSqlDiffToMigrate')->willReturn([]);
- $schemaDiffProvider
- ->method('createToSchema')
- ->willReturnCallback(static function () use ($schema) {
- return $schema;
- });
-
- $version = $this->createTestVersion(
- $this->config,
- '1',
- MigrateNotTouchingTheSchema::class,
- $schemaDiffProvider
- );
-
- $version->execute('up');
-
- foreach (get_class_methods(Schema::class) as $method) {
- if (in_array($method, ['__construct', '__clone'], true)) {
- continue;
- }
-
- $schema->expects(self::never())->method($method);
- }
- }
-
- public function testSuccessfulMigrationDispatchesTheExpectedEvents() : void
- {
- $this->config->registerMigration('1', MigrationMigrateUp::class);
-
- $this->config->getConnection()->getEventManager()->addEventSubscriber(
- $listener = new EventVerificationListener()
- );
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate();
-
- self::assertCount(4, $listener->events);
-
- foreach ([
- Events::onMigrationsMigrating,
- Events::onMigrationsMigrated,
- Events::onMigrationsVersionExecuting,
- Events::onMigrationsVersionExecuted,
- ] as $eventName) {
- self::assertCount(1, $listener->events[$eventName]);
- self::assertArrayHasKey($eventName, $listener->events);
- }
- }
-
- public function testSkippedMigrationsDispatchesTheExpectedEvents() : void
- {
- $this->config->registerMigration('1', MigrationSkipMigration::class);
-
- $this->config->getConnection()->getEventManager()->addEventSubscriber(
- $listener = new EventVerificationListener()
- );
-
- $migrator = $this->createTestMigrator($this->config);
- $migrator->migrate();
-
- self::assertCount(4, $listener->events);
-
- foreach ([
- Events::onMigrationsMigrating,
- Events::onMigrationsMigrated,
- Events::onMigrationsVersionExecuting,
- Events::onMigrationsVersionSkipped,
- ] as $eventName) {
- self::assertArrayHasKey($eventName, $listener->events);
- }
- }
-
- /**
- * This uses a file path based SQL database to actually test the closing
- * of a connection with autocommit mode and re-opening it.
- *
- * @group https://github.com/doctrine/migrations/issues/496
- */
- public function testMigrateWithConnectionWithAutoCommitOffStillPersistsChanges() : void
- {
- $listener = new AutoCommitListener();
- [$conn, $config] = self::fileConnectionAndConfig();
- $config->registerMigration('1', MigrateWithDataModification::class);
- $migrator = $this->createTestMigrator($config);
- $conn->getEventManager()->addEventSubscriber($listener);
- $conn->exec('CREATE TABLE test_data_migration (test INTEGER)');
- $conn->commit();
-
- $migrator->migrate();
-
- self::assertCount(3, $conn->fetchAll('SELECT * FROM test_data_migration'), 'migration did not execute');
- $conn->close();
- self::assertCount(3, $conn->fetchAll('SELECT * FROM test_data_migration'));
- }
-
- public function testMigrationExecutedAt() : void
- {
- $version = $this->createTestVersion($this->config, '1', MigrationMigrateUp::class);
- $version->execute('up');
-
- $row = $this->config->getConnection()
- ->fetchAssoc('SELECT * FROM test_migrations_table');
-
- assert(is_array($row));
-
- self::assertSame('1', $row['current_version']);
- self::assertTrue(isset($row['executed_at']));
- self::assertNotNull($row['executed_at']);
- self::assertNotFalse(strtotime($row['executed_at']));
- }
-
- /**
- * @return Connection[]|Configuration[]
- */
- private static function fileConnectionAndConfig() : array
- {
- $path = __DIR__ . '/_files/db/sqlite_file_config.db';
-
- if (file_exists($path)) {
- @unlink($path);
- }
-
- $dbalConfig = new DbalConfig();
- $dbalConfig->setAutoCommit(false);
- $conn = DriverManager::getConnection([
- 'driver' => 'pdo_sqlite',
- 'path' => $path,
- ], $dbalConfig);
-
- return [$conn, self::createConfiguration($conn)];
- }
-
- private static function createConfiguration(Connection $conn) : Configuration
- {
- $config = new Configuration($conn);
- $config->setMigrationsNamespace('Doctrine\Migrations\Tests\Functional');
- $config->setMigrationsDirectory('.');
- $config->setMigrationsTableName('test_migrations_table');
- $config->setMigrationsColumnName('current_version');
-
- return $config;
- }
-
- private function createTestVersion(
- Configuration $configuration,
- string $versionName,
- string $className,
- ?SchemaDiffProviderInterface $schemaDiffProvider = null
- ) : Version {
- if ($schemaDiffProvider === null) {
- $schemaDiffProvider = new SchemaDiffProvider(
- $this->connection->getSchemaManager(),
- $this->connection->getDatabasePlatform()
- );
-
- $schemaDiffProvider = LazySchemaDiffProvider::fromDefaultProxyFactoryConfiguration(
- $schemaDiffProvider
- );
- }
-
- $parameterFormatter = new ParameterFormatter($this->connection);
-
- $symfonyStopwatch = new SymfonyStopwatch();
- $stopwatch = new Stopwatch($symfonyStopwatch);
-
- $versionExecutor = new Executor(
- $this->config,
- $this->connection,
- $schemaDiffProvider,
- $this->config->getOutputWriter(),
- $parameterFormatter,
- $stopwatch
- );
-
- return new Version($configuration, $versionName, $className, $versionExecutor);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Functional/MigrationTableManipulatorTest.php b/tests/Doctrine/Migrations/Tests/Functional/MigrationTableManipulatorTest.php
deleted file mode 100644
index 118eab593a..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/MigrationTableManipulatorTest.php
+++ /dev/null
@@ -1,110 +0,0 @@
-connection->getSchemaManager();
-
- self::assertTrue($this->trackingTableManipulator->createMigrationTable());
-
- self::assertTrue($schemaManager->tablesExist(['doctrine_migration_versions']));
- self::assertTrue($this->trackingTableStatus->isCreated());
- self::assertTrue($this->trackingTableStatus->isUpToDate());
-
- $table = $schemaManager->listTableDetails('doctrine_migration_versions');
-
- self::assertTrue($table->hasColumn('version'));
- self::assertTrue($table->getColumn('version')->getNotnull());
- self::assertSame(200, $table->getColumn('version')->getLength());
-
- self::assertTrue($table->hasColumn('executed_at'));
- self::assertTrue($table->getColumn('executed_at')->getNotnull());
-
- self::assertTrue($table->hasIndex('unique_version'));
- self::assertTrue($table->getIndex('unique_version')->isUnique());
- }
-
- public function testUpdateMigrationTable() : void
- {
- $createTablesSql = [
- 'CREATE TABLE doctrine_migration_versions (version varchar(200) NOT NULL, test varchar(255) DEFAULT NULL, PRIMARY KEY (version))',
- 'CREATE TABLE test (test varchar(255) NOT NULL)',
- ];
-
- foreach ($createTablesSql as $createTableSql) {
- $this->connection->executeQuery($createTableSql);
- }
-
- self::assertTrue($this->trackingTableStatus->isCreated());
- self::assertFalse($this->trackingTableStatus->isUpToDate());
-
- self::assertTrue($this->trackingTableManipulator->createMigrationTable());
-
- self::assertTrue($this->trackingTableStatus->isUpToDate());
-
- $schemaManager = $this->connection->getSchemaManager();
-
- $table = $schemaManager->listTableDetails('doctrine_migration_versions');
-
- self::assertTrue($table->hasColumn('version'));
- self::assertTrue($table->getColumn('version')->getNotnull());
-
- self::assertTrue($table->hasColumn('executed_at'), 'Check executedAt column was added');
- self::assertFalse($table->getColumn('executed_at')->getNotnull());
-
- self::assertTrue($table->hasColumn('test'), 'Check column not related to Doctrine was not dropped');
- self::assertTrue($schemaManager->tablesExist(['test']), 'Check table not related to Doctrine was not dropped');
- }
-
- protected function setUp() : void
- {
- $this->connection = $this->getTestConnection();
-
- $configuration = new Configuration($this->connection);
- $configuration->setMigrationsDirectory(__DIR__ . '/Stub/migration-empty-folder');
- $configuration->setMigrationsNamespace('DoctrineMigrations');
- $configuration->setMigrationsColumnLength(200);
-
- $dependencyFactory = $configuration->getDependencyFactory();
-
- $this->trackingTableManipulator = $dependencyFactory->getTrackingTableManipulator();
- $this->trackingTableStatus = $dependencyFactory->getTrackingTableStatus();
- }
-
- private function getTestConnection() : Connection
- {
- $params = [
- 'driver' => 'pdo_sqlite',
- 'memory' => true,
- 'defaultTableOptions' => [
- 'unique' => [
- new Index('unique_version', ['version'], true),
- ],
- ],
- ];
-
- return DriverManager::getConnection($params);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Functional/_files/config.yml b/tests/Doctrine/Migrations/Tests/Functional/_files/config.yml
deleted file mode 100644
index da2302a620..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/_files/config.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: "name"
-table_name: "migrations_table_name"
-migrations_namespace: "TestMigrations"
-migrations_directory: migrations
-migrations:
- migration1:
- version: '20150426000000'
- class: Doctrine\Migrations\Tests\Functional\FirstMigration
diff --git a/tests/Doctrine/Migrations/Tests/Functional/_files/config_organize_by_year_and_month.xml b/tests/Doctrine/Migrations/Tests/Functional/_files/config_organize_by_year_and_month.xml
deleted file mode 100644
index e92085e206..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/_files/config_organize_by_year_and_month.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
- some-name
- TestMigrationsVersionsOrganized
-
- migrations
- year_and_month
-
-
diff --git a/tests/Doctrine/Migrations/Tests/Functional/_files/db/.gitignore b/tests/Doctrine/Migrations/Tests/Functional/_files/db/.gitignore
deleted file mode 100644
index d6b7ef32c8..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/_files/db/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
diff --git a/tests/Doctrine/Migrations/Tests/Functional/_files/entities/Doctrine.Migrations.Tests.Functional.SampleEntity.dcm.xml b/tests/Doctrine/Migrations/Tests/Functional/_files/entities/Doctrine.Migrations.Tests.Functional.SampleEntity.dcm.xml
deleted file mode 100644
index 7e1030dcb0..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/_files/entities/Doctrine.Migrations.Tests.Functional.SampleEntity.dcm.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/tests/Doctrine/Migrations/Tests/Functional/_files/migrations/.gitignore b/tests/Doctrine/Migrations/Tests/Functional/_files/migrations/.gitignore
deleted file mode 100644
index d6b7ef32c8..0000000000
--- a/tests/Doctrine/Migrations/Tests/Functional/_files/migrations/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
diff --git a/tests/Doctrine/Migrations/Tests/Generator/ClassNameGeneratorTest.php b/tests/Doctrine/Migrations/Tests/Generator/ClassNameGeneratorTest.php
new file mode 100644
index 0000000000..2e5cd82a35
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Generator/ClassNameGeneratorTest.php
@@ -0,0 +1,18 @@
+generateClassName('Foo');
+ self::assertRegExp('/^Foo\\\\Version[0-9]{14}$/', $fqcn);
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Generator/DiffGeneratorTest.php b/tests/Doctrine/Migrations/Tests/Generator/DiffGeneratorTest.php
index 7d992ff239..851003bb19 100644
--- a/tests/Doctrine/Migrations/Tests/Generator/DiffGeneratorTest.php
+++ b/tests/Doctrine/Migrations/Tests/Generator/DiffGeneratorTest.php
@@ -12,7 +12,7 @@
use Doctrine\Migrations\Generator\DiffGenerator;
use Doctrine\Migrations\Generator\Generator;
use Doctrine\Migrations\Generator\SqlGenerator;
-use Doctrine\Migrations\Provider\SchemaProviderInterface;
+use Doctrine\Migrations\Provider\SchemaProvider;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -24,7 +24,7 @@ class DiffGeneratorTest extends TestCase
/** @var AbstractSchemaManager|MockObject */
private $schemaManager;
- /** @var SchemaProviderInterface|MockObject */
+ /** @var SchemaProvider|MockObject */
private $schemaProvider;
/** @var AbstractPlatform|MockObject */
@@ -122,7 +122,7 @@ protected function setUp() : void
{
$this->dbalConfiguration = $this->createMock(DBALConfiguration::class);
$this->schemaManager = $this->createMock(AbstractSchemaManager::class);
- $this->schemaProvider = $this->createMock(SchemaProviderInterface::class);
+ $this->schemaProvider = $this->createMock(SchemaProvider::class);
$this->platform = $this->createMock(AbstractPlatform::class);
$this->migrationGenerator = $this->createMock(Generator::class);
$this->migrationSqlGenerator = $this->createMock(SqlGenerator::class);
diff --git a/tests/Doctrine/Migrations/Tests/Generator/FileBuilderTest.php b/tests/Doctrine/Migrations/Tests/Generator/FileBuilderTest.php
index 074733777b..a07ce4f85c 100644
--- a/tests/Doctrine/Migrations/Tests/Generator/FileBuilderTest.php
+++ b/tests/Doctrine/Migrations/Tests/Generator/FileBuilderTest.php
@@ -50,17 +50,14 @@ public function testBuildMigrationFile() : void
-- Version 1
SELECT 1;
SELECT 2;
-INSERT INTO table_name (column_name, executed_at) VALUES ('1', CURRENT_TIMESTAMP);
-- Version 2
SELECT 3;
SELECT 4;
-INSERT INTO table_name (column_name, executed_at) VALUES ('2', CURRENT_TIMESTAMP);
-- Version 3
SELECT 5;
SELECT 6;
-INSERT INTO table_name (column_name, executed_at) VALUES ('3', CURRENT_TIMESTAMP);
FILE;
@@ -73,11 +70,6 @@ protected function setUp() : void
{
$this->platform = $this->createMock(AbstractPlatform::class);
- $this->migrationFileBuilder = new FileBuilder(
- $this->platform,
- 'table_name',
- 'column_name',
- 'executed_at'
- );
+ $this->migrationFileBuilder = new FileBuilder();
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Generator/GeneratorTest.php b/tests/Doctrine/Migrations/Tests/Generator/GeneratorTest.php
index b887efd0f8..efdbeda7cc 100644
--- a/tests/Doctrine/Migrations/Tests/Generator/GeneratorTest.php
+++ b/tests/Doctrine/Migrations/Tests/Generator/GeneratorTest.php
@@ -7,7 +7,6 @@
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Generator\Generator;
use InvalidArgumentException;
-use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use function class_exists;
use function file_get_contents;
@@ -18,7 +17,7 @@
final class GeneratorTest extends TestCase
{
- /** @var Configuration|MockObject */
+ /** @var Configuration */
private $configuration;
/** @var Generator */
@@ -26,22 +25,13 @@ final class GeneratorTest extends TestCase
public function testGenerateMigration() : void
{
- $this->configuration->expects(self::once())
- ->method('getMigrationsNamespace')
- ->willReturn('Test');
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsDirectory')
- ->willReturn(sys_get_temp_dir());
-
- $path = $this->migrationGenerator->generateMigration('1234', '// up', '// down');
+ $path = $this->migrationGenerator->generateMigration('Test\\Version1234', '// up', '// down');
self::assertFileExists($path);
$migrationCode = file_get_contents($path);
self::assertContains('// up', $migrationCode);
- self::assertContains('// down', $migrationCode);
include $path;
@@ -56,11 +46,9 @@ public function testCustomTemplate() : void
file_put_contents($customTemplate, 'custom template test');
- $this->configuration->expects(self::once())
- ->method('getCustomTemplate')
- ->willReturn($customTemplate);
+ $this->configuration->setCustomTemplate($customTemplate);
- $path = $this->migrationGenerator->generateMigration('1234', '// up', '// down');
+ $path = $this->migrationGenerator->generateMigration('Test\\Version1234', '// up', '// down');
self::assertFileExists($path);
@@ -69,16 +57,22 @@ public function testCustomTemplate() : void
unlink($path);
}
+ public function tesThrowsInvalidArgumentExceptionWhenNamespaceDirMissing() : void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('Path not defined for the namespace "Bar"');
+
+ $this->migrationGenerator->generateMigration('Bar\\Version1234');
+ }
+
public function testCustomTemplateThrowsInvalidArgumentExceptionWhenTemplateMissing() : void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The specified template "invalid" cannot be found or is not readable.');
- $this->configuration->expects(self::once())
- ->method('getCustomTemplate')
- ->willReturn('invalid');
+ $this->configuration->setCustomTemplate('invalid');
- $this->migrationGenerator->generateMigration('1234');
+ $this->migrationGenerator->generateMigration('Test\\Version1234');
}
public function testCustomTemplateThrowsInvalidArgumentExceptionWhenTemplateEmpty() : void
@@ -93,19 +87,17 @@ public function testCustomTemplateThrowsInvalidArgumentExceptionWhenTemplateEmpt
$customTemplate
));
- $this->configuration->expects(self::once())
- ->method('getCustomTemplate')
- ->willReturn($customTemplate);
+ $this->configuration->setCustomTemplate($customTemplate);
- $this->migrationGenerator->generateMigration('1234');
+ $this->migrationGenerator->generateMigration('Test\\Version1234');
unlink($customTemplate);
}
protected function setUp() : void
{
- $this->configuration = $this->createMock(Configuration::class);
-
+ $this->configuration = new Configuration();
+ $this->configuration->addMigrationsDirectory('Test', sys_get_temp_dir());
$this->migrationGenerator = new Generator($this->configuration);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Generator/SqlGeneratorTest.php b/tests/Doctrine/Migrations/Tests/Generator/SqlGeneratorTest.php
index fa57b3ae83..9f32db7cb7 100644
--- a/tests/Doctrine/Migrations/Tests/Generator/SqlGeneratorTest.php
+++ b/tests/Doctrine/Migrations/Tests/Generator/SqlGeneratorTest.php
@@ -7,6 +7,7 @@
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Generator\SqlGenerator;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use SqlFormatter;
@@ -14,7 +15,7 @@
final class SqlGeneratorTest extends TestCase
{
- /** @var Configuration|MockObject */
+ /** @var Configuration */
private $configuration;
/** @var AbstractPlatform|MockObject */
@@ -26,9 +27,12 @@ final class SqlGeneratorTest extends TestCase
/** @var string[] */
private $sql;
+ /** @var TableMetadataStorageConfiguration */
+ private $metadataConfig;
+
public function testGenerate() : void
{
- $this->configuration->method('isDatabasePlatformChecked')->willReturn(true);
+ $this->configuration->setCheckDatabasePlatform(true);
$expectedCode = $this->prepareGeneratedCode(
<<<'CODE'
@@ -51,7 +55,7 @@ public function testGenerate() : void
public function testGenerationWithoutCheckingDatabasePlatform() : void
{
- $this->configuration->method('isDatabasePlatformChecked')->willReturn(true);
+ $this->configuration->setCheckDatabasePlatform(true);
$expectedCode = $this->prepareGeneratedCode(
<<<'CODE'
@@ -68,7 +72,7 @@ public function testGenerationWithoutCheckingDatabasePlatform() : void
public function testGenerationWithoutCheckingDatabasePlatformWithConfiguration() : void
{
- $this->configuration->method('isDatabasePlatformChecked')->willReturn(false);
+ $this->configuration->setCheckDatabasePlatform(false);
$expectedCode = $this->prepareGeneratedCode(
<<<'CODE'
@@ -85,9 +89,11 @@ public function testGenerationWithoutCheckingDatabasePlatformWithConfiguration()
protected function setUp() : void
{
- $this->configuration = $this->createMock(Configuration::class);
+ $this->configuration = new Configuration();
$this->platform = $this->createMock(AbstractPlatform::class);
+ $this->metadataConfig = new TableMetadataStorageConfiguration();
+ $this->configuration->setMetadataStorageConfiguration($this->metadataConfig);
$this->migrationSqlGenerator = new SqlGenerator(
$this->configuration,
$this->platform
@@ -107,9 +113,7 @@ private function prepareGeneratedCode(string $expectedCode) : string
$expectedCode = sprintf($expectedCode, $formattedUpdate);
- $this->configuration->expects(self::any())
- ->method('getMigrationsTableName')
- ->willReturn('migrations_table_name');
+ $this->metadataConfig->setTableName('migrations_table_name');
return $expectedCode;
}
diff --git a/tests/Doctrine/Migrations/Tests/Helper.php b/tests/Doctrine/Migrations/Tests/Helper.php
index fde13c7678..186f5367a4 100644
--- a/tests/Doctrine/Migrations/Tests/Helper.php
+++ b/tests/Doctrine/Migrations/Tests/Helper.php
@@ -33,7 +33,7 @@ public static function deleteDir(string $path) : bool
$files = glob($path . '/*');
- if ($files !== []) {
+ if ($files !== [] && $files !== false) {
array_map($classFunction, $files);
@rmdir($path);
diff --git a/tests/Doctrine/Migrations/Tests/Metadata/AvailableMigrationListTest.php b/tests/Doctrine/Migrations/Tests/Metadata/AvailableMigrationListTest.php
new file mode 100644
index 0000000000..43b6570f34
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Metadata/AvailableMigrationListTest.php
@@ -0,0 +1,122 @@
+abstractMigration = $this->createMock(AbstractMigration::class);
+ }
+
+ public function testFirstWhenEmpty() : void
+ {
+ $this->expectException(NoMigrationsFoundWithCriteria::class);
+ $this->expectExceptionMessage('Could not find any migrations matching your criteria (first).');
+ $set = new AvailableMigrationsList([]);
+ $set->getFirst();
+ }
+
+ public function testLastWhenEmpty() : void
+ {
+ $this->expectException(NoMigrationsFoundWithCriteria::class);
+ $this->expectExceptionMessage('Could not find any migrations matching your criteria (last).');
+ $set = new AvailableMigrationsList([]);
+ $set->getLast();
+ }
+
+ public function testFirst() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $set = new AvailableMigrationsList([$m1, $m2, $m3]);
+ self::assertSame($m1, $set->getFirst());
+ self::assertSame($m2, $set->getFirst(1));
+ }
+
+ public function testLast() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $set = new AvailableMigrationsList([$m1, $m2, $m3]);
+ self::assertSame($m3, $set->getLast());
+ self::assertSame($m2, $set->getLast(-1));
+ }
+
+ public function testItems() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $set = new AvailableMigrationsList([$m1, $m2, $m3]);
+ self::assertSame([$m1, $m2, $m3], $set->getItems());
+ }
+
+ public function testCount() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $set = new AvailableMigrationsList([$m1, $m2, $m3]);
+ self::assertCount(3, $set);
+ }
+
+ public function testGetMigration() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $set = new AvailableMigrationsList([$m1, $m2, $m3]);
+ self::assertSame($m2, $set->getMigration(new Version('B')));
+ }
+
+ public function testGetMigrationThrowsExceptionIfNotExisting() : void
+ {
+ $this->expectException(MigrationNotAvailable::class);
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $set = new AvailableMigrationsList([$m1, $m2, $m3]);
+ $set->getMigration(new Version('D'));
+ }
+
+ public function testHasMigration() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $set = new AvailableMigrationsList([$m1, $m2, $m3]);
+ self::assertTrue($set->hasMigration(new Version('B')));
+ self::assertFalse($set->hasMigration(new Version('D')));
+ }
+
+ public function testAvailableMigration() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+
+ self::assertEquals(new Version('A'), $m1->getVersion());
+ self::assertSame($this->abstractMigration, $m1->getMigration());
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Metadata/ExecutedMigrationSetTest.php b/tests/Doctrine/Migrations/Tests/Metadata/ExecutedMigrationSetTest.php
new file mode 100644
index 0000000000..781013f6d1
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Metadata/ExecutedMigrationSetTest.php
@@ -0,0 +1,124 @@
+expectException(NoMigrationsFoundWithCriteria::class);
+ $this->expectExceptionMessage('Could not find any migrations matching your criteria (first).');
+ $set = new ExecutedMigrationsSet([]);
+ $set->getFirst();
+ }
+
+ public function testLastWhenEmpty() : void
+ {
+ $this->expectException(NoMigrationsFoundWithCriteria::class);
+ $this->expectExceptionMessage('Could not find any migrations matching your criteria (last).');
+ $set = new ExecutedMigrationsSet([]);
+ $set->getLast();
+ }
+
+ public function testFirst() : void
+ {
+ $m1 = new ExecutedMigration(new Version('A'));
+ $m2 = new ExecutedMigration(new Version('B'));
+ $m3 = new ExecutedMigration(new Version('C'));
+
+ $set = new ExecutedMigrationsSet([$m1, $m2, $m3]);
+ self::assertSame($m1, $set->getFirst());
+ self::assertSame($m2, $set->getFirst(1));
+ }
+
+ public function testLast() : void
+ {
+ $m1 = new ExecutedMigration(new Version('A'));
+ $m2 = new ExecutedMigration(new Version('B'));
+ $m3 = new ExecutedMigration(new Version('C'));
+
+ $set = new ExecutedMigrationsSet([$m1, $m2, $m3]);
+ self::assertSame($m3, $set->getLast());
+ self::assertSame($m2, $set->getLast(-1));
+ }
+
+ public function testItems() : void
+ {
+ $m1 = new ExecutedMigration(new Version('A'));
+ $m2 = new ExecutedMigration(new Version('B'));
+ $m3 = new ExecutedMigration(new Version('C'));
+
+ $set = new ExecutedMigrationsSet([$m1, $m2, $m3]);
+ self::assertSame([$m1, $m2, $m3], $set->getItems());
+ }
+
+ public function testCount() : void
+ {
+ $m1 = new ExecutedMigration(new Version('A'));
+ $m2 = new ExecutedMigration(new Version('B'));
+ $m3 = new ExecutedMigration(new Version('C'));
+
+ $set = new ExecutedMigrationsSet([$m1, $m2, $m3]);
+ self::assertCount(3, $set);
+ }
+
+ public function testGetMigration() : void
+ {
+ $m1 = new ExecutedMigration(new Version('A'));
+ $m2 = new ExecutedMigration(new Version('B'));
+ $m3 = new ExecutedMigration(new Version('C'));
+
+ $set = new ExecutedMigrationsSet([$m1, $m2, $m3]);
+ self::assertSame($m2, $set->getMigration(new Version('B')));
+ }
+
+ public function testGetMigrationThrowsExceptionIfNotExisting() : void
+ {
+ $this->expectException(MigrationNotExecuted::class);
+ $m1 = new ExecutedMigration(new Version('A'));
+ $m2 = new ExecutedMigration(new Version('B'));
+ $m3 = new ExecutedMigration(new Version('C'));
+
+ $set = new ExecutedMigrationsSet([$m1, $m2, $m3]);
+ $set->getMigration(new Version('D'));
+ }
+
+ public function testHasMigration() : void
+ {
+ $m1 = new ExecutedMigration(new Version('A'));
+ $m2 = new ExecutedMigration(new Version('B'));
+ $m3 = new ExecutedMigration(new Version('C'));
+
+ $set = new ExecutedMigrationsSet([$m1, $m2, $m3]);
+ self::assertTrue($set->hasMigration(new Version('B')));
+ self::assertFalse($set->hasMigration(new Version('D')));
+ }
+
+ public function testExecutedMigration() : void
+ {
+ $m1 = new ExecutedMigration(new Version('A'));
+
+ self::assertEquals(new Version('A'), $m1->getVersion());
+ self::assertNull($m1->getExecutedAt());
+ self::assertNull($m1->getExecutionTime());
+ }
+
+ public function testExecutedMigrationWithTiming() : void
+ {
+ $date = new DateTimeImmutable();
+ $m1 = new ExecutedMigration(new Version('A'), $date, 123);
+
+ self::assertSame($date, $m1->getExecutedAt());
+ self::assertSame(123, $m1->getExecutionTime());
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Metadata/MigrationPlanListTest.php b/tests/Doctrine/Migrations/Tests/Metadata/MigrationPlanListTest.php
new file mode 100644
index 0000000000..8e19ca8b7e
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Metadata/MigrationPlanListTest.php
@@ -0,0 +1,108 @@
+abstractMigration = $this->createMock(AbstractMigration::class);
+ $this->m1 = new MigrationPlan(new Version('A'), $this->abstractMigration, Direction::UP);
+ $this->m2 = new MigrationPlan(new Version('B'), $this->abstractMigration, Direction::UP);
+ $this->m3 = new MigrationPlan(new Version('C'), $this->abstractMigration, Direction::UP);
+
+ $this->set = new MigrationPlanList([$this->m1, $this->m2, $this->m3], Direction::UP);
+ }
+
+ public function testFirstWhenEmpty() : void
+ {
+ $this->expectException(NoMigrationsFoundWithCriteria::class);
+ $this->expectExceptionMessage('Could not find any migrations matching your criteria (first).');
+ $set = new MigrationPlanList([], Direction::UP);
+ $set->getFirst();
+ }
+
+ public function testLastWhenEmpty() : void
+ {
+ $this->expectException(NoMigrationsFoundWithCriteria::class);
+ $this->expectExceptionMessage('Could not find any migrations matching your criteria (last).');
+ $set = new MigrationPlanList([], Direction::UP);
+ $set->getLast();
+ }
+
+ public function testFirst() : void
+ {
+ self::assertSame($this->m1, $this->set->getFirst());
+ }
+
+ public function testLast() : void
+ {
+ self::assertSame($this->m3, $this->set->getLast());
+ }
+
+ public function testItems() : void
+ {
+ self::assertSame([$this->m1, $this->m2, $this->m3], $this->set->getItems());
+ }
+
+ public function testCount() : void
+ {
+ self::assertCount(3, $this->set);
+ }
+
+ public function testDirection() : void
+ {
+ self::assertSame(Direction::UP, $this->set->getDirection());
+ self::assertSame(Direction::UP, $this->set->getFirst()->getDirection());
+ }
+
+ public function testPlan() : void
+ {
+ self::assertSame(Direction::UP, $this->m1->getDirection());
+ self::assertSame($this->abstractMigration, $this->m1->getMigration());
+ self::assertEquals(new Version('A'), $this->m1->getVersion());
+ self::assertNull($this->m1->getResult());
+ }
+
+ public function testPlanResultCanBeSetOnlyOnce() : void
+ {
+ $this->expectException(PlanAlreadyExecuted::class);
+ $this->expectExceptionMessage('This plan was already marked as executed.');
+
+ $result = new ExecutionResult(new Version('A'), Direction::UP);
+ $this->m1->markAsExecuted($result);
+ $this->m1->markAsExecuted($result);
+ }
+
+ public function testPlanResult() : void
+ {
+ $result = new ExecutionResult(new Version('A'), Direction::UP);
+ $this->m1->markAsExecuted($result);
+
+ self::assertSame($result, $this->m1->getResult());
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Metadata/Storage/TableMetadataStorageConfigurationTest.php b/tests/Doctrine/Migrations/Tests/Metadata/Storage/TableMetadataStorageConfigurationTest.php
new file mode 100644
index 0000000000..16ab2fe5cb
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Metadata/Storage/TableMetadataStorageConfigurationTest.php
@@ -0,0 +1,39 @@
+getTableName());
+ self::assertSame('version', $config->getVersionColumnName());
+ self::assertSame(1024, $config->getVersionColumnLength());
+ self::assertSame('executed_at', $config->getExecutedAtColumnName());
+ self::assertSame('execution_time', $config->getExecutionTimeColumnName());
+ }
+
+ public function testConfigs() : void
+ {
+ $config = new TableMetadataStorageConfiguration();
+
+ $config->setTableName('a');
+ $config->setVersionColumnName('b');
+ $config->setVersionColumnLength(1);
+ $config->setExecutedAtColumnName('c');
+ $config->setExecutionTimeColumnName('d');
+
+ self::assertSame('a', $config->getTableName());
+ self::assertSame('b', $config->getVersionColumnName());
+ self::assertSame(1, $config->getVersionColumnLength());
+ self::assertSame('c', $config->getExecutedAtColumnName());
+ self::assertSame('d', $config->getExecutionTimeColumnName());
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Metadata/Storage/TableMetadataStorageTest.php b/tests/Doctrine/Migrations/Tests/Metadata/Storage/TableMetadataStorageTest.php
new file mode 100644
index 0000000000..6b64da240a
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Metadata/Storage/TableMetadataStorageTest.php
@@ -0,0 +1,175 @@
+ 'pdo_sqlite', 'memory' => true];
+
+ return DriverManager::getConnection($params);
+ }
+
+ public function setUp() : void
+ {
+ $this->connection = $this->getSqliteConnection();
+ $this->schemaManager = $this->connection->getSchemaManager();
+
+ $this->config = new TableMetadataStorageConfiguration();
+ $this->storage = new TableMetadataStorage($this->connection, $this->config);
+ }
+
+ public function testTableCreatedOnRead() : void
+ {
+ $this->storage->getExecutedMigrations();
+ self::assertTrue($this->schemaManager->tablesExist([$this->config->getTableName()]));
+ }
+
+ public function testTableStructure() : void
+ {
+ $config = new TableMetadataStorageConfiguration();
+ $config->setTableName('a');
+ $config->setVersionColumnName('b');
+ $config->setVersionColumnLength(199);
+ $config->setExecutedAtColumnName('c');
+ $config->setExecutionTimeColumnName('d');
+
+ $storage = new TableMetadataStorage($this->connection, $config);
+ // trigger table creation
+ $storage->getExecutedMigrations();
+
+ $table = $this->schemaManager->listTableDetails($config->getTableName());
+
+ self::assertInstanceOf(StringType::class, $table->getColumn('b')->getType());
+ self::assertInstanceOf(DateTimeType::class, $table->getColumn('c')->getType());
+ self::assertInstanceOf(IntegerType::class, $table->getColumn('d')->getType());
+ }
+
+ public function testComplete() : void
+ {
+ $result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-05 10:30:21'));
+ $result->setTime(31);
+ $this->storage->complete($result);
+
+ $sql = sprintf(
+ 'SELECT * FROM %s',
+ $this->connection->getDatabasePlatform()->quoteIdentifier($this->config->getTableName())
+ );
+ $rows = $this->connection->fetchAll($sql);
+ self::assertSame([
+ 0 =>
+ [
+ 'version' => '1230',
+ 'executed_at' => '2010-01-05 10:30:21',
+ 'execution_time' => '31',
+ ],
+ ], $rows);
+ }
+
+ public function testRead() : void
+ {
+ $date = new DateTimeImmutable('2010-01-05 10:30:21');
+ $result1 = new ExecutionResult(new Version('1230'), Direction::UP, $date);
+ $result1->setTime(31);
+ $this->storage->complete($result1);
+
+ $result2 = new ExecutionResult(new Version('1231'), Direction::UP);
+ $this->storage->complete($result2);
+
+ $executedMigrations = $this->storage->getExecutedMigrations();
+
+ self::assertTrue($executedMigrations->hasMigration(new Version('1230')));
+ self::assertTrue($executedMigrations->hasMigration(new Version('1231')));
+ self::assertFalse($executedMigrations->hasMigration(new Version('1232')));
+
+ $m1 = $executedMigrations->getMigration($result1->getVersion());
+
+ self::assertEquals($result1->getVersion(), $m1->getVersion());
+ self::assertNotNull($m1->getExecutedAt());
+ self::assertSame($date->format(DateTime::ISO8601), $m1->getExecutedAt()->format(DateTime::ISO8601));
+ self::assertSame(31, $m1->getExecutionTime());
+
+ $m2 = $executedMigrations->getMigration($result2->getVersion());
+
+ self::assertEquals($result2->getVersion(), $m2->getVersion());
+ self::assertNull($m2->getExecutedAt());
+ self::assertNull($m2->getExecutionTime());
+ }
+
+ public function testExecutedMigrationWithTiming() : void
+ {
+ $date = new DateTimeImmutable();
+ $m1 = new ExecutedMigration(new Version('A'), $date, 123);
+
+ self::assertSame($date, $m1->getExecutedAt());
+ self::assertSame(123, $m1->getExecutionTime());
+ }
+
+ public function testCompleteDownRemovesTheRow() : void
+ {
+ $result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-05 10:30:21'));
+ $result->setTime(31);
+ $this->storage->complete($result);
+
+ $sql = sprintf(
+ 'SELECT * FROM %s',
+ $this->connection->getDatabasePlatform()->quoteIdentifier($this->config->getTableName())
+ );
+ self::assertCount(1, $this->connection->fetchAll($sql));
+
+ $result = new ExecutionResult(new Version('1230'), Direction::DOWN, new DateTimeImmutable('2010-01-05 10:30:21'));
+ $result->setTime(31);
+ $this->storage->complete($result);
+
+ self::assertCount(0, $this->connection->fetchAll($sql));
+ }
+
+ public function testReset() : void
+ {
+ $result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-05 10:30:21'));
+ $result->setTime(31);
+ $this->storage->complete($result);
+
+ $sql = sprintf(
+ 'SELECT * FROM %s',
+ $this->connection->getDatabasePlatform()->quoteIdentifier($this->config->getTableName())
+ );
+ self::assertCount(1, $this->connection->fetchAll($sql));
+
+ $this->storage->reset();
+
+ self::assertCount(0, $this->connection->fetchAll($sql));
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/MigrationPlanCalculatorTest.php b/tests/Doctrine/Migrations/Tests/MigrationPlanCalculatorTest.php
index 4257f8e594..d6b8da49ca 100644
--- a/tests/Doctrine/Migrations/Tests/MigrationPlanCalculatorTest.php
+++ b/tests/Doctrine/Migrations/Tests/MigrationPlanCalculatorTest.php
@@ -4,127 +4,228 @@
namespace Doctrine\Migrations\Tests;
+use Doctrine\Migrations\AbstractMigration;
+use Doctrine\Migrations\Exception\NoMigrationsToExecute;
+use Doctrine\Migrations\Metadata\AvailableMigration;
+use Doctrine\Migrations\Metadata\AvailableMigrationsList;
+use Doctrine\Migrations\Metadata\ExecutedMigration;
+use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\MigrationPlanCalculator;
use Doctrine\Migrations\MigrationRepository;
use Doctrine\Migrations\Version\Direction;
use Doctrine\Migrations\Version\Version;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
+use function count;
final class MigrationPlanCalculatorTest extends TestCase
{
- /** @var MigrationRepository|MockObject */
- private $migrationRepository;
-
/** @var MigrationPlanCalculator */
private $migrationPlanCalculator;
- public function testGetMigrationsToExecuteUp() : void
+ /** @var MockObject|MigrationRepository */
+ private $migrationRepository;
+
+ /** @var MockObject|MetadataStorage */
+ private $metadataStorage;
+
+ /** @var MockObject|AbstractMigration */
+ private $abstractMigration;
+
+ protected function setUp() : void
+ {
+ $this->abstractMigration = $this->createMock(AbstractMigration::class);
+
+ $this->migrationRepository = $this->createMock(MigrationRepository::class);
+ $this->metadataStorage = $this->createMock(MetadataStorage::class);
+ $this->migrationPlanCalculator = new MigrationPlanCalculator($this->migrationRepository, $this->metadataStorage);
+ }
+
+ public function testPlanForExactVersionWhenNoMigrations() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $migrationList = new AvailableMigrationsList([$m1, $m2, $m3]);
+
+ $this->migrationRepository
+ ->expects(self::any())
+ ->method('getMigration')
+ ->willReturnCallback(static function (Version $version) use ($migrationList) {
+ return $migrationList->getMigration($version);
+ });
+
+ $plan = $this->migrationPlanCalculator->getPlanForExactVersion(new Version('C'), Direction::UP);
+
+ self::assertCount(1, $plan);
+ self::assertSame(Direction::UP, $plan->getDirection());
+ self::assertSame(Direction::UP, $plan->getFirst()->getDirection());
+ self::assertEquals(new Version('C'), $plan->getFirst()->getVersion());
+ }
+
+ /**
+ * @param string[] $expectedPlan
+ *
+ * @dataProvider getPlanUpWhenNoMigrations
+ */
+ public function testPlanWhenNoMigrations(?string $to, array $expectedPlan, string $direction) : void
{
- $version1 = $this->createMock(Version::class);
- $version1->expects(self::any())
- ->method('getVersion')
- ->willReturn('01');
-
- $version2 = $this->createMock(Version::class);
- $version2->expects(self::any())
- ->method('getVersion')
- ->willReturn('02');
-
- $version3 = $this->createMock(Version::class);
- $version3->expects(self::any())
- ->method('getVersion')
- ->willReturn('03');
-
- $version4 = $this->createMock(Version::class);
- $version4->expects(self::any())
- ->method('getVersion')
- ->willReturn('04');
-
- $this->migrationRepository->expects(self::once())
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $migrationList = new AvailableMigrationsList([$m1, $m2, $m3]);
+ $this->migrationRepository
+ ->expects(self::any())
->method('getMigrations')
- ->willReturn([
- '01' => $version1,
- '02' => $version2,
- '03' => $version3,
- '04' => $version4,
- ]);
-
- $this->migrationRepository->expects(self::once())
- ->method('getMigratedVersions')
- ->willReturn([
- '02',
- '03',
- ]);
-
- $expected = [
- '01' => $version1,
- '04' => $version4,
+ ->willReturn($migrationList);
+
+ $this->metadataStorage
+ ->expects(self::atLeastOnce())
+ ->method('getExecutedMigrations')
+ ->willReturn(new ExecutedMigrationsSet([]));
+
+ $plan = $this->migrationPlanCalculator->getPlanUntilVersion($to !== null ? new Version($to) : null);
+
+ self::assertSame($direction, $plan->getDirection());
+ self::assertCount(count($expectedPlan), $plan);
+
+ foreach ($expectedPlan as $itemN => $version) {
+ self::assertSame($direction, $plan->getItems()[$itemN]->getDirection());
+ self::assertEquals(new Version($version), $plan->getItems()[$itemN]->getVersion());
+ }
+ }
+
+ /**
+ * @return mixed[]
+ */
+ public function getPlanUpWhenNoMigrations() : array
+ {
+ return [
+ ['A', ['A'], Direction::UP],
+ ['B', ['A', 'B'], Direction::UP],
+ ['C', ['A', 'B', 'C'], Direction::UP],
+ ['C', ['A', 'B', 'C'], Direction::UP],
+ [null, ['A', 'B', 'C'], Direction::UP],
];
+ }
+
+ /**
+ * @param string[] $expectedPlan
+ *
+ * @dataProvider getPlanUpWhenMigrations
+ */
+ public function testPlanWhenMigrations(?string $to, array $expectedPlan, ?string $direction) : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $e1 = new ExecutedMigration(new Version('A'));
+ $e2 = new ExecutedMigration(new Version('B'));
+
+ $migrationList = new AvailableMigrationsList([$m1, $m2, $m3]);
+ $this->migrationRepository
+ ->expects(self::any())
+ ->method('getMigrations')
+ ->willReturn($migrationList);
+
+ $this->metadataStorage
+ ->expects(self::atLeastOnce())
+ ->method('getExecutedMigrations')
+ ->willReturn(new ExecutedMigrationsSet([$e1, $e2]));
+
+ $plan = $this->migrationPlanCalculator->getPlanUntilVersion($to !== null ? new Version($to) : null);
+
+ self::assertCount(count($expectedPlan), $plan);
- $migrationsToExecute = $this->migrationPlanCalculator->getMigrationsToExecute(
- Direction::UP,
- '04'
- );
+ self::assertSame($direction, $plan->getDirection());
- self::assertSame($expected, $migrationsToExecute);
+ foreach ($expectedPlan as $itemN => $version) {
+ self::assertSame($direction, $plan->getItems()[$itemN]->getDirection());
+ self::assertEquals(new Version($version), $plan->getItems()[$itemN]->getVersion());
+ }
}
- public function testGetMigrationsToExecuteDown() : void
+ public function testNoAvailableMigrations() : void
{
- $version1 = $this->createMock(Version::class);
- $version1->expects(self::any())
- ->method('getVersion')
- ->willReturn('01');
-
- $version2 = $this->createMock(Version::class);
- $version2->expects(self::any())
- ->method('getVersion')
- ->willReturn('02');
-
- $version3 = $this->createMock(Version::class);
- $version3->expects(self::any())
- ->method('getVersion')
- ->willReturn('03');
-
- $version4 = $this->createMock(Version::class);
- $version4->expects(self::any())
- ->method('getVersion')
- ->willReturn('04');
-
- $this->migrationRepository->expects(self::once())
+ $this->expectException(NoMigrationsToExecute::class);
+ $e1 = new ExecutedMigration(new Version('A'));
+ $e2 = new ExecutedMigration(new Version('B'));
+
+ $migrationList = new AvailableMigrationsList([]);
+ $this->migrationRepository
+ ->expects(self::any())
->method('getMigrations')
- ->willReturn([
- '01' => $version1,
- '02' => $version2,
- '03' => $version3,
- '04' => $version4,
- ]);
-
- $this->migrationRepository->expects(self::once())
- ->method('getMigratedVersions')
- ->willReturn([
- '02',
- '03',
- ]);
-
- $expected = [
- '03' => $version3,
- '02' => $version2,
- ];
+ ->willReturn($migrationList);
- $migrationsToExecute = $this->migrationPlanCalculator->getMigrationsToExecute(
- Direction::DOWN,
- '01'
- );
+ $this->metadataStorage
+ ->expects(self::atLeastOnce())
+ ->method('getExecutedMigrations')
+ ->willReturn(new ExecutedMigrationsSet([$e1, $e2]));
- self::assertSame($expected, $migrationsToExecute);
+ $this->migrationPlanCalculator->getPlanUntilVersion();
}
- protected function setUp() : void
+ public function testGetNewMigrations() : void
+ {
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
+ $m3 = new AvailableMigration(new Version('C'), $this->abstractMigration);
+
+ $e1 = new ExecutedMigration(new Version('A'));
+
+ $this->migrationRepository
+ ->expects(self::any())
+ ->method('getMigrations')
+ ->willReturn(new AvailableMigrationsList([$m1, $m2, $m3]));
+
+ $this->metadataStorage
+ ->expects(self::atLeastOnce())
+ ->method('getExecutedMigrations')
+ ->willReturn(new ExecutedMigrationsSet([$e1]));
+
+ $newSet = $this->migrationPlanCalculator->getNewMigrations();
+
+ self::assertSame([$m2, $m3], $newSet->getItems());
+ }
+
+ public function testGetExecutedUnavailableMigrations() : void
{
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
+ $a1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+
+ $e1 = new ExecutedMigration(new Version('A'));
+ $e2 = new ExecutedMigration(new Version('B'));
+ $e3 = new ExecutedMigration(new Version('C'));
+
+ $this->migrationRepository
+ ->expects(self::any())
+ ->method('getMigrations')
+ ->willReturn(new AvailableMigrationsList([$a1]));
+
+ $this->metadataStorage
+ ->expects(self::atLeastOnce())
+ ->method('getExecutedMigrations')
+ ->willReturn(new ExecutedMigrationsSet([$e1, $e2, $e3]));
- $this->migrationPlanCalculator = new MigrationPlanCalculator($this->migrationRepository);
+ $newSet = $this->migrationPlanCalculator->getExecutedUnavailableMigrations();
+
+ self::assertSame([$e2, $e3], $newSet->getItems());
+ }
+
+ /**
+ * @return mixed[]
+ */
+ public function getPlanUpWhenMigrations() : array
+ {
+ return [
+ ['0', ['B', 'A'], Direction::DOWN],
+ ['A', ['B'], Direction::DOWN],
+ ['B', [], Direction::UP],
+ ['C', ['C'], Direction::UP],
+ [null, ['C'], Direction::UP],
+ ];
}
}
diff --git a/tests/Doctrine/Migrations/Tests/MigrationRepository/MigrationRepositoryTest.php b/tests/Doctrine/Migrations/Tests/MigrationRepository/MigrationRepositoryTest.php
new file mode 100644
index 0000000000..3b31ae44b3
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/MigrationRepository/MigrationRepositoryTest.php
@@ -0,0 +1,163 @@
+migrationRepository->hasMigration('non_existent'));
+ }
+
+ public function testGetNonExistentMigration() : void
+ {
+ $this->expectException(MigrationClassNotFound::class);
+
+ $this->migrationRepository->getMigration(new Version('non_existent'));
+ }
+
+ public function testGetOneMigration() : void
+ {
+ $migration = $this->migrationRepository->getMigration(new Version(A::class));
+
+ self::assertSame(A::class, (string) $migration->getVersion());
+ self::assertInstanceOf(A::class, $migration->getMigration());
+ }
+
+ public function testLoadMigrationClassesProvidedViaConstructor() : void
+ {
+ $migrationRepository = new MigrationRepository(
+ [A::class],
+ [],
+ new RecursiveRegexFinder('#.*\\.php$#i'),
+ $this->versionFactory
+ );
+
+ $migrations = $migrationRepository->getMigrations();
+
+ self::assertCount(1, $migrations);
+ self::assertInstanceOf(A::class, $migrations->getMigration(new Version(A::class))->getMigration());
+ }
+
+ public function testNoMigrationsInFolder() : void
+ {
+ $migrationRepository = new MigrationRepository(
+ [],
+ [
+ 'Doctrine\Migrations\Tests\MigrationRepository\Migrations' => __DIR__ . '/NoMigrations',
+ ],
+ new RecursiveRegexFinder('#.*\\.php$#i'),
+ $this->versionFactory
+ );
+
+ $migrations = $migrationRepository->getMigrations();
+
+ self::assertCount(0, $migrations);
+ }
+
+ public function testCustomMigrationSorting() : void
+ {
+ $migrationRepository = new MigrationRepository(
+ [],
+ [
+ 'Doctrine\Migrations\Tests\MigrationRepository\Migrations' => __DIR__ . '/Migrations',
+ ],
+ new RecursiveRegexFinder('#.*\\.php$#i'),
+ $this->versionFactory,
+ static function (AvailableMigration $m1, AvailableMigration $m2) {
+ return strcmp((string) $m1->getVersion(), (string) $m2->getVersion())*-1;
+ }
+ );
+
+ $migrations = $migrationRepository->getMigrations();
+
+ self::assertCount(3, $migrations);
+
+ // reverse order
+ self::assertSame(A::class, (string) $migrations->getItems()[2]->getVersion());
+ self::assertSame(B::class, (string) $migrations->getItems()[1]->getVersion());
+ self::assertSame(C::class, (string) $migrations->getItems()[0]->getVersion());
+ }
+
+ public function testLoadMigrationInstance() : void
+ {
+ $this->migrationRepository->registerMigrationInstance(new Version('Z'), $this->createMock(AbstractMigration::class));
+
+ $migrations = $this->migrationRepository->getMigrations();
+
+ self::assertCount(4, $migrations);
+ self::assertSame('Z', (string) $migrations->getItems()[3]->getVersion());
+ }
+
+ public function testDuplicateLoadMigrationInstance() : void
+ {
+ $this->expectException(DuplicateMigrationVersion::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('Z'), $this->createMock(AbstractMigration::class));
+ $this->migrationRepository->registerMigrationInstance(new Version('Z'), $this->createMock(AbstractMigration::class));
+ }
+
+ public function testFindMigrations() : void
+ {
+ $this->versionFactory
+ ->expects(self::exactly(3))
+ ->method('createVersion')
+ ->willReturnCallback(function ($class) {
+ return $this->createMock($class);
+ });
+
+ $migrations = $this->migrationRepository->getMigrations();
+
+ self::assertCount(3, $migrations);
+
+ self::assertSame(A::class, (string) $migrations->getItems()[0]->getVersion());
+ self::assertSame(B::class, (string) $migrations->getItems()[1]->getVersion());
+ self::assertSame(C::class, (string) $migrations->getItems()[2]->getVersion());
+
+ self::assertInstanceOf(A::class, $migrations->getItems()[0]->getMigration());
+ self::assertInstanceOf(B::class, $migrations->getItems()[1]->getMigration());
+ self::assertInstanceOf(C::class, $migrations->getItems()[2]->getMigration());
+ }
+
+ protected function setUp() : void
+ {
+ $this->versionFactory = $this->createMock(MigrationFactory::class);
+ $this->versionFactory
+ ->expects(self::any())
+ ->method('createVersion')
+ ->willReturnCallback(function ($class) {
+ return $this->createMock($class);
+ });
+
+ $this->migrationRepository = new MigrationRepository(
+ [],
+ [
+ 'Doctrine\Migrations\Tests\MigrationRepository\Migrations' => __DIR__ . '/Migrations',
+ ],
+ new RecursiveRegexFinder('#.*\\.php$#i'),
+ $this->versionFactory
+ );
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Version1Test.php b/tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/A/A.php
similarity index 69%
rename from tests/Doctrine/Migrations/Tests/Stub/Version1Test.php
rename to tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/A/A.php
index 3a83e0cfef..df0466d0bb 100644
--- a/tests/Doctrine/Migrations/Tests/Stub/Version1Test.php
+++ b/tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/A/A.php
@@ -2,18 +2,18 @@
declare(strict_types=1);
-namespace Doctrine\Migrations\Tests\Stub;
+namespace Doctrine\Migrations\Tests\MigrationRepository\Migrations\A;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-class Version1Test extends AbstractMigration
+class A extends AbstractMigration
{
- public function down(Schema $schema) : void
+ public function up(Schema $schema) : void
{
}
- public function up(Schema $schema) : void
+ public function down(Schema $schema) : void
{
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Version2Test.php b/tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/A/B.php
similarity index 69%
rename from tests/Doctrine/Migrations/Tests/Stub/Version2Test.php
rename to tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/A/B.php
index ec9d388c16..ce4eeb015c 100644
--- a/tests/Doctrine/Migrations/Tests/Stub/Version2Test.php
+++ b/tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/A/B.php
@@ -2,18 +2,18 @@
declare(strict_types=1);
-namespace Doctrine\Migrations\Tests\Stub;
+namespace Doctrine\Migrations\Tests\MigrationRepository\Migrations\A;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-class Version2Test extends AbstractMigration
+class B extends AbstractMigration
{
- public function down(Schema $schema) : void
+ public function up(Schema $schema) : void
{
}
- public function up(Schema $schema) : void
+ public function down(Schema $schema) : void
{
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Version3Test.php b/tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/B/C.php
similarity index 69%
rename from tests/Doctrine/Migrations/Tests/Stub/Version3Test.php
rename to tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/B/C.php
index 7c4a1c3175..6a3ef6b858 100644
--- a/tests/Doctrine/Migrations/Tests/Stub/Version3Test.php
+++ b/tests/Doctrine/Migrations/Tests/MigrationRepository/Migrations/B/C.php
@@ -2,18 +2,18 @@
declare(strict_types=1);
-namespace Doctrine\Migrations\Tests\Stub;
+namespace Doctrine\Migrations\Tests\MigrationRepository\Migrations\B;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-class Version3Test extends AbstractMigration
+class C extends AbstractMigration
{
- public function down(Schema $schema) : void
+ public function up(Schema $schema) : void
{
}
- public function up(Schema $schema) : void
+ public function down(Schema $schema) : void
{
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/migration-empty-folder/.gitkeep b/tests/Doctrine/Migrations/Tests/MigrationRepository/NoMigrations/.gitkeep
similarity index 100%
rename from tests/Doctrine/Migrations/Tests/Stub/migration-empty-folder/.gitkeep
rename to tests/Doctrine/Migrations/Tests/MigrationRepository/NoMigrations/.gitkeep
diff --git a/tests/Doctrine/Migrations/Tests/MigrationRepositoryTest.php b/tests/Doctrine/Migrations/Tests/MigrationRepositoryTest.php
deleted file mode 100644
index 4ab5ea09a6..0000000000
--- a/tests/Doctrine/Migrations/Tests/MigrationRepositoryTest.php
+++ /dev/null
@@ -1,144 +0,0 @@
-migrationRepository->getDeltaVersion('00'));
- self::assertNull($this->migrationRepository->getDeltaVersion('01'));
- }
-
- public function testGetVersions() : void
- {
- $version1 = $this->createMock(Version::class);
- $version1->expects(self::once())
- ->method('getVersion')
- ->willReturn('01');
-
- $version2 = $this->createMock(Version::class);
- $version2->expects(self::once())
- ->method('getVersion')
- ->willReturn('02');
-
- $versions = [
- '01' => $version1,
- '02' => $version2,
- ];
-
- $this->migrationRepository->addVersions($versions);
-
- self::assertSame($versions, $this->migrationRepository->getVersions());
-
- $this->migrationRepository->clearVersions();
-
- self::assertEmpty($this->migrationRepository->getVersions());
- }
-
- public function testGetVersionData() : void
- {
- $version = $this->createMock(Version::class);
-
- $this->configuration->expects(self::once())
- ->method('connect');
-
- $this->configuration->expects(self::once())
- ->method('createMigrationTable');
-
- $this->configuration->expects(self::exactly(2))
- ->method('getQuotedMigrationsColumnName')
- ->willReturn('version');
-
- $this->configuration->expects(self::once())
- ->method('getQuotedMigrationsExecutedAtColumnName')
- ->willReturn('executed_at');
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsTableName')
- ->willReturn('versions');
-
- $versionData = [
- 'version' => '1234',
- 'executed_at' => '2018-05-16 11:14:40',
- ];
-
- $this->connection->expects(self::once())
- ->method('fetchAssoc')
- ->with('SELECT version, executed_at FROM versions WHERE version = ?')
- ->willReturn($versionData);
-
- self::assertSame($versionData, $this->migrationRepository->getVersionData($version));
- }
-
- public function testRegisterMigrationWithNonExistentClassCausesError() : void
- {
- $this->expectException(MigrationClassNotFound::class);
-
- $this->migrationRepository->registerMigration('123', DoesNotExistAtAll::class);
- }
-
- public function testRemoveMigrationVersionFromDatabase() : void
- {
- $migrationsTableName = 'migration_versions';
- $migrationsColumnName = 'version';
- $version = '123';
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsTableName')
- ->willReturn($migrationsTableName);
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsColumnName')
- ->willReturn($migrationsColumnName);
-
- $this->connection->expects(self::once())
- ->method('delete')
- ->with($migrationsTableName, [$migrationsColumnName => $version])
- ->willReturn(1);
-
- $this->migrationRepository->removeMigrationVersionFromDatabase($version);
- }
-
- protected function setUp() : void
- {
- $this->configuration = $this->createMock(Configuration::class);
- $this->connection = $this->createMock(Connection::class);
- $this->migrationFinder = $this->createMock(MigrationFinder::class);
- $this->versionFactory = $this->createMock(Factory::class);
-
- $this->migrationRepository = new MigrationRepository(
- $this->configuration,
- $this->connection,
- $this->migrationFinder,
- $this->versionFactory
- );
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/MigrationTestCase.php b/tests/Doctrine/Migrations/Tests/MigrationTestCase.php
index 824b8a798d..fb7ee328bd 100644
--- a/tests/Doctrine/Migrations/Tests/MigrationTestCase.php
+++ b/tests/Doctrine/Migrations/Tests/MigrationTestCase.php
@@ -6,34 +6,11 @@
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
-use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Migrator;
-use Doctrine\Migrations\OutputWriter;
-use Doctrine\Migrations\Stopwatch;
-use Exception;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\Console\Output\StreamOutput;
-use Symfony\Component\Stopwatch\Stopwatch as SymfonyStopwatch;
-use function assert;
-use function fopen;
-use function fwrite;
-use function glob;
-use function is_dir;
-use function is_file;
-use function is_resource;
-use function mkdir;
-use function realpath;
-use function rewind;
-use function stream_get_contents;
+use function implode;
abstract class MigrationTestCase extends TestCase
{
- /** @var OutputWriter */
- private $outputWriter;
-
- /** @var StreamOutput */
- protected $output;
-
public function getSqliteConnection() : Connection
{
$params = ['driver' => 'pdo_sqlite', 'memory' => true];
@@ -41,102 +18,8 @@ public function getSqliteConnection() : Connection
return DriverManager::getConnection($params);
}
- public function getSqliteConfiguration() : Configuration
- {
- $config = new Configuration($this->getSqliteConnection());
- $config->setMigrationsDirectory(__DIR__ . '/Stub/migration-empty-folder');
- $config->setMigrationsNamespace('DoctrineMigrations');
-
- return $config;
- }
-
- public function getOutputStream() : StreamOutput
- {
- $stream = fopen('php://memory', 'r+', false);
-
- assert(is_resource($stream));
-
- return new StreamOutput($stream);
- }
-
- public function getOutputStreamContent(StreamOutput $streamOutput) : string
- {
- $stream = $streamOutput->getStream();
- rewind($stream);
-
- return stream_get_contents($stream);
- }
-
- /** @return resource */
- public function getInputStream(string $input)
- {
- $stream = fopen('php://memory', 'r+', false);
-
- assert(is_resource($stream));
-
- fwrite($stream, $input);
- rewind($stream);
-
- return $stream;
- }
-
- protected function getOutputWriter() : OutputWriter
- {
- if ($this->outputWriter === null) {
- $this->output = $this->getOutputStream();
- $output = $this->output;
- $this->outputWriter = new OutputWriter(static function ($message) use ($output) {
- return $output->writeln($message);
- });
- }
-
- return $this->outputWriter;
- }
-
- /** @throws Exception */
- protected function createTempDirForMigrations(string $path) : void
+ public function getLogOutput(TestLogger $logger) : string
{
- if (! mkdir($path)) {
- throw new Exception('fail to create a temporary folder for the tests at ' . $path);
- }
- }
-
- /** @return string[] */
- protected function getSqlFilesList(string $path) : array
- {
- if (is_dir($path)) {
- return glob(realpath($path) . '/*.sql');
- }
-
- if (is_file($path)) {
- return [$path];
- }
-
- return [];
- }
-
- protected function createTestMigrator(Configuration $config) : Migrator
- {
- $dependencyFactory = $config->getDependencyFactory();
- $migrationRepository = $dependencyFactory->getMigrationRepository();
- $outputWriter = $dependencyFactory->getOutputWriter();
- $symfonyStopwatch = new SymfonyStopwatch();
- $stopwatch = new Stopwatch($symfonyStopwatch);
-
- return new Migrator($config, $migrationRepository, $outputWriter, $stopwatch);
- }
-
- /**
- * @return mixed[]
- */
- protected function getMigratorConstructorArgs(Configuration $config) : array
- {
- $dependencyFactory = $config->getDependencyFactory();
- $migrationRepository = $dependencyFactory->getMigrationRepository();
- $outputWriter = $dependencyFactory->getOutputWriter();
- $symfonyStopwatch = new SymfonyStopwatch();
- $stopwatch = new Stopwatch($symfonyStopwatch);
-
- return [$config, $migrationRepository, $outputWriter, $stopwatch];
+ return implode("\n", $logger->logs);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/MigratorTest.php b/tests/Doctrine/Migrations/Tests/MigratorTest.php
index 838896e20b..0bf5155f2c 100644
--- a/tests/Doctrine/Migrations/Tests/MigratorTest.php
+++ b/tests/Doctrine/Migrations/Tests/MigratorTest.php
@@ -4,30 +4,33 @@
namespace Doctrine\Migrations\Tests;
+use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;
use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\DependencyFactory;
-use Doctrine\Migrations\Exception\MigrationException;
-use Doctrine\Migrations\MigrationRepository;
+use Doctrine\Migrations\EventDispatcher;
+use Doctrine\Migrations\Metadata\MigrationPlan;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\Migrator;
use Doctrine\Migrations\MigratorConfiguration;
-use Doctrine\Migrations\OutputWriter;
-use Doctrine\Migrations\QueryWriter;
+use Doctrine\Migrations\ParameterFormatterInterface;
+use Doctrine\Migrations\Provider\SchemaDiffProvider;
use Doctrine\Migrations\Stopwatch;
use Doctrine\Migrations\Tests\Stub\Functional\MigrateNotTouchingTheSchema;
use Doctrine\Migrations\Tests\Stub\Functional\MigrationThrowsError;
use Doctrine\Migrations\Version\Direction;
-use PHPUnit\Framework\Constraint\RegularExpression;
+use Doctrine\Migrations\Version\Executor;
+use Doctrine\Migrations\Version\ExecutorInterface;
+use Doctrine\Migrations\Version\Version;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Output\StreamOutput;
+use Symfony\Component\Stopwatch\Stopwatch as SymfonyStopwatch;
use Throwable;
use const DIRECTORY_SEPARATOR;
-require_once __DIR__ . '/realpath.php';
-
class MigratorTest extends MigrationTestCase
{
- /** @var Connection */
+ /** @var Connection|MockObject */
private $conn;
/** @var Configuration */
@@ -36,260 +39,127 @@ class MigratorTest extends MigrationTestCase
/** @var StreamOutput */
protected $output;
- protected function setUp() : void
- {
- $this->conn = $this->getSqliteConnection();
- $this->config = new Configuration($this->conn);
- $this->config->setMigrationsDirectory(__DIR__ . DIRECTORY_SEPARATOR . 'Stub/migration-empty-folder');
- $this->config->setMigrationsNamespace('DoctrineMigrations\\');
- }
+ /** @var MigratorConfiguration */
+ private $migratorConfiguration;
- public function testWriteSqlDown() : void
- {
- $configuration = $this->createMock(Configuration::class);
- $migrationRepository = $this->createMock(MigrationRepository::class);
- $outputWriter = $this->createMock(OutputWriter::class);
- $stopwatch = $this->createMock(Stopwatch::class);
- $queryWriter = $this->createMock(QueryWriter::class);
-
- $sql = ['SELECT 1'];
-
- $migration = $this->getMockBuilder(Migrator::class)
- ->setConstructorArgs([
- $configuration,
- $migrationRepository,
- $outputWriter,
- $stopwatch,
- ])
- ->setMethods(['getSql'])
- ->getMock();
-
- $migration->expects(self::once())
- ->method('getSql')
- ->with('1')
- ->willReturn($sql);
-
- $migrationRepository->expects(self::once())
- ->method('getCurrentVersion')
- ->willReturn('5');
-
- $outputWriter->expects(self::once())
- ->method('write')
- ->with("-- Migrating from 5 to 1\n");
-
- $configuration->expects(self::once())
- ->method('getQueryWriter')
- ->willReturn($queryWriter);
-
- $queryWriter->expects(self::once())
- ->method('write')
- ->with('/path', Direction::DOWN, $sql);
-
- $migration->writeSqlFile('/path', '1');
- }
+ /** @var ExecutorInterface */
+ private $executor;
- public function testMigrateToUnknownVersionThrowsException() : void
- {
- $migration = $this->createTestMigrator($this->config);
-
- $this->expectException(MigrationException::class);
- $this->expectExceptionMessage('Could not find migration version 1234');
+ /** @var TestLogger */
+ private $logger;
- $migration->migrate('1234');
- }
-
- public function testMigrateWithNoMigrationsThrowsException() : void
+ protected function setUp() : void
{
- $migration = $this->createTestMigrator($this->config);
-
- $this->expectException(MigrationException::class);
- $this->expectExceptionMessage('Could not find any migrations to execute.');
-
- $migration->migrate();
+ $this->conn = $this->createMock(Connection::class);
+ $this->config = new Configuration();
+
+ $this->migratorConfiguration = new MigratorConfiguration();
+ $this->config->addMigrationsDirectory(
+ 'DoctrineMigrations\\',
+ __DIR__ . DIRECTORY_SEPARATOR . 'Stub/migration-empty-folder'
+ );
}
- public function testMigrateWithNoMigrationsDontThrowsExceptionIfContiniousIntegrationOption() : void
+ public function testGetSql() : void
{
- $messages = [];
-
- $callback = static function ($msg) use (&$messages) : void {
- $messages[] = $msg;
- };
+ $this->config->addMigrationsDirectory('DoctrineMigrations\\', __DIR__ . '/Stub/migrations-empty-folder');
- $this->config->getOutputWriter()->setCallback($callback);
+ $migrator = $this->createTestMigrator();
- $migrator = $this->createTestMigrator($this->config);
+ $migration = new MigrateNotTouchingTheSchema($this->conn, $this->logger);
+ $plan = new MigrationPlan(new Version(MigrateNotTouchingTheSchema::class), $migration, Direction::UP);
+ $planList = new MigrationPlanList([$plan], Direction::UP);
- $migratorConfiguration = (new MigratorConfiguration())
- ->setNoMigrationException(true);
+ $sql = $migrator->migrate($planList, $this->migratorConfiguration);
- $migrator->migrate(null, $migratorConfiguration);
-
- self::assertCount(2, $messages, 'should output header and no migrations message');
- self::assertContains('No migrations', $messages[1]);
+ self::assertSame([
+ 'Doctrine\\Migrations\\Tests\\Stub\\Functional\\MigrateNotTouchingTheSchema' => ['SELECT 1'],
+ ], $sql);
}
- /**
- * @dataProvider getSqlProvider
- */
- public function testGetSql(?string $to) : void
+ public function testEmptyPlanShowsMessage() : void
{
- /** @var Migrator|MockObject $migration */
- $migration = $this->getMockBuilder(Migrator::class)
- ->disableOriginalConstructor()
- ->setMethods(['migrate'])
- ->getMock();
-
- $expected = [['something']];
+ $migrator = $this->createTestMigrator();
- $migration->expects(self::once())
- ->method('migrate')
- ->with($to)
- ->willReturn($expected);
+ $planList = new MigrationPlanList([], Direction::UP);
+ $migrator->migrate($planList, $this->migratorConfiguration);
- $result = $migration->getSql($to);
-
- self::assertSame($expected, $result);
+ self::assertCount(1, $this->logger->logs, 'should output the no migrations message');
+ self::assertContains('No migrations', $this->logger->logs[0]);
}
- /** @return mixed[][] */
- public function getSqlProvider() : array
+ protected function createTestMigrator() : Migrator
{
- return [
- [null],
- ['test'],
- ];
- }
-
- /**
- * @param string[] $getSqlReturn
- *
- * @dataProvider writeSqlFileProvider
- */
- public function testWriteSqlFile(string $path, string $from, ?string $to, array $getSqlReturn) : void
- {
- $queryWriter = $this->createMock(QueryWriter::class);
- $outputWriter = $this->createMock(OutputWriter::class);
-
- $queryWriter->method('write')
- ->with($path, new RegularExpression('/(up|down)/'), $getSqlReturn)
- ->willReturn(true);
+ $eventManager = new EventManager();
+ $eventDispatcher = new EventDispatcher($this->conn, $eventManager);
- $outputWriter->expects(self::atLeastOnce())
- ->method('write');
+ $this->logger = new TestLogger();
- /** @var Configuration|PHPUnit_Framework_MockObject_MockObject $migration */
- $config = $this->createMock(Configuration::class);
+ $symfonyStopwatch = new SymfonyStopwatch();
+ $stopwatch = new Stopwatch($symfonyStopwatch);
+ $paramFormatter = $this->createMock(ParameterFormatterInterface::class);
+ $storage = $this->createMock(MetadataStorage::class);
+ $schemaDiff = $this->createMock(SchemaDiffProvider::class);
- $dependencyFactory = $this->createMock(DependencyFactory::class);
- $migrationRepository = $this->createMock(MigrationRepository::class);
+ $this->executor = new Executor($storage, $eventDispatcher, $this->conn, $schemaDiff, $this->logger, $paramFormatter, $stopwatch);
- $config->expects(self::once())
- ->method('getDependencyFactory')
- ->willReturn($dependencyFactory);
-
- $dependencyFactory->expects(self::once())
- ->method('getMigrationRepository')
- ->willReturn($migrationRepository);
-
- $dependencyFactory->expects(self::once())
- ->method('getOutputWriter')
- ->willReturn($outputWriter);
-
- $config->method('getCurrentVersion')
- ->willReturn($from);
-
- $config->method('getOutputWriter')
- ->willReturn($outputWriter);
-
- $config->method('getQueryWriter')
- ->willReturn($queryWriter);
-
- if ($to === null) { // this will always just test the "up" direction
- $config->method('getLatestVersion')
- ->willReturn((int) $from + 1);
- }
-
- /** @var Migrator|MockObject $migration */
- $migration = $this->getMockBuilder(Migrator::class)
- ->setConstructorArgs($this->getMigratorConstructorArgs($config))
- ->setMethods(['getSql'])
- ->getMock();
-
- $migration->expects(self::once())
- ->method('getSql')
- ->with($to)
- ->willReturn($getSqlReturn);
-
- self::assertTrue($migration->writeSqlFile($path, $to));
+ return new Migrator($this->conn, $eventDispatcher, $this->executor, $this->logger, $stopwatch);
}
- /**
- * @return mixed[][]
- */
- public function writeSqlFileProvider() : array
+ public function testMigrateAllOrNothing() : void
{
- return [
- [__DIR__, '0', '1', ['1' => ['SHOW DATABASES;']]], // up
- [__DIR__, '0', null, ['1' => ['SHOW DATABASES;']]], // up
- [__DIR__, '1', '1', ['1' => ['SHOW DATABASES;']]], // up (same)
- [__DIR__, '1', '0', ['1' => ['SHOW DATABASES;']]], // down
- [__DIR__ . '/tmpfile.sql', '0', '1', ['1' => ['SHOW DATABASES']]], // tests something actually got written
- ];
- }
+ $this->config->addMigrationsDirectory('DoctrineMigrations\\', __DIR__ . '/Stub/migrations-empty-folder');
- public function testMigrateWithMigrationsAndAddTheCurrentVersionOutputsANoMigrationsMessage() : void
- {
- $messages = [];
+ $migrator = $this->createTestMigrator();
+ $this->conn
+ ->expects(self::exactly(2))
+ ->method('beginTransaction');
- $callback = static function ($msg) use (&$messages) : void {
- $messages[] = $msg;
- };
+ $this->conn
+ ->expects(self::never())
+ ->method('rollback');
- $this->config->getOutputWriter()->setCallback($callback);
- $this->config->setMigrationsDirectory(__DIR__ . '/Stub/migrations-empty-folder');
- $this->config->setMigrationsNamespace('DoctrineMigrations\\');
- $this->config->registerMigration('20160707000000', MigrateNotTouchingTheSchema::class);
- $this->config->createMigrationTable();
- $this->conn->insert($this->config->getMigrationsTableName(), [
- 'version' => '20160707000000',
- 'executed_at' => '2018-05-14 20:44:28',
- ]);
+ $this->conn
+ ->expects(self::exactly(2))
+ ->method('commit');
- $migration = $this->createTestMigrator($this->config);
+ $this->migratorConfiguration->setAllOrNothing(true);
- $migration->migrate();
+ $migration = new MigrateNotTouchingTheSchema($this->conn, $this->logger);
+ $plan = new MigrationPlan(new Version(MigrateNotTouchingTheSchema::class), $migration, Direction::UP);
+ $planList = new MigrationPlanList([$plan], Direction::UP);
- self::assertCount(1, $messages, 'should output the no migrations message');
- self::assertContains('No migrations', $messages[0]);
+ $sql = $migrator->migrate($planList, $this->migratorConfiguration);
+ self::assertSame([
+ 'Doctrine\\Migrations\\Tests\\Stub\\Functional\\MigrateNotTouchingTheSchema' => ['SELECT 1'],
+ ], $sql);
}
- public function testMigrateAllOrNothing() : void
+ public function testMigrateAllOrNothingRollback() : void
{
- $this->config->setMigrationsDirectory(__DIR__ . '/Stub/migrations-empty-folder');
- $this->config->setMigrationsNamespace('DoctrineMigrations\\');
- $this->config->registerMigration('20160707000000', MigrateNotTouchingTheSchema::class);
+ $this->expectException(Throwable::class);
+ $this->expectExceptionMessage('Migration up throws exception.');
- $migration = $this->createTestMigrator($this->config);
+ $this->conn
+ ->expects(self::exactly(2))
+ ->method('beginTransaction');
- $sql = $migration->migrate(null, (new MigratorConfiguration())
- ->setAllOrNothing(true));
+ $this->conn
+ ->expects(self::never())
+ ->method('commit');
- self::assertCount(1, $sql);
- }
+ $this->conn
+ ->expects(self::exactly(2))
+ ->method('rollback');
- public function testMigrateAllOrNothingRollback() : void
- {
- $this->expectException(Throwable::class);
- $this->expectExceptionMessage('Migration up throws exception.');
+ $migrator = $this->createTestMigrator();
- $this->config->setMigrationsDirectory(__DIR__ . '/Stub/migrations-empty-folder');
- $this->config->setMigrationsNamespace('DoctrineMigrations\\');
- $this->config->registerMigration('20160707000000', MigrationThrowsError::class);
+ $this->migratorConfiguration->setAllOrNothing(true);
- $migration = $this->createTestMigrator($this->config);
+ $migration = new MigrationThrowsError($this->conn, $this->logger);
+ $plan = new MigrationPlan(new Version(MigrationThrowsError::class), $migration, Direction::UP);
+ $planList = new MigrationPlanList([$plan], Direction::UP);
- $migration->migrate(null, (new MigratorConfiguration())
- ->setAllOrNothing(true));
+ $migrator->migrate($planList, $this->migratorConfiguration);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/OutputWriterTest.php b/tests/Doctrine/Migrations/Tests/OutputWriterTest.php
deleted file mode 100644
index 253e7e8843..0000000000
--- a/tests/Doctrine/Migrations/Tests/OutputWriterTest.php
+++ /dev/null
@@ -1,51 +0,0 @@
-write('test message');
-
- self::assertSame('test message', $outputWriter->getLastMessage());
- }
-
- public function testWrite() : void
- {
- $this->outputWriter->write('test message');
-
- self::assertSame('test message', $this->lastMessage);
- }
-
- public function testSetCallback() : void
- {
- $this->outputWriter->setCallback(function (string $message) : void {
- $this->lastMessage = '[LOG] ' . $message;
- });
-
- $this->outputWriter->write('test message');
-
- self::assertSame('[LOG] test message', $this->lastMessage);
- }
-
- protected function setUp() : void
- {
- $this->outputWriter = new OutputWriter(function (string $message) : void {
- $this->lastMessage = $message;
- });
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Provider/SchemaDiffProviderTest.php b/tests/Doctrine/Migrations/Tests/Provider/SchemaDiffProviderTest.php
new file mode 100644
index 0000000000..357fbdd070
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Provider/SchemaDiffProviderTest.php
@@ -0,0 +1,51 @@
+provider->createFromSchema();
+
+ self::assertTrue($schema->hasTable('foo'));
+ }
+
+ public function testGetSqlDiffToMigrate() : void
+ {
+ $oldSchema = $this->provider->createFromSchema();
+
+ $newSchema = $this->provider->createToSchema($oldSchema);
+ $newSchema->dropTable('foo');
+
+ $queries = $this->provider->getSqlDiffToMigrate($oldSchema, $newSchema);
+
+ self::assertContains('DROP TABLE foo', $queries);
+ self::assertContains('DROP TABLE foo', $queries);
+ }
+
+ protected function setUp() : void
+ {
+ $conn = $this->getSqliteConnection();
+ $schemaManager = $conn->getSchemaManager();
+ $this->provider = new DBALSchemaDiffProvider($schemaManager, $conn->getDatabasePlatform());
+
+ $schemaChangelog = new Table('foo');
+ $schemaChangelog->addColumn('a', 'string');
+ $schemaChangelog->addColumn('b', 'string');
+ $schemaManager->createTable($schemaChangelog);
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Provider/StubSchemaProviderTest.php b/tests/Doctrine/Migrations/Tests/Provider/StubSchemaProviderTest.php
new file mode 100644
index 0000000000..e8420eca53
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Provider/StubSchemaProviderTest.php
@@ -0,0 +1,23 @@
+createMock(Schema::class);
+ $provider = new StubSchemaProvider($schema);
+
+ self::assertSame($schema, $provider->createSchema());
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/RollupTest.php b/tests/Doctrine/Migrations/Tests/RollupTest.php
index d55d84c351..e6502b53f7 100644
--- a/tests/Doctrine/Migrations/Tests/RollupTest.php
+++ b/tests/Doctrine/Migrations/Tests/RollupTest.php
@@ -4,95 +4,92 @@
namespace Doctrine\Migrations\Tests;
-use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\AbstractMigration;
+use Doctrine\Migrations\Exception\RollupFailed;
+use Doctrine\Migrations\Metadata\AvailableMigration;
+use Doctrine\Migrations\Metadata\AvailableMigrationsList;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\MigrationRepository;
use Doctrine\Migrations\Rollup;
+use Doctrine\Migrations\Version\ExecutionResult;
use Doctrine\Migrations\Version\Version;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
-use RuntimeException;
class RollupTest extends TestCase
{
- /** @var Configuration|MockObject */
- private $configuration;
-
- /** @var Connection|MockObject */
- private $connection;
+ /** @var MockObject|AbstractMigration */
+ private $abstractMigration;
/** @var MigrationRepository|MockObject */
- private $migrationRepository;
+ private $repository;
+
+ /** @var MetadataStorage|MockObject */
+ private $storage;
/** @var Rollup */
private $rollup;
- public function testRollupNoMigrtionsFoundException() : void
+ public function setUp() : void
{
- $this->expectException(RuntimeException::class);
- $this->expectExceptionMessage('No migrations found.');
+ $this->abstractMigration = $this->createMock(AbstractMigration::class);
+ $this->repository = $this->createMock(MigrationRepository::class);
- $this->migrationRepository->expects(self::once())
- ->method('getVersions')
- ->willReturn([]);
-
- $this->rollup->rollup();
+ $this->storage = $this->createMock(MetadataStorage::class);
+ $this->rollup = new Rollup($this->storage, $this->repository);
}
- public function testRollupTooManyMigrationsException() : void
+ public function testRollup() : void
{
- $this->expectException(RuntimeException::class);
- $this->expectExceptionMessage('Too many migrations.');
-
- $version1 = $this->createMock(Version::class);
- $version2 = $this->createMock(Version::class);
-
- $versions = [
- '01' => $version1,
- '02' => $version2,
- ];
-
- $this->migrationRepository->expects(self::once())
- ->method('getVersions')
- ->willReturn($versions);
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+
+ $this->repository
+ ->expects(self::once())
+ ->method('getMigrations')
+ ->willReturn(new AvailableMigrationsList([$m1]));
+
+ $this->storage
+ ->expects(self::at(0))->method('reset')->with();
+ $this->storage
+ ->expects(self::at(1))
+ ->method('complete')
+ ->willReturnCallback(static function (ExecutionResult $result) : void {
+ self::assertEquals(new Version('A'), $result->getVersion());
+ })->with();
$this->rollup->rollup();
}
- public function testRollup() : void
+ public function testRollupTooManyMigrations() : void
{
- $version1 = $this->createMock(Version::class);
-
- $versions = ['01' => $version1];
-
- $this->migrationRepository->expects(self::once())
- ->method('getVersions')
- ->willReturn($versions);
+ $m1 = new AvailableMigration(new Version('A'), $this->abstractMigration);
+ $m2 = new AvailableMigration(new Version('B'), $this->abstractMigration);
- $this->configuration->expects(self::once())
- ->method('getMigrationsTableName')
- ->willReturn('versions');
+ $this->repository
+ ->expects(self::once())
+ ->method('getMigrations')
+ ->willReturn(new AvailableMigrationsList([$m1, $m2]));
- $this->connection->expects(self::once())
- ->method('executeQuery')
- ->with('DELETE FROM versions');
-
- $version1->expects(self::once())
- ->method('markMigrated');
+ $this->storage->expects(self::never())->method('reset');
+ $this->storage->expects(self::never())->method('complete');
+ $this->expectException(RollupFailed::class);
+ $this->expectExceptionMessage('Too many migrations.');
- self::assertSame($version1, $this->rollup->rollup());
+ $this->rollup->rollup();
}
- protected function setUp() : void
+ public function testRollupNoMigrations() : void
{
- $this->configuration = $this->createMock(Configuration::class);
- $this->connection = $this->createMock(Connection::class);
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
-
- $this->rollup = new Rollup(
- $this->configuration,
- $this->connection,
- $this->migrationRepository
- );
+ $this->repository
+ ->expects(self::any())
+ ->method('getMigrations')
+ ->willReturn(new AvailableMigrationsList([]));
+
+ $this->storage->expects(self::never())->method('reset');
+ $this->storage->expects(self::never())->method('complete');
+ $this->expectException(RollupFailed::class);
+ $this->expectExceptionMessage('No migrations found.');
+
+ $this->rollup->rollup();
}
}
diff --git a/tests/Doctrine/Migrations/Tests/SchemaDumperTest.php b/tests/Doctrine/Migrations/Tests/SchemaDumperTest.php
index 1781daaa85..263f237dfb 100644
--- a/tests/Doctrine/Migrations/Tests/SchemaDumperTest.php
+++ b/tests/Doctrine/Migrations/Tests/SchemaDumperTest.php
@@ -11,6 +11,7 @@
use Doctrine\Migrations\Generator\Generator;
use Doctrine\Migrations\Generator\SqlGenerator;
use Doctrine\Migrations\SchemaDumper;
+use InvalidArgumentException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use RuntimeException;
@@ -47,12 +48,53 @@ public function testDumpNoTablesException() : void
->method('getTables')
->willReturn([]);
- $this->schemaDumper->dump('1234');
+ $this->schemaDumper->dump('Foo\\1234');
}
public function testDump() : void
{
$table = $this->createMock(Table::class);
+ $table->expects(self::once())
+ ->method('getName')
+ ->willReturn('test');
+
+ $schema = $this->createMock(Schema::class);
+
+ $this->schemaManager->expects(self::once())
+ ->method('createSchema')
+ ->willReturn($schema);
+
+ $schema->expects(self::once())
+ ->method('getTables')
+ ->willReturn([$table]);
+
+ $this->platform->expects(self::once())
+ ->method('getCreateTableSQL')
+ ->willReturn(['CREATE TABLE test']);
+
+ $this->platform->expects(self::never())
+ ->method('getDropTableSQL')
+ ->willReturn('DROP TABLE test');
+
+ $this->migrationSqlGenerator->expects(self::once())
+ ->method('generate')
+ ->with(['CREATE TABLE test'])
+ ->willReturn('up');
+
+ $this->migrationGenerator->expects(self::once())
+ ->method('generateMigration')
+ ->with('Foo\\1234', 'up', null, null, '')
+ ->willReturn('/path/to/migration.php');
+
+ self::assertSame('/path/to/migration.php', $this->schemaDumper->dump('Foo\\1234'));
+ }
+
+ public function testDumpWithDownMigration() : void
+ {
+ $table = $this->createMock(Table::class);
+ $table->expects(self::once())
+ ->method('getName')
+ ->willReturn('test');
$schema = $this->createMock(Schema::class);
@@ -84,10 +126,103 @@ public function testDump() : void
$this->migrationGenerator->expects(self::once())
->method('generateMigration')
- ->with('1234', 'up', 'down')
+ ->with('Foo\\1234', 'up', null, null, '')
->willReturn('/path/to/migration.php');
- self::assertSame('/path/to/migration.php', $this->schemaDumper->dump('1234'));
+ self::assertSame('/path/to/migration.php', $this->schemaDumper->dump('Foo\\1234', [], false, 120, true));
+ }
+
+ public function testExcludedTableIsNotInTheDump() : void
+ {
+ $this->expectException(RuntimeException::class);
+ $this->expectExceptionMessage('Your database schema does not contain any tables.');
+
+ $table = $this->createMock(Table::class);
+ $table->expects(self::atLeastOnce())
+ ->method('getName')
+ ->willReturn('skipped_table_name');
+
+ $schema = $this->createMock(Schema::class);
+
+ $this->schemaManager->expects(self::once())
+ ->method('createSchema')
+ ->willReturn($schema);
+
+ $schema->expects(self::once())
+ ->method('getTables')
+ ->willReturn([$table]);
+
+ $this->platform->expects(self::never())
+ ->method('getCreateTableSQL');
+
+ $this->platform->expects(self::never())
+ ->method('getDropTableSQL');
+
+ $this->migrationSqlGenerator->expects(self::never())
+ ->method('generate');
+
+ $this->migrationGenerator->expects(self::never())
+ ->method('generateMigration');
+
+ self::assertSame('/path/to/migration.php', $this->schemaDumper->dump('Foo\\1234'));
+ }
+
+ public function testRegexErrorsAreConvertedToExceptions() : void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('Internal PCRE error, please check your Regex. Reported errors: preg_match(): Delimiter must not be alphanumeric or backslash.');
+
+ $table = $this->createMock(Table::class);
+ $table->expects(self::atLeastOnce())
+ ->method('getName')
+ ->willReturn('other_skipped_table_name');
+
+ $schema = $this->createMock(Schema::class);
+
+ $this->schemaManager->expects(self::once())
+ ->method('createSchema')
+ ->willReturn($schema);
+
+ $schema->expects(self::once())
+ ->method('getTables')
+ ->willReturn([$table]);
+
+ self::assertSame('/path/to/migration.php', $this->schemaDumper->dump('Foo\\1234', ['invalid regex']));
+ }
+
+ public function testExcludedTableViaParamIsNotInTheDump() : void
+ {
+ $this->expectException(RuntimeException::class);
+ $this->expectExceptionMessage('Your database schema does not contain any tables.');
+
+ $table = $this->createMock(Table::class);
+ $table->expects(self::atLeastOnce())
+ ->method('getName')
+ ->willReturn('other_skipped_table_name');
+
+ $schema = $this->createMock(Schema::class);
+
+ $this->schemaManager->expects(self::once())
+ ->method('createSchema')
+ ->willReturn($schema);
+
+ $schema->expects(self::once())
+ ->method('getTables')
+ ->willReturn([$table]);
+
+ $this->platform->expects(self::never())
+ ->method('getCreateTableSQL');
+
+ $this->platform->expects(self::never())
+ ->method('getDropTableSQL');
+
+ $this->migrationSqlGenerator->expects(self::never())
+ ->method('generate');
+
+ $this->migrationGenerator->expects(self::never())
+ ->method('generateMigration');
+
+ self::assertSame('/path/to/migration.php', $this->schemaDumper->dump('Foo\\1234', ['/other_skipped_table_name/']));
}
protected function setUp() : void
@@ -101,7 +236,8 @@ protected function setUp() : void
$this->platform,
$this->schemaManager,
$this->migrationGenerator,
- $this->migrationSqlGenerator
+ $this->migrationSqlGenerator,
+ ['/skipped_table_name/']
);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/AbstractMigrationStub.php b/tests/Doctrine/Migrations/Tests/Stub/AbstractMigrationStub.php
index 6061903cf1..ae78f4f109 100644
--- a/tests/Doctrine/Migrations/Tests/Stub/AbstractMigrationStub.php
+++ b/tests/Doctrine/Migrations/Tests/Stub/AbstractMigrationStub.php
@@ -6,7 +6,6 @@
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-use Doctrine\Migrations\Version\Version;
class AbstractMigrationStub extends AbstractMigration
{
@@ -36,9 +35,4 @@ public function exposedAddSql(string $sql, array $params = [], array $types = []
{
$this->addSql($sql, $params, $types);
}
-
- public function getVersion() : Version
- {
- return $this->version;
- }
}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Configuration/AutoloadVersions/Version1Test.php b/tests/Doctrine/Migrations/Tests/Stub/Configuration/AutoloadVersions/Version1Test.php
deleted file mode 100644
index 45fef775c0..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Configuration/AutoloadVersions/Version1Test.php
+++ /dev/null
@@ -1,19 +0,0 @@
-events[__FUNCTION__][] = $args;
- }
-
- public function onMigrationsMigrated(EventArgs $args) : void
- {
- $this->events[__FUNCTION__][] = $args;
- }
-
- public function onMigrationsVersionExecuting(EventArgs $args) : void
- {
- $this->events[__FUNCTION__][] = $args;
- }
-
- public function onMigrationsVersionExecuted(EventArgs $args) : void
- {
- $this->events[__FUNCTION__][] = $args;
- }
-
- public function onMigrationsVersionSkipped(EventArgs $args) : void
- {
- $this->events[__FUNCTION__][] = $args;
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/ExceptionVersionDummy.php b/tests/Doctrine/Migrations/Tests/Stub/ExceptionVersionDummy.php
deleted file mode 100644
index 1960225f60..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/ExceptionVersionDummy.php
+++ /dev/null
@@ -1,22 +0,0 @@
-createTable('foo');
- $table->addColumn('id', 'integer');
- }
-
- public function down(Schema $schema) : void
- {
- $schema->dropTable('foo');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/DryRun/DryRun2.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/DryRun/DryRun2.php
deleted file mode 100644
index 7dab4b44e7..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/DryRun/DryRun2.php
+++ /dev/null
@@ -1,23 +0,0 @@
-getTable('foo');
- $table->addColumn('bar', 'string', ['notnull' => false]);
- }
-
- public function down(Schema $schema) : void
- {
- $table = $schema->getTable('foo');
- $table->dropColumn('bar');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateAddSqlPostAndPreUpAndDownTest.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateAddSqlPostAndPreUpAndDownTest.php
deleted file mode 100644
index f730cd4a77..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateAddSqlPostAndPreUpAndDownTest.php
+++ /dev/null
@@ -1,62 +0,0 @@
-addSql(
- sprintf('INSERT INTO %s (test) values (?)', self::TABLE_NAME),
- [1]
- );
- }
-
- public function up(Schema $schema) : void
- {
- $this->addSql(
- sprintf('INSERT INTO %s (test) values (?)', self::TABLE_NAME),
- [2]
- );
- }
-
- public function postUp(Schema $schema) : void
- {
- $this->addSql(
- sprintf('INSERT INTO %s (test) values (?)', self::TABLE_NAME),
- [3]
- );
- }
-
- public function preDown(Schema $schema) : void
- {
- $this->addSql(
- sprintf('INSERT INTO %s (test) values (?)', self::TABLE_NAME),
- [4]
- );
- }
-
- public function down(Schema $schema) : void
- {
- $this->addSql(
- sprintf('INSERT INTO %s (test) values (?)', self::TABLE_NAME),
- [5]
- );
- }
-
- public function postDown(Schema $schema) : void
- {
- $this->addSql(
- sprintf('INSERT INTO %s (test) values (?)', self::TABLE_NAME),
- [6]
- );
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateAddSqlTest.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateAddSqlTest.php
deleted file mode 100644
index 773d386018..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateAddSqlTest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-addSql('CREATE TABLE test_add_sql_table (test varchar(255))');
- $this->addSql('INSERT INTO test_add_sql_table (test) values (?)', ['test']);
- }
-
- public function down(Schema $schema) : void
- {
- $this->addSql('DROP TABLE test_add_sql_table');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateNotTouchingTheSchema.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateNotTouchingTheSchema.php
index 700aef0b0e..34faa9da1b 100644
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateNotTouchingTheSchema.php
+++ b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateNotTouchingTheSchema.php
@@ -28,7 +28,7 @@ public function preDown(Schema $schema) : void
public function down(Schema $schema) : void
{
- $this->addSql('SELECT 1');
+ $this->addSql('SELECT 2');
}
public function postDown(Schema $schema) : void
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateWithDataModification.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateWithDataModification.php
deleted file mode 100644
index 0f191e8144..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrateWithDataModification.php
+++ /dev/null
@@ -1,28 +0,0 @@
-addSql('INSERT INTO test_data_migration (test) VALUES (1)');
- $this->addSql('INSERT INTO test_data_migration (test) VALUES (2)');
- $this->addSql('INSERT INTO test_data_migration (test) VALUES (3)');
- }
-
- public function down(Schema $schema) : void
- {
- $this->addSql('DELETE FROM test_data_migration');
- }
-
- public function isTransactional() : bool
- {
- return true;
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationMigrateFurther.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationMigrateFurther.php
deleted file mode 100644
index 628f2f8461..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationMigrateFurther.php
+++ /dev/null
@@ -1,22 +0,0 @@
-dropTable('bar');
- }
-
- public function up(Schema $schema) : void
- {
- $table = $schema->createTable('bar');
- $table->addColumn('id', 'integer');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationMigrateUp.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationMigrateUp.php
deleted file mode 100644
index b0ae002143..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationMigrateUp.php
+++ /dev/null
@@ -1,22 +0,0 @@
-dropTable('foo');
- }
-
- public function up(Schema $schema) : void
- {
- $table = $schema->createTable('foo');
- $table->addColumn('id', 'integer');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationModifySchemaInPreAndPost.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationModifySchemaInPreAndPost.php
deleted file mode 100644
index 59668db399..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationModifySchemaInPreAndPost.php
+++ /dev/null
@@ -1,48 +0,0 @@
-createTable($tableName);
- $table->addColumn('id', 'integer');
- }
-
- public function preUp(Schema $schema) : void
- {
- $this->addTable($schema, 'bar');
- }
-
- public function preDown(Schema $schema) : void
- {
- $this->addTable($schema, 'bar');
- }
-
- public function postUp(Schema $schema) : void
- {
- $this->addTable($schema, 'bar2');
- }
-
- public function postDown(Schema $schema) : void
- {
- $this->addTable($schema, 'bar2');
- }
-
- public function down(Schema $schema) : void
- {
- $schema->dropTable('foo');
- }
-
- public function up(Schema $schema) : void
- {
- $table = $schema->createTable('foo');
- $table->addColumn('id', 'integer');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationSkipMigration.php b/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationSkipMigration.php
deleted file mode 100644
index f69ccf8acd..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/Functional/MigrationSkipMigration.php
+++ /dev/null
@@ -1,20 +0,0 @@
-skipIf(true);
- }
-
- public function preDown(Schema $schema) : void
- {
- $this->skipIf(true);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunNamedParams.php b/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunNamedParams.php
deleted file mode 100644
index d6fd1efe2b..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunNamedParams.php
+++ /dev/null
@@ -1,23 +0,0 @@
-addSql('INSERT INTO test VALUES (:one, :two)', [
- 'one' => 'one',
- 'two' => 'two',
- ]);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunQuestionMarkParams.php b/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunQuestionMarkParams.php
deleted file mode 100644
index c192b7a834..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunQuestionMarkParams.php
+++ /dev/null
@@ -1,20 +0,0 @@
-addSql('INSERT INTO test VALUES (?, ?)', ['one', 'two']);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunTypes.php b/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunTypes.php
deleted file mode 100644
index 3e7307a668..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunTypes.php
+++ /dev/null
@@ -1,36 +0,0 @@
-value = $value;
- $this->type = $type;
- }
-
- public function down(Schema $schema) : void
- {
- }
-
- public function up(Schema $schema) : void
- {
- $this->addSql('INSERT INTO test VALUES (?)', $this->value, $this->type);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunWithoutParams.php b/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunWithoutParams.php
deleted file mode 100644
index 70a7391fbf..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/VersionDryRunWithoutParams.php
+++ /dev/null
@@ -1,20 +0,0 @@
-addSql('SELECT 1 WHERE 1');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/VersionDummy.php b/tests/Doctrine/Migrations/Tests/Stub/VersionDummy.php
deleted file mode 100644
index e7bfcdbee7..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/VersionDummy.php
+++ /dev/null
@@ -1,19 +0,0 @@
-addSql('Select 1');
- }
-
- public function up(Schema $schema) : void
- {
- $this->addSql('Select 1');
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/VersionOutputSqlWithParam.php b/tests/Doctrine/Migrations/Tests/Stub/VersionOutputSqlWithParam.php
deleted file mode 100644
index 1852f679ef..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/VersionOutputSqlWithParam.php
+++ /dev/null
@@ -1,34 +0,0 @@
- 1,
- 'param2' => 2,
- 'param3' => 3,
- ];
-
- /** @param mixed[] $param */
- public function setParam(array $param) : void
- {
- $this->param = $param;
- }
-
- public function down(Schema $schema) : void
- {
- }
-
- public function up(Schema $schema) : void
- {
- $this->addSql('Select 1 WHERE 1');
- $this->addSql('Select :param1 WHERE :param2 = :param3', $this->param);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Stub/VersionOutputSqlWithParamAndType.php b/tests/Doctrine/Migrations/Tests/Stub/VersionOutputSqlWithParamAndType.php
deleted file mode 100644
index e758272276..0000000000
--- a/tests/Doctrine/Migrations/Tests/Stub/VersionOutputSqlWithParamAndType.php
+++ /dev/null
@@ -1,39 +0,0 @@
- 1];
-
- /** @var int[] */
- private $type = [Connection::PARAM_STR_ARRAY];
-
- /** @param mixed[] $param */
- public function setParam(array $param) : void
- {
- $this->param = $param;
- }
-
- /** @param int[] $type */
- public function setType(array $type) : void
- {
- $this->type = $type;
- }
-
- public function down(Schema $schema) : void
- {
- }
-
- public function up(Schema $schema) : void
- {
- $this->addSql('Select id WHERE id IN ( :param1 )', $this->param, $this->type);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/TestLogger.php b/tests/Doctrine/Migrations/Tests/TestLogger.php
new file mode 100644
index 0000000000..c3dcd36c49
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/TestLogger.php
@@ -0,0 +1,57 @@
+logs[] = $this->interpolate($message, $context);
+ }
+
+ /**
+ * Interpolates context values into the message placeholders.
+ *
+ * @param mixed[] $context
+ */
+ private function interpolate(string $message, array $context) : string
+ {
+ if (strpos($message, '{') === false) {
+ return $message;
+ }
+
+ $replacements = [];
+ foreach ($context as $key => $val) {
+ if ($val === null || is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) {
+ $replacements["{{$key}}"] = $val;
+ } elseif ($val instanceof DateTimeInterface) {
+ $replacements["{{$key}}"] = $val->format(DateTime::RFC3339);
+ } elseif (is_object($val)) {
+ $replacements["{{$key}}"] = '[object ' . get_class($val) . ']';
+ } else {
+ $replacements["{{$key}}"] = '[' . gettype($val) . ']';
+ }
+ }
+
+ return strtr($message, $replacements);
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/AbstractCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/AbstractCommandTest.php
deleted file mode 100644
index 054c9e94f7..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/AbstractCommandTest.php
+++ /dev/null
@@ -1,351 +0,0 @@
-getMethod('getMigrationConfiguration');
- $method->setAccessible(true);
-
- /** @var AbstractCommand $command */
- $command = $this->getMockForAbstractClass(
- AbstractCommand::class,
- ['command']
- );
-
- if ($helperSet instanceof HelperSet) {
- $command->setHelperSet($helperSet);
- } else {
- $command->setHelperSet(new HelperSet());
- }
-
- if (! $noConnection) {
- $command->getHelperSet()->set(
- new ConnectionHelper($this->getSqliteConnection()),
- 'connection'
- );
- }
-
- if ($configuration !== null) {
- $command->setMigrationConfiguration($configuration);
- }
-
- $output = $this->getMockBuilder(Output::class)
- ->setMethods(['doWrite', 'writeln'])
- ->getMock();
-
- return $method->invokeArgs($command, [$input, $output]);
- }
-
- public function testSetConnection() : void
- {
- $command = new TestAbstractCommand();
- $connection = $this->createMock(Connection::class);
-
- $command->setConnection($connection);
-
- self::assertSame($connection, $command->getConnection());
- }
-
- public function testGetMigrationConfigurationDefaultsToConnection() : void
- {
- $configuration = $this->createMock(Configuration::class);
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
- $command = new TestAbstractCommand();
- $command->setMigrationConfiguration($configuration);
-
- self::assertSame($configuration, $command->getConfiguration($input, $output));
- }
-
- /**
- * Test if the returned migration configuration is the injected one
- */
- public function testInjectedMigrationConfigurationIsBeingReturned() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->setMethods(['getOption'])
- ->getMock();
-
- $input->method('getOption')
- ->with(self::logicalOr(self::equalTo('db-configuration'), self::equalTo('configuration')))
- ->will(self::returnValue(null));
-
- $configuration = $this->createMock(Configuration::class);
-
- self::assertSame($configuration, $this->invokeMigrationConfigurationGetter($input, $configuration));
- }
-
- /**
- * Test if the migration configuration returns the connection from the helper set
- */
- public function testMigrationConfigurationReturnsConnectionFromHelperSet() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->setMethods(['getOption'])
- ->getMock();
-
- $input->method('getOption')
- ->with(self::logicalOr(self::equalTo('db-configuration'), self::equalTo('configuration')))
- ->will(self::returnValue(null));
-
- $actualConfiguration = $this->invokeMigrationConfigurationGetter($input);
-
- self::assertSame('pdo_sqlite', $actualConfiguration->getConnection()->getDriver()->getName());
- }
-
- /**
- * Test if the migration configuration returns the connection from the input option
- */
- public function testMigrationConfigurationReturnsConnectionFromInputOption() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->setMethods(['getOption'])
- ->getMock();
-
- $input->method('getOption')
- ->will(self::returnValueMap([
- ['db-configuration', __DIR__ . '/_files/db-config.php'],
- ]));
-
- $actualConfiguration = $this->invokeMigrationConfigurationGetter($input);
-
- self::assertSame('pdo_sqlite', $actualConfiguration->getConnection()->getDriver()->getName());
- }
-
- /**
- * Test if the migration configuration returns values from the configuration file
- */
- public function testMigrationConfigurationReturnsConfigurationFileOption() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->setMethods(['getOption'])
- ->getMock();
-
- $input->method('getOption')
- ->will(self::returnValueMap([
- ['configuration', __DIR__ . '/_files/config.yml'],
- ]));
-
- $actualConfiguration = $this->invokeMigrationConfigurationGetter($input);
-
- self::assertInstanceOf(YamlConfiguration::class, $actualConfiguration);
- self::assertSame('name', $actualConfiguration->getName());
- self::assertSame('migrations_table_name', $actualConfiguration->getMigrationsTableName());
- self::assertSame('migrations_namespace', $actualConfiguration->getMigrationsNamespace());
- }
-
- /**
- * Test if the migration configuration use the connection in a configuration passed to it.
- */
- public function testMigrationConfigurationReturnsConnectionFromConfigurationIfNothingElseIsProvided() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->getMock();
-
- $connection = $this->getSqliteConnection();
- $configuration = new Configuration($connection);
- $actualConfiguration = $this->invokeMigrationConfigurationGetter($input, $configuration, true);
-
- self::assertSame($connection, $actualConfiguration->getConnection());
- self::assertSame('doctrine_migration_versions', $actualConfiguration->getMigrationsTableName());
- self::assertNull($actualConfiguration->getMigrationsNamespace());
- }
-
- /**
- * Test if throw an error if no connection is passed.
- */
- public function testMigrationConfigurationReturnsErrorWhenNoConnectionIsProvided() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->getMock();
-
- $this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage('You have to specify a --db-configuration file or pass a Database Connection as a dependency to the Migrations.');
-
- $this->invokeMigrationConfigurationGetter($input, null, true);
- }
-
- public function testMigrationsConfigurationFromCommandLineOverridesInjectedConfiguration() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->setMethods(['getOption'])
- ->getMock();
-
- $input->method('getOption')
- ->will(self::returnValueMap([
- ['configuration', __DIR__ . '/_files/config.yml'],
- ]));
-
- $configuration = $this
- ->getMockBuilder(Configuration::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $actualConfiguration = $this->invokeMigrationConfigurationGetter($input, $configuration);
-
- self::assertInstanceOf(YamlConfiguration::class, $actualConfiguration);
- self::assertSame('name', $actualConfiguration->getName());
- self::assertSame('migrations_table_name', $actualConfiguration->getMigrationsTableName());
- self::assertSame('migrations_namespace', $actualConfiguration->getMigrationsNamespace());
- }
-
- /**
- * @see https://github.com/doctrine/migrations/issues/228
- *
- * @group regression
- */
- public function testInjectedConfigurationIsPreferedOverConfigFileIsCurrentWorkingDirectory() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->setMethods(['getOption'])
- ->getMock();
-
- $input->method('getOption')
- ->will(self::returnValueMap([
- ['configuration', null],
- ]));
-
- $configuration = $this->createMock(Configuration::class);
-
- chdir(__DIR__ . '/_files');
- $actualConfiguration = $this->invokeMigrationConfigurationGetter($input, $configuration);
-
- self::assertSame($configuration, $actualConfiguration);
- }
-
- /**
- * Test if the migration configuration can be set via ConfigurationHelper in HelperSet
- */
- public function testMigrationsConfigurationFromConfighelperInHelperset() : void
- {
- $input = $this->getMockBuilder(ArrayInput::class)
- ->setConstructorArgs([[]])
- ->getMock();
-
- $configuration = $this
- ->getMockBuilder(Configuration::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $helperSet = new HelperSet();
- $configHelper = new ConfigurationHelper($this->getSqliteConnection(), $configuration);
- $helperSet->set($configHelper, 'configuration');
-
- $actualConfiguration = $this->invokeMigrationConfigurationGetter($input, null, false, $helperSet);
-
- self::assertSame($configuration, $actualConfiguration);
- }
-
- private function invokeAbstractCommandConfirmation(
- ArrayInput $input,
- QuestionHelper $helper,
- string $response = 'y',
- string $question = 'There is no question?'
- ) : bool {
- $class = new ReflectionClass(AbstractCommand::class);
- $method = $class->getMethod('askConfirmation');
- $method->setAccessible(true);
-
- /** @var AbstractCommand $command */
- $command = $this->getMockForAbstractClass(
- AbstractCommand::class,
- ['command']
- );
-
- $input->setStream($this->getInputStream($response . "\n"));
-
- $helperSet = new HelperSet(['question' => $helper]);
-
- $command->setHelperSet($helperSet);
-
- $output = $this->getMockBuilder(Output::class)
- ->setMethods(['doWrite', 'writeln'])
- ->getMock();
-
- return $method->invokeArgs($command, [$question, $input, $output]);
- }
-
- public function testAskConfirmation() : void
- {
- $input = new ArrayInput([]);
- $helper = new QuestionHelper();
-
- self::assertTrue($this->invokeAbstractCommandConfirmation($input, $helper));
- self::assertFalse($this->invokeAbstractCommandConfirmation($input, $helper, 'n'));
- }
-
- protected function setUp() : void
- {
- $cwd = getcwd();
-
- assert($cwd !== false);
-
- $this->originalCwd = $cwd;
- }
-
- protected function tearDown() : void
- {
- if (getcwd() === $this->originalCwd) {
- return;
- }
-
- chdir($this->originalCwd);
- }
-}
-
-class TestAbstractCommand extends AbstractCommand
-{
- public function getConnection() : Connection
- {
- return $this->connection;
- }
-
- public function getConfiguration(InputInterface $input, OutputInterface $output) : Configuration
- {
- return $this->getMigrationConfiguration($input, $output);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/CommandTestCase.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/CommandTestCase.php
deleted file mode 100644
index 7fb0e355d9..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/CommandTestCase.php
+++ /dev/null
@@ -1,69 +0,0 @@
-connection = $this->createConnection();
- $this->config = $this->createMock(Configuration::class);
- $this->config->method('getConnection')->willReturn($this->connection);
- $this->command = $this->createCommand();
- $this->command->setMigrationConfiguration($this->config);
- $this->app = new Application();
- $this->app->add($this->command);
- }
-
- abstract protected function createCommand() : AbstractCommand;
-
- protected function createConnection() : Connection
- {
- return $this->getSqliteConnection();
- }
-
- protected function createCommandTester() : CommandTester
- {
- return new CommandTester($this->app->find($this->command->getName()));
- }
-
- /**
- * @param mixed[] $args
- * @param mixed[] $options
- *
- * @return mixed[] [CommandTester, int]
- */
- protected function executeCommand(array $args, array $options = []) : array
- {
- $tester = $this->createCommandTester();
-
- $statusCode = $tester->execute(array_replace([
- 'command' => $this->command->getName(),
- ], $args), $options);
-
- return [$tester, $statusCode];
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DiffCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DiffCommandTest.php
index 82be37c97a..c96a9f960e 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DiffCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DiffCommandTest.php
@@ -5,33 +5,35 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Command;
use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Generator\ClassNameGenerator;
use Doctrine\Migrations\Generator\DiffGenerator;
use Doctrine\Migrations\Tools\Console\Command\DiffCommand;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use function sys_get_temp_dir;
final class DiffCommandTest extends TestCase
{
/** @var DiffGenerator|MockObject */
private $migrationDiffGenerator;
- /** @var Configuration|MockObject */
+ /** @var Configuration */
private $configuration;
/** @var DiffCommand|MockObject */
private $diffCommand;
+ /** @var MockObject */
+ private $dependencyFactory;
+
public function testExecute() : void
{
$input = $this->createMock(InputInterface::class);
$output = $this->createMock(OutputInterface::class);
- $this->configuration->expects(self::once())
- ->method('generateVersionNumber')
- ->willReturn('1234');
-
$input->expects(self::at(0))
->method('getOption')
->with('filter-expression')
@@ -58,17 +60,18 @@ public function testExecute() : void
->willReturn(true);
$input->expects(self::at(5))
+ ->method('getOption')
+ ->with('namespace')
+ ->willReturn('FooNs');
+
+ $input->expects(self::at(6))
->method('getOption')
->with('editor-cmd')
->willReturn('mate');
- $this->configuration->expects(self::once())
- ->method('generateVersionNumber')
- ->willReturn('1234');
-
$this->migrationDiffGenerator->expects(self::once())
->method('generate')
- ->with('1234', 'filter expression', true, 80)
+ ->with('FooNs\\Version1234', 'filter expression', true, 80)
->willReturn('/path/to/migration.php');
$this->diffCommand->expects(self::once())
@@ -80,9 +83,9 @@ public function testExecute() : void
->with([
'Generated new migration class to "/path/to/migration.php"',
'',
- 'To run just this migration for testing purposes, you can use migrations:execute --up 1234',
+ 'To run just this migration for testing purposes, you can use migrations:execute --up \'FooNs\\\\Version1234\'',
'',
- 'To revert the migration you can use migrations:execute --down 1234',
+ 'To revert the migration you can use migrations:execute --down \'FooNs\\\\Version1234\'',
]);
$this->diffCommand->execute($input, $output);
@@ -91,16 +94,32 @@ public function testExecute() : void
protected function setUp() : void
{
$this->migrationDiffGenerator = $this->createMock(DiffGenerator::class);
- $this->configuration = $this->createMock(Configuration::class);
+ $this->configuration = new Configuration();
+ $this->configuration->addMigrationsDirectory('FooNs', sys_get_temp_dir());
- $this->diffCommand = $this->getMockBuilder(DiffCommand::class)
- ->setMethods(['createMigrationDiffGenerator', 'procOpen'])
- ->getMock();
+ $this->dependencyFactory = $this->createMock(DependencyFactory::class);
- $this->diffCommand->setMigrationConfiguration($this->configuration);
+ $classNameGenerator = $this->createMock(ClassNameGenerator::class);
+ $classNameGenerator->expects(self::once())
+ ->method('generateClassName')
+ ->with('FooNs')
+ ->willReturn('FooNs\\Version1234');
- $this->diffCommand->expects(self::once())
- ->method('createMigrationDiffGenerator')
+ $this->dependencyFactory->expects(self::once())
+ ->method('getClassNameGenerator')
+ ->willReturn($classNameGenerator);
+
+ $this->dependencyFactory->expects(self::any())
+ ->method('getConfiguration')
+ ->willReturn($this->configuration);
+
+ $this->dependencyFactory->expects(self::any())
+ ->method('getDiffGenerator')
->willReturn($this->migrationDiffGenerator);
+
+ $this->diffCommand = $this->getMockBuilder(DiffCommand::class)
+ ->setConstructorArgs([null, $this->dependencyFactory])
+ ->setMethods(['procOpen'])
+ ->getMock();
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DumpSchemaCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DumpSchemaCommandTest.php
index 96e2f8e827..fd84a21de9 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DumpSchemaCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/DumpSchemaCommandTest.php
@@ -4,8 +4,12 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Command;
+use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Generator\ClassNameGenerator;
+use Doctrine\Migrations\Metadata\AvailableMigration;
+use Doctrine\Migrations\Metadata\AvailableMigrationsList;
use Doctrine\Migrations\MigrationRepository;
use Doctrine\Migrations\SchemaDumper;
use Doctrine\Migrations\Tools\Console\Command\DumpSchemaCommand;
@@ -15,10 +19,11 @@
use RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use function sys_get_temp_dir;
final class DumpSchemaCommandTest extends TestCase
{
- /** @var Configuration|MockObject */
+ /** @var Configuration */
private $configuration;
/** @var DependencyFactory|MockObject */
@@ -30,24 +35,22 @@ final class DumpSchemaCommandTest extends TestCase
/** @var SchemaDumper|MockObject */
private $schemaDumper;
- /** @var DumpSchemaCommand|MockObject */
+ /** @var DumpSchemaCommand */
private $dumpSchemaCommand;
public function testExecuteThrowsRuntimeException() : void
{
$this->expectException(RuntimeException::class);
- $this->expectExceptionMessage('Delete any previous migrations before dumping your schema.');
+ $this->expectExceptionMessage('Delete any previous migrations in the namespace "FooNs" before dumping your schema.');
$input = $this->createMock(InputInterface::class);
$output = $this->createMock(OutputInterface::class);
- $version = $this->createMock(Version::class);
-
- $versions = [$version];
+ $migration = new AvailableMigration(new Version('FooNs\Abc'), $this->createMock(AbstractMigration::class));
$this->migrationRepository->expects(self::once())
- ->method('getVersions')
- ->willReturn($versions);
+ ->method('getMigrations')
+ ->willReturn(new AvailableMigrationsList([$migration]));
$this->dumpSchemaCommand->execute($input, $output);
}
@@ -68,32 +71,41 @@ public function testExecute() : void
->willReturn(80);
$input->expects(self::at(2))
+ ->method('getOption')
+ ->with('with-down-migration')
+ ->willReturn(true);
+
+ $input->expects(self::at(3))
+ ->method('getOption')
+ ->with('namespace')
+ ->willReturn(null);
+
+ $input->expects(self::at(4))
+ ->method('getOption')
+ ->with('filter-tables')
+ ->willReturn(['/foo/']);
+
+ $input->expects(self::at(5))
->method('getOption')
->with('editor-cmd')
->willReturn('test');
- $versions = [];
-
$this->migrationRepository->expects(self::once())
- ->method('getVersions')
- ->willReturn($versions);
-
- $this->configuration->expects(self::once())
- ->method('generateVersionNumber')
- ->willReturn('1234');
+ ->method('getMigrations')
+ ->willReturn(new AvailableMigrationsList([]));
$this->schemaDumper->expects(self::once())
->method('dump')
- ->with('1234', true, 80);
+ ->with('FooNs\\Version1234', ['/foo/'], true, 80);
$output->expects(self::once())
->method('writeln')
->with([
'Dumped your schema to a new migration class at ""',
'',
- 'To run just this migration for testing purposes, you can use migrations:execute --up 1234',
+ 'To run just this migration for testing purposes, you can use migrations:execute --up \'FooNs\\\\Version1234\'',
'',
- 'To revert the migration you can use migrations:execute --down 1234',
+ 'To revert the migration you can use migrations:execute --down \'FooNs\\\\Version1234\'',
'',
'To use this as a rollup migration you can use the migrations:rollup command.',
]);
@@ -103,19 +115,35 @@ public function testExecute() : void
protected function setUp() : void
{
- $this->configuration = $this->createMock(Configuration::class);
+ $this->configuration = new Configuration();
+ $this->configuration->addMigrationsDirectory('FooNs', sys_get_temp_dir());
+
$this->dependencyFactory = $this->createMock(DependencyFactory::class);
$this->migrationRepository = $this->createMock(MigrationRepository::class);
$this->schemaDumper = $this->createMock(SchemaDumper::class);
+ $classNameGenerator = $this->createMock(ClassNameGenerator::class);
+ $classNameGenerator->expects(self::any())
+ ->method('generateClassName')
+ ->with('FooNs')
+ ->willReturn('FooNs\\Version1234');
+
+ $this->dependencyFactory->expects(self::any())
+ ->method('getClassNameGenerator')
+ ->willReturn($classNameGenerator);
+
$this->dependencyFactory->expects(self::any())
->method('getSchemaDumper')
->willReturn($this->schemaDumper);
- $this->dumpSchemaCommand = $this->createPartialMock(DumpSchemaCommand::class, []);
+ $this->dependencyFactory->expects(self::any())
+ ->method('getConfiguration')
+ ->willReturn($this->configuration);
+
+ $this->dependencyFactory->expects(self::any())
+ ->method('getMigrationRepository')
+ ->willReturn($this->migrationRepository);
- $this->dumpSchemaCommand->setMigrationConfiguration($this->configuration);
- $this->dumpSchemaCommand->setDependencyFactory($this->dependencyFactory);
- $this->dumpSchemaCommand->setMigrationRepository($this->migrationRepository);
+ $this->dumpSchemaCommand = new DumpSchemaCommand(null, $this->dependencyFactory);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php
index cfefee5e1e..f47e2827ba 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php
@@ -4,194 +4,182 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Command;
+use Doctrine\Migrations\AbstractMigration;
+use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Metadata\AvailableMigration;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
+use Doctrine\Migrations\MigrationPlanCalculator;
use Doctrine\Migrations\MigrationRepository;
+use Doctrine\Migrations\MigratorConfiguration;
+use Doctrine\Migrations\MigratorInterface;
+use Doctrine\Migrations\QueryWriter;
use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand;
use Doctrine\Migrations\Version\Version;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Tester\CommandTester;
use function getcwd;
+use function sys_get_temp_dir;
class ExecuteCommandTest extends TestCase
{
- /** @var MigrationRepository|MockObject */
- private $migrationRepository;
-
/** @var ExecuteCommand|MockObject */
private $executeCommand;
- public function testWriteSqlCustomPath() : void
- {
- $versionName = '1';
-
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
- $version = $this->createMock(Version::class);
-
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn($versionName);
-
- $input->expects(self::at(3))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn('/path');
+ /** @var MockObject|DependencyFactory */
+ private $dependencyFactory;
- $input->expects(self::at(4))
- ->method('getOption')
- ->with('down')
- ->willReturn(true);
+ /** @var CommandTester */
+ private $executeCommandTester;
- $this->migrationRepository->expects(self::once())
- ->method('getVersion')
- ->with($versionName)
- ->willReturn($version);
+ /** @var MockObject */
+ private $migrator;
- $version->expects(self::once())
- ->method('writeSqlFile')
- ->with('/path', 'down');
+ /** @var MockObject */
+ private $queryWriter;
- self::assertSame(0, $this->executeCommand->execute($input, $output));
+ /**
+ * @param mixed $arg
+ *
+ * @dataProvider getWriteSqlValues
+ */
+ public function testWriteSql($arg, string $path) : void
+ {
+ $this->migrator
+ ->expects(self::once())
+ ->method('migrate')
+ ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration) {
+ self::assertTrue($configuration->isDryRun());
+
+ return ['A'];
+ });
+
+ $this->queryWriter->expects(self::once())
+ ->method('write')
+ ->with($path, 'down', ['A']);
+
+ $this->executeCommandTester->execute([
+ 'version' => '1',
+ '--down' => true,
+ '--write-sql' => $arg,
+ ]);
+
+ self::assertSame(0, $this->executeCommandTester->getStatusCode());
}
- public function testWriteSqlCurrentWorkingDirectory() : void
+ /**
+ * @return mixed[]
+ */
+ public function getWriteSqlValues() : array
{
- $versionName = '1';
-
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
- $version = $this->createMock(Version::class);
-
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn($versionName);
-
- $input->expects(self::at(3))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn(null);
-
- $input->expects(self::at(4))
- ->method('getOption')
- ->with('down')
- ->willReturn(true);
-
- $this->migrationRepository->expects(self::once())
- ->method('getVersion')
- ->with($versionName)
- ->willReturn($version);
-
- $version->expects(self::once())
- ->method('writeSqlFile')
- ->with(getcwd(), 'down');
-
- self::assertSame(0, $this->executeCommand->execute($input, $output));
+ return [
+ [true, getcwd()],
+ [ __DIR__ . '/_files', __DIR__ . '/_files'],
+ ];
}
public function testExecute() : void
{
- $versionName = '1';
+ $this->executeCommand->expects(self::once())
+ ->method('canExecute')
+ ->willReturn(true);
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
- $version = $this->createMock(Version::class);
+ $this->migrator
+ ->expects(self::once())
+ ->method('migrate')
+ ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration) {
+ self::assertFalse($configuration->isDryRun());
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn($versionName);
+ return ['A'];
+ });
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('query-time')
- ->willReturn(true);
+ $this->executeCommandTester->execute([
+ 'version' => '1',
+ '--down' => true,
+ ]);
- $input->expects(self::at(2))
- ->method('getOption')
- ->with('dry-run')
- ->willReturn(true);
+ self::assertSame(0, $this->executeCommandTester->getStatusCode());
+ }
- $input->expects(self::at(3))
- ->method('getOption')
- ->with('write-sql')
+ public function testExecuteCancel() : void
+ {
+ $this->executeCommand->expects(self::once())
+ ->method('canExecute')
->willReturn(false);
- $input->expects(self::at(4))
- ->method('getOption')
- ->with('down')
- ->willReturn(true);
+ $this->migrator
+ ->expects(self::never())
+ ->method('migrate')
+ ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration) {
+ self::assertFalse($configuration->isDryRun());
- $this->migrationRepository->expects(self::once())
- ->method('getVersion')
- ->with($versionName)
- ->willReturn($version);
+ return ['A'];
+ });
- $version->expects(self::once())
- ->method('execute')
- ->with('down');
+ $this->executeCommandTester->execute([
+ 'version' => '1',
+ '--down' => true,
+ ]);
- self::assertSame(0, $this->executeCommand->execute($input, $output));
+ self::assertSame(1, $this->executeCommandTester->getStatusCode());
}
- public function testExecuteCancel() : void
+ protected function setUp() : void
{
- $versionName = '1';
+ $this->dependencyFactory = $this->getMockBuilder(DependencyFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethodsExcept(['getConsoleInputMigratorConfigurationFactory'])
+ ->getMock();
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
- $version = $this->createMock(Version::class);
+ $storage = $this->createMock(MetadataStorage::class);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn($versionName);
+ $this->migrator = $this->createMock(MigratorInterface::class);
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('query-time')
- ->willReturn(true);
+ $this->queryWriter = $this->createMock(QueryWriter::class);
- $input->expects(self::at(2))
- ->method('getOption')
- ->with('dry-run')
- ->willReturn(false);
+ $migration = $this->createMock(AbstractMigration::class);
+ $m1 = new AvailableMigration(new Version('1'), $migration);
- $input->expects(self::at(3))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn(false);
+ $migrationRepository = $this->createMock(MigrationRepository::class);
+ $migrationRepository
+ ->expects(self::once())
+ ->method('getMigration')
+ ->willReturn($m1);
- $input->expects(self::at(4))
- ->method('getOption')
- ->with('down')
- ->willReturn(true);
+ $planCalculator = new MigrationPlanCalculator($migrationRepository, $storage);
- $this->migrationRepository->expects(self::once())
- ->method('getVersion')
- ->with($versionName)
- ->willReturn($version);
+ $configuration = new Configuration();
+ $configuration->setMetadataStorageConfiguration(new TableMetadataStorageConfiguration());
+ $configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir());
- $this->executeCommand->expects(self::once())
- ->method('canExecute')
- ->willReturn(false);
+ $this->dependencyFactory->expects(self::any())
+ ->method('getConfiguration')
+ ->willReturn($configuration);
- $version->expects(self::never())
- ->method('execute');
+ $this->dependencyFactory->expects(self::once())
+ ->method('getMigrator')
+ ->willReturn($this->migrator);
- self::assertSame(1, $this->executeCommand->execute($input, $output));
- }
+ $this->dependencyFactory->expects(self::once())
+ ->method('getMigrationPlanCalculator')
+ ->willReturn($planCalculator);
- protected function setUp() : void
- {
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
+ $this->dependencyFactory->expects(self::any())
+ ->method('getQueryWriter')
+ ->willReturn($this->queryWriter);
+
+ $this->dependencyFactory->expects(self::any())
+ ->method('getMigrationRepository')
+ ->willReturn($migrationRepository);
$this->executeCommand = $this->getMockBuilder(ExecuteCommand::class)
+ ->setConstructorArgs([null, $this->dependencyFactory])
->setMethods(['canExecute'])
->getMock();
- $this->executeCommand->setMigrationRepository($this->migrationRepository);
+ $this->executeCommandTester = new CommandTester($this->executeCommand);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/GenerateCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/GenerateCommandTest.php
index a73a08d340..5915f1e357 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/GenerateCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/GenerateCommandTest.php
@@ -6,16 +6,18 @@
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Generator\ClassNameGenerator;
use Doctrine\Migrations\Generator\Generator;
use Doctrine\Migrations\Tools\Console\Command\GenerateCommand;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use function sys_get_temp_dir;
final class GenerateCommandTest extends TestCase
{
- /** @var Configuration|MockObject */
+ /** @var Configuration */
private $configuration;
/** @var DependencyFactory|MockObject */
@@ -32,18 +34,24 @@ public function testExecute() : void
$input = $this->createMock(InputInterface::class);
$output = $this->createMock(OutputInterface::class);
- $input->expects(self::once())
+ $input->expects(self::at(0))
+ ->method('getOption')
+ ->with('namespace')
+ ->willReturn(null);
+
+ $input->expects(self::at(1))
+ ->method('getOption')
+ ->with('with-down-migration')
+ ->willReturn(true);
+
+ $input->expects(self::at(2))
->method('getOption')
->with('editor-cmd')
->willReturn('mate');
- $this->configuration->expects(self::once())
- ->method('generateVersionNumber')
- ->willReturn('1234');
-
$this->migrationGenerator->expects(self::once())
->method('generateMigration')
- ->with('1234')
+ ->with('FooNs\\Version1234')
->willReturn('/path/to/migration.php');
$this->generateCommand->expects(self::once())
@@ -55,9 +63,9 @@ public function testExecute() : void
->with([
'Generated new migration class to "/path/to/migration.php"',
'',
- 'To run just this migration for testing purposes, you can use migrations:execute --up 1234',
+ 'To run just this migration for testing purposes, you can use migrations:execute --up \'FooNs\Version1234\'',
'',
- 'To revert the migration you can use migrations:execute --down 1234',
+ 'To revert the migration you can use migrations:execute --down \'FooNs\Version1234\'',
]);
$this->generateCommand->execute($input, $output);
@@ -65,19 +73,33 @@ public function testExecute() : void
protected function setUp() : void
{
- $this->configuration = $this->createMock(Configuration::class);
+ $this->configuration = new Configuration();
+ $this->configuration->addMigrationsDirectory('FooNs', sys_get_temp_dir());
+
$this->dependencyFactory = $this->createMock(DependencyFactory::class);
$this->migrationGenerator = $this->createMock(Generator::class);
+ $classNameGenerator = $this->createMock(ClassNameGenerator::class);
+ $classNameGenerator->expects(self::once())
+ ->method('generateClassName')
+ ->with('FooNs')
+ ->willReturn('FooNs\\Version1234');
+
+ $this->dependencyFactory->expects(self::once())
+ ->method('getClassNameGenerator')
+ ->willReturn($classNameGenerator);
+
+ $this->dependencyFactory->expects(self::any())
+ ->method('getConfiguration')
+ ->willReturn($this->configuration);
+
$this->dependencyFactory->expects(self::once())
->method('getMigrationGenerator')
->willReturn($this->migrationGenerator);
$this->generateCommand = $this->getMockBuilder(GenerateCommand::class)
+ ->setConstructorArgs([null, $this->dependencyFactory])
->setMethods(['procOpen'])
->getMock();
-
- $this->generateCommand->setMigrationConfiguration($this->configuration);
- $this->generateCommand->setDependencyFactory($this->dependencyFactory);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/LatestCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/LatestCommandTest.php
new file mode 100644
index 0000000000..778ce81442
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/LatestCommandTest.php
@@ -0,0 +1,70 @@
+setMetadataStorageConfiguration(new TableMetadataStorageConfiguration());
+ $configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir());
+
+ $conn = $this->getSqliteConnection();
+
+ $dependencyFactory = new DependencyFactory($configuration, $conn);
+
+ $this->migrationRepository = $dependencyFactory->getMigrationRepository();
+ $this->metadataStorage = $dependencyFactory->getMetadataStorage();
+
+ $this->command = new LatestCommand(null, $dependencyFactory);
+ $this->commandTester = new CommandTester($this->command);
+ }
+
+ public function testExecute() : void
+ {
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('1231'), $migrationClass);
+ $this->migrationRepository->registerMigrationInstance(new Version('1230'), $migrationClass);
+
+ $this->metadataStorage->complete(new ExecutionResult(new Version('1231')));
+
+ $this->commandTester->execute(
+ [],
+ ['interactive' => false]
+ );
+
+ $lines = array_map('trim', explode("\n", trim($this->commandTester->getDisplay(true))));
+ self::assertSame('1231', $lines[0]);
+ }
+}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrateCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrateCommandTest.php
index daf9e93056..03e18b4165 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrateCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrateCommandTest.php
@@ -4,506 +4,316 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Command;
+use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\DependencyFactory;
-use Doctrine\Migrations\MigrationRepository;
+use Doctrine\Migrations\Metadata\MigrationPlanList;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\Migrator;
+use Doctrine\Migrations\MigratorConfiguration;
+use Doctrine\Migrations\QueryWriter;
+use Doctrine\Migrations\Tests\MigrationTestCase;
use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
+use Doctrine\Migrations\Version\ExecutionResult;
+use Doctrine\Migrations\Version\Version;
use PHPUnit\Framework\MockObject\MockObject;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Tester\CommandTester;
use function getcwd;
+use function strpos;
+use function sys_get_temp_dir;
-class MigrateCommandTest extends TestCase
+class MigrateCommandTest extends MigrationTestCase
{
/** @var DependencyFactory|MockObject */
private $dependencyFactory;
- /** @var MigrationRepository|MockObject */
- private $migrationRepository;
-
- /** @var Configuration|MockObject */
+ /** @var Configuration */
private $configuration;
/** @var MigrateCommand|MockObject */
private $migrateCommand;
- public function testExecuteCouldNotResolveAlias() : void
- {
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
+ /** @var CommandTester */
+ private $migrateCommandTester;
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('1234');
+ /** @var MetadataStorage */
+ private $storage;
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
+ /** @var MockObject */
+ private $queryWriter;
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('1234')
- ->willReturn('');
+ public function testExecuteEmptyMigrationPlanCausesException() : void
+ {
+ $result = new ExecutionResult(new Version('A'));
+ $this->storage->complete($result);
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
+ $this->migrateCommandTester->execute(
+ ['version' => 'first'],
+ ['interactive' => false]
+ );
+
+ self::assertTrue(strpos($this->migrateCommandTester->getDisplay(true), 'Could not find any migrations to execute') !== false);
+ self::assertSame(1, $this->migrateCommandTester->getStatusCode());
}
public function testExecuteAlreadyAtFirstVersion() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn(null);
-
- $output->expects(self::at(4))
- ->method('writeln')
- ->with('Already at first version.');
-
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
+ $result = new ExecutionResult(new Version('A'));
+ $this->storage->complete($result);
+
+ $this->migrateCommandTester->execute(
+ [
+ 'version' => 'first',
+ '--allow-no-migration' => true,
+ ],
+ ['interactive' => false]
+ );
+
+ self::assertTrue(strpos($this->migrateCommandTester->getDisplay(true), 'Already at first version.') !== false);
+ self::assertSame(0, $this->migrateCommandTester->getStatusCode());
}
public function testExecuteAlreadyAtLatestVersion() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('next');
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('next')
- ->willReturn(null);
-
- $output->expects(self::at(4))
- ->method('writeln')
- ->with('Already at latest version.');
-
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
+ $result = new ExecutionResult(new Version('A'));
+ $this->storage->complete($result);
+
+ $this->migrateCommandTester->execute(
+ [
+ 'version' => 'latest',
+ '--allow-no-migration' => true,
+ ],
+ ['interactive' => false]
+ );
+
+ self::assertTrue(strpos($this->migrateCommandTester->getDisplay(true), 'Already at latest version.') !== false);
+ self::assertSame(0, $this->migrateCommandTester->getStatusCode());
}
public function testExecuteTheDeltaCouldNotBeReached() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
+ $result = new ExecutionResult(new Version('A'));
+ $this->storage->complete($result);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('current-1');
+ $this->migrateCommandTester->execute(
+ ['version' => 'current+1'],
+ ['interactive' => false]
+ );
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('current-1')
- ->willReturn(null);
-
- $output->expects(self::at(4))
- ->method('writeln')
- ->with('The delta couldn\'t be reached.');
-
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
+ self::assertTrue(strpos($this->migrateCommandTester->getDisplay(true), 'The delta couldn\'t be reached.') !== false);
+ self::assertSame(1, $this->migrateCommandTester->getStatusCode());
}
public function testExecuteUnknownVersion() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('unknown');
+ $this->migrateCommandTester->execute(
+ ['version' => 'unknown'],
+ ['interactive' => false]
+ );
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('unknown')
- ->willReturn(null);
-
- $output->expects(self::at(4))
- ->method('writeln')
- ->with('Unknown version: unknown');
-
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
+ self::assertTrue(strpos($this->migrateCommandTester->getDisplay(true), 'Unknown version: unknown') !== false);
+ self::assertSame(1, $this->migrateCommandTester->getStatusCode());
}
public function testExecutedUnavailableMigrationsCancel() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
+ $result = new ExecutionResult(new Version('345'));
+ $this->storage->complete($result);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
+ $migrator = $this->createMock(Migrator::class);
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn('1234');
+ $this->dependencyFactory->expects(self::any())
+ ->method('getMigrator')
+ ->willReturn($migrator);
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1235']);
+ $migrator->expects(self::never())
+ ->method('migrate');
$this->migrateCommand->expects(self::once())
->method('canExecute')
+ ->with('Are you sure you wish to continue? (y/n)')
->willReturn(false);
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
- }
-
- public function testExecuteWriteSqlCustomPath() : void
- {
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
- $migration = $this->createMock(Migrator::class);
-
- $this->dependencyFactory->expects(self::once())
- ->method('getMigrator')
- ->willReturn($migration);
-
- $migration->expects(self::once())
- ->method('writeSqlFile')
- ->with('test', '1234');
+ $this->migrateCommandTester->execute(['version' => 'prev']);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn('test');
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn('1234');
-
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1235']);
-
- $this->migrateCommand->expects(self::once())
- ->method('canExecute')
- ->willReturn(true);
-
- self::assertSame(0, $this->migrateCommand->execute($input, $output));
+ self::assertSame(3, $this->migrateCommandTester->getStatusCode());
}
- public function testExecuteWriteSqlCurrentWorkingDirectory() : void
+ /**
+ * @param mixed $arg
+ *
+ * @dataProvider getWriteSqlValues
+ */
+ public function testExecuteWriteSql($arg, string $path) : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
$migrator = $this->createMock(Migrator::class);
- $this->dependencyFactory->expects(self::once())
+ $this->dependencyFactory->expects(self::any())
->method('getMigrator')
->willReturn($migrator);
$migrator->expects(self::once())
- ->method('writeSqlFile')
- ->with(getcwd(), '1234');
-
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn(null);
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn('1234');
-
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1235']);
-
- $this->migrateCommand->expects(self::once())
- ->method('canExecute')
- ->willReturn(true);
+ ->method('migrate')
+ ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration) {
+ return ['A'];
+ });
+
+ $this->queryWriter->expects(self::once())
+ ->method('write')
+ ->with($path, 'up', ['A']);
+
+ $this->migrateCommandTester->execute(
+ ['--write-sql' => $arg],
+ ['interactive' => false]
+ );
+ self::assertSame(0, $this->migrateCommandTester->getStatusCode());
+ }
- self::assertSame(0, $this->migrateCommand->execute($input, $output));
+ /**
+ * @return mixed[]
+ */
+ public function getWriteSqlValues() : array
+ {
+ return [
+ [true, getcwd()],
+ [ __DIR__ . '/_files', __DIR__ . '/_files'],
+ ];
}
public function testExecuteMigrate() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
$migrator = $this->createMock(Migrator::class);
- $this->dependencyFactory->expects(self::once())
+ $this->dependencyFactory->expects(self::any())
->method('getMigrator')
->willReturn($migrator);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn(false);
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn('1234');
-
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1235']);
-
- $this->migrateCommand->expects(self::at(0))
- ->method('canExecute')
- ->with('Are you sure you wish to continue? (y/n)')
- ->willReturn(true);
-
- $this->migrateCommand->expects(self::at(1))
+ $this->migrateCommand->expects(self::once())
->method('canExecute')
- ->with('WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)')
->willReturn(true);
$migrator->expects(self::once())
->method('migrate')
- ->with('1234');
+ ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration) {
+ self::assertCount(1, $planList);
+ self::assertEquals(new Version('A'), $planList->getFirst()->getVersion());
+
+ return ['A'];
+ });
+
+ $this->migrateCommandTester->execute([]);
- self::assertSame(0, $this->migrateCommand->execute($input, $output));
+ self::assertSame(0, $this->migrateCommandTester->getStatusCode());
}
public function testExecuteMigrateAllOrNothing() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
$migrator = $this->createMock(Migrator::class);
- $this->dependencyFactory->expects(self::once())
+ $this->dependencyFactory->expects(self::any())
->method('getMigrator')
->willReturn($migrator);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn(false);
-
- $input->expects(self::at(2))
- ->method('getOption')
- ->with('allow-no-migration')
- ->willReturn(false);
-
- $input->expects(self::at(3))
- ->method('getOption')
- ->with('query-time')
- ->willReturn(false);
-
- $input->expects(self::at(4))
- ->method('getOption')
- ->with('dry-run')
- ->willReturn(false);
-
- $input->expects(self::at(5))
- ->method('getOption')
- ->with('all-or-nothing')
- ->willReturn(true);
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn('1234');
+ $migrator->expects(self::once())
+ ->method('migrate')
+ ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration) {
+ self::assertTrue($configuration->isAllOrNothing());
+ self::assertCount(1, $planList);
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1235']);
+ return ['A'];
+ });
- $this->migrateCommand->expects(self::at(0))
- ->method('canExecute')
- ->with('Are you sure you wish to continue? (y/n)')
- ->willReturn(true);
-
- $this->migrateCommand->expects(self::at(1))
+ $this->migrateCommand->expects(self::once())
->method('canExecute')
- ->with('WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)')
->willReturn(true);
- $migrator->expects(self::once())
- ->method('migrate')
- ->with('1234');
+ $this->migrateCommandTester->execute(
+ ['--all-or-nothing' => true],
+ ['interactive' => false]
+ );
- self::assertSame(0, $this->migrateCommand->execute($input, $output));
+ self::assertSame(0, $this->migrateCommandTester->getStatusCode());
}
public function testExecuteMigrateCancelExecutedUnavailableMigrations() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
+ $result = new ExecutionResult(new Version('345'));
+ $this->storage->complete($result);
$migrator = $this->createMock(Migrator::class);
- $this->dependencyFactory->expects(self::never())
+ $this->dependencyFactory->expects(self::once())
->method('getMigrator')
->willReturn($migrator);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn(false);
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn('1234');
-
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1235']);
+ $migrator->expects(self::never())
+ ->method('migrate');
- $this->migrateCommand->expects(self::once())
+ $this->migrateCommand->expects(self::at(0))
->method('canExecute')
->with('Are you sure you wish to continue? (y/n)')
+ ->willReturn(true);
+
+ $this->migrateCommand->expects(self::at(1))
+ ->method('canExecute')
+ ->with('WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)')
->willReturn(false);
- $migrator->expects(self::never())
- ->method('migrate');
+ $this->migrateCommandTester->execute(['version' => 'latest']);
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
+ self::assertSame(3, $this->migrateCommandTester->getStatusCode());
}
public function testExecuteMigrateCancel() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
$migrator = $this->createMock(Migrator::class);
$this->dependencyFactory->expects(self::once())
->method('getMigrator')
->willReturn($migrator);
- $input->expects(self::once())
- ->method('getArgument')
- ->with('version')
- ->willReturn('prev');
-
- $input->expects(self::at(1))
- ->method('getOption')
- ->with('write-sql')
- ->willReturn(false);
-
- $this->configuration->expects(self::once())
- ->method('setIsDryRun')
- ->with(false);
-
- $this->configuration->expects(self::once())
- ->method('resolveVersionAlias')
- ->with('prev')
- ->willReturn('1234');
-
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1235']);
-
- $this->migrateCommand->expects(self::at(0))
- ->method('canExecute')
- ->with('Are you sure you wish to continue? (y/n)')
- ->willReturn(true);
+ $migrator->expects(self::never())
+ ->method('migrate');
- $this->migrateCommand->expects(self::at(1))
+ $this->migrateCommand->expects(self::once())
->method('canExecute')
->with('WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)')
->willReturn(false);
- $migrator->expects(self::never())
- ->method('migrate');
+ $this->migrateCommandTester->execute(['version' => 'latest']);
- self::assertSame(1, $this->migrateCommand->execute($input, $output));
+ self::assertSame(3, $this->migrateCommandTester->getStatusCode());
}
protected function setUp() : void
{
- $this->configuration = $this->createMock(Configuration::class);
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
- $this->dependencyFactory = $this->createMock(DependencyFactory::class);
+ $this->configuration = new Configuration();
+ $this->configuration->addMigrationsDirectory('FooNs', sys_get_temp_dir());
+
+ $connection = $this->getSqliteConnection();
+
+ $this->dependencyFactory = $this->getMockBuilder(DependencyFactory::class)
+ ->setConstructorArgs([$this->configuration, $connection])
+ ->setMethods(['getMigrator', 'getQueryWriter'])
+ ->getMock();
+
+ $this->queryWriter = $this->createMock(QueryWriter::class);
+ $this->dependencyFactory->expects(self::any())
+ ->method('getQueryWriter')
+ ->willReturn($this->queryWriter);
+
+ $migration = $this->createMock(AbstractMigration::class);
+
+ $repo = $this->dependencyFactory->getMigrationRepository();
+ $repo->registerMigrationInstance(new Version('A'), $migration);
$this->migrateCommand = $this->getMockBuilder(MigrateCommand::class)
+ ->setConstructorArgs([null, $this->dependencyFactory])
->setMethods(['canExecute'])
->getMock();
- $this->migrateCommand->setMigrationConfiguration($this->configuration);
- $this->migrateCommand->setMigrationRepository($this->migrationRepository);
- $this->migrateCommand->setDependencyFactory($this->dependencyFactory);
+ $this->migrateCommandTester = new CommandTester($this->migrateCommand);
+
+ $this->storage = $this->dependencyFactory->getMetadataStorage();
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrationStatusTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrationStatusTest.php
deleted file mode 100644
index f284f04058..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrationStatusTest.php
+++ /dev/null
@@ -1,141 +0,0 @@
-migrationDirectory = __DIR__ . '/../../../Stub/migration-empty-folder';
- }
-
- /**
- * Tests the display of the previous/current/next/latest versions.
- */
- public function testVersions() : void
- {
- self::assertVersion('prev', '123', 'Previous Version', 'FORMATTED (123)');
- self::assertVersion('current', '234', 'Current Version', 'FORMATTED (234)');
- self::assertVersion('next', '345', 'Next Version', 'FORMATTED (345)');
- self::assertVersion('latest', '456', 'Latest Version', 'FORMATTED (456)');
-
- // Initial version is not formatted as date.
- self::assertVersion('prev', '0', 'Previous Version', '0');
-
- // The initial version has no previous version, and the latest has no next.
- self::assertVersion('prev', null, 'Previous Version', 'Already at first version');
- self::assertVersion('next', null, 'Next Version', 'Already at latest version');
- }
-
- /**
- * Asserts that one version is displayed correctly.
- *
- * @param string $alias "prev", "current", "next", "latest".
- * @param string|null $version The version corresponding to the $alias.
- * @param string $label The expected row label.
- * @param string $output The expected row value.
- */
- protected function assertVersion(string $alias, ?string $version, string $label, string $output) : void
- {
- $command = $this
- ->getMockBuilder(StatusCommand::class)
- ->setConstructorArgs(['migrations:status'])
- ->setMethods(
- ['getMigrationConfiguration']
- )
- ->getMock();
-
- $configuration = $this->getMockBuilder(Configuration::class)
- ->setConstructorArgs([$this->getSqliteConnection()])
- ->setMethods(['resolveVersionAlias', 'getDateTime', 'getAvailableVersions'])
- ->getMock();
-
- $configuration
- ->expects(self::exactly(4))
- ->method('resolveVersionAlias')
- ->will(self::returnCallback(static function ($argAlias) use ($alias, $version) {
- return $argAlias === $alias ? $version : '999';
- }));
-
- $configuration
- ->method('getDateTime')
- ->will(self::returnValue('FORMATTED'));
-
- $configuration
- ->method('getAvailableVersions')
- ->will(self::returnValue([]));
-
- $configuration->setMigrationsNamespace('DoctrineMigrations');
- $configuration->setMigrationsDirectory($this->migrationDirectory);
-
- $command
- ->expects(self::once())
- ->method('getMigrationConfiguration')
- ->will(self::returnValue($configuration));
-
- $commandTester = new CommandTester($command);
- $commandTester->execute(
- [],
- []
- );
-
- $textOutput = $commandTester->getDisplay();
- self::assertRegExp('/\s+>> ' . $label . ':\s+' . preg_quote($output) . '/m', $textOutput);
- }
-
- public function testShowVersions() : void
- {
- $configuration = new Configuration($this->getSqliteConnection());
- $configuration->setMigrationsNamespace('DoctrineMigrations');
- $configuration->setMigrationsDirectory($this->migrationDirectory);
-
- $configuration->registerMigration('1233', Version1Test::class);
- $configuration->registerMigration('1234', Version1Test::class);
- $configuration->registerMigration('20170101010101', Version1Test::class);
- $configuration->registerMigration('20170101010102', Version1Test::class);
- $configuration->registerMigration('VeryLongMigrationName_VeryLongMigrationName_VeryLongMigrationName_1', Version1Test::class);
-
- $configuration->registerMigration('VeryLongMigrationName_VeryLongMigrationName_VeryLongMigrationName_2', Version1Test::class);
-
- $configuration->getVersion('1234')->markMigrated();
- $configuration->getVersion('20170101010101')->markMigrated();
- $configuration->getVersion('VeryLongMigrationName_VeryLongMigrationName_VeryLongMigrationName_1')->markMigrated();
-
- $command = $this
- ->getMockBuilder(StatusCommand::class)
- ->setConstructorArgs(['migrations:status'])
- ->setMethods(['getMigrationConfiguration'])
- ->getMock();
-
- $command
- ->expects(self::once())
- ->method('getMigrationConfiguration')
- ->will(self::returnValue($configuration));
-
- $commandTester = new CommandTester($command);
- $commandTester->execute(
- ['--show-versions' => true],
- []
- );
-
- $textOutput = $commandTester->getDisplay();
- self::assertRegExp('/\s+>> \(1233\)\s+not migrated/m', $textOutput);
- self::assertRegExp('/\s+>> \(1234\)\s+migrated/m', $textOutput);
- self::assertRegExp('/\s+>> 2017-01-01 01:01:01 \(20170101010101\)\s+migrated/m', $textOutput);
- self::assertRegExp('/\s+>> 2017-01-01 01:01:02 \(20170101010102\)\s+not migrated/m', $textOutput);
- self::assertRegExp('/\s+>> \(VeryLongMigrationName_VeryLongMigrationName_VeryLongMigrationName_1\)\s+migrated/m', $textOutput);
- self::assertRegExp('/\s+>> \(VeryLongMigrationName_VeryLongMigrationName_VeryLongMigrationName_2\)\s+not migrated/m', $textOutput);
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrationVersionTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrationVersionTest.php
index bd3cb105ab..330c91cded 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrationVersionTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/MigrationVersionTest.php
@@ -4,12 +4,18 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Command;
+use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
+use Doctrine\Migrations\MigrationRepository;
use Doctrine\Migrations\Tests\MigrationTestCase;
-use Doctrine\Migrations\Tests\Stub\Version1Test;
+use Doctrine\Migrations\Tests\TestLogger;
use Doctrine\Migrations\Tools\Console\Command\VersionCommand;
+use Doctrine\Migrations\Version\Direction;
+use Doctrine\Migrations\Version\ExecutionResult;
+use Doctrine\Migrations\Version\Version;
use InvalidArgumentException;
-use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Tester\CommandTester;
@@ -17,28 +23,33 @@
class MigrationVersionTest extends MigrationTestCase
{
- /** @var VersionCommand|MockObject */
+ /** @var VersionCommand */
private $command;
- /** @var Configuration */
- private $configuration;
+ /** @var MigrationRepository */
+ private $migrationRepository;
+
+ /** @var MetadataStorage */
+ private $metadataStorage;
+
+ /** @var CommandTester */
+ private $commandTester;
protected function setUp() : void
{
- $this->command = $this
- ->getMockBuilder(VersionCommand::class)
- ->setConstructorArgs(['migrations:version'])
- ->setMethods(['getMigrationConfiguration'])
- ->getMock();
-
- $this->configuration = new Configuration($this->getSqliteConnection());
- $this->configuration->setMigrationsNamespace('DoctrineMigrations');
- $this->configuration->setMigrationsDirectory(sys_get_temp_dir());
-
- $this->command
- ->expects(self::once())
- ->method('getMigrationConfiguration')
- ->will(self::returnValue($this->configuration));
+ $configuration = new Configuration();
+ $configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir());
+
+ $conn = $this->getSqliteConnection();
+ $logger = new TestLogger();
+
+ $dependencyFactory = new DependencyFactory($configuration, $conn, null, $logger);
+
+ $this->migrationRepository = $dependencyFactory->getMigrationRepository();
+ $this->metadataStorage = $dependencyFactory->getMetadataStorage();
+
+ $this->command = new VersionCommand(null, $dependencyFactory);
+ $this->commandTester = new CommandTester($this->command);
}
/**
@@ -46,14 +57,14 @@ protected function setUp() : void
*/
public function testAddRangeOption() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->registerMigration('1234', Version1Test::class);
- $this->configuration->registerMigration('1235', Version1Test::class);
- $this->configuration->registerMigration('1239', Version1Test::class);
- $this->configuration->registerMigration('1240', Version1Test::class);
-
- $commandTester = new CommandTester($this->command);
- $commandTester->execute(
+ $mock = $this->createMock(AbstractMigration::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('1233'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1234'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1235'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1239'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1240'), $mock);
+
+ $this->commandTester->execute(
[
'--add' => true,
'--range-from' => '1234',
@@ -62,11 +73,12 @@ public function testAddRangeOption() : void
['interactive' => false]
);
- self::assertFalse($this->configuration->getVersion('1233')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1234')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1235')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1239')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1240')->isMigrated());
+ $executed = $this->metadataStorage->getExecutedMigrations();
+ self::assertFalse($executed->hasMigration(new Version('1233')));
+ self::assertTrue($executed->hasMigration(new Version('1234')));
+ self::assertTrue($executed->hasMigration(new Version('1235')));
+ self::assertTrue($executed->hasMigration(new Version('1239')));
+ self::assertFalse($executed->hasMigration(new Version('1240')));
}
/**
@@ -74,12 +86,10 @@ public function testAddRangeOption() : void
*/
public function testAddRangeWithoutRangeToOption() : void
{
- $commandTester = new CommandTester($this->command);
-
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Options --range-to and --range-from should be used together.');
- $commandTester->execute(
+ $this->commandTester->execute(
[
'--add' => true,
'--range-from' => '1233',
@@ -93,12 +103,10 @@ public function testAddRangeWithoutRangeToOption() : void
*/
public function testAddRangeWithoutRangeFromOption() : void
{
- $commandTester = new CommandTester($this->command);
-
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Options --range-to and --range-from should be used together.');
- $commandTester->execute(
+ $this->commandTester->execute(
[
'--add' => true,
'--range-to' => '1233',
@@ -112,12 +120,10 @@ public function testAddRangeWithoutRangeFromOption() : void
*/
public function testAddAllOptionsWithRangeTo() : void
{
- $commandTester = new CommandTester($this->command);
-
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Options --all and --range-to/--range-from both used. You should use only one of them.');
- $commandTester->execute(
+ $this->commandTester->execute(
[
'--add' => true,
'--all' => true,
@@ -132,12 +138,10 @@ public function testAddAllOptionsWithRangeTo() : void
*/
public function testAddAllOptionsWithRangeFrom() : void
{
- $commandTester = new CommandTester($this->command);
-
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Options --all and --range-to/--range-from both used. You should use only one of them.');
- $commandTester->execute(
+ $this->commandTester->execute(
[
'--add' => true,
'--all' => true,
@@ -152,19 +156,19 @@ public function testAddAllOptionsWithRangeFrom() : void
*/
public function testDeleteRangeOption() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->registerMigration('1234', Version1Test::class);
- $this->configuration->registerMigration('1235', Version1Test::class);
- $this->configuration->registerMigration('1239', Version1Test::class);
- $this->configuration->registerMigration('1240', Version1Test::class);
-
- $this->configuration->getVersion('1233')->markMigrated();
- $this->configuration->getVersion('1234')->markMigrated();
- $this->configuration->getVersion('1239')->markMigrated();
- $this->configuration->getVersion('1240')->markMigrated();
-
- $commandTester = new CommandTester($this->command);
- $commandTester->execute(
+ $mock = $this->createMock(AbstractMigration::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('1233'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1234'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1235'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1239'), $mock);
+ $this->migrationRepository->registerMigrationInstance(new Version('1240'), $mock);
+
+ foreach (['1233', '1234', '1239', '1240'] as $v) {
+ $r = new ExecutionResult(new Version($v));
+ $this->metadataStorage->complete($r);
+ }
+
+ $this->commandTester->execute(
[
'--delete' => true,
'--range-from' => '1234',
@@ -173,11 +177,12 @@ public function testDeleteRangeOption() : void
['interactive' => false]
);
- self::assertTrue($this->configuration->getVersion('1233')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1234')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1235')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1239')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1240')->isMigrated());
+ $executed = $this->metadataStorage->getExecutedMigrations();
+ self::assertTrue($executed->hasMigration(new Version('1233')));
+ self::assertFalse($executed->hasMigration(new Version('1234')));
+ self::assertFalse($executed->hasMigration(new Version('1235')));
+ self::assertFalse($executed->hasMigration(new Version('1239')));
+ self::assertTrue($executed->hasMigration(new Version('1240')));
}
/**
@@ -185,26 +190,28 @@ public function testDeleteRangeOption() : void
*/
public function testAddAllOption() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->registerMigration('1234', Version1Test::class);
- $this->configuration->registerMigration('1235', Version1Test::class);
- $this->configuration->registerMigration('1239', Version1Test::class);
- $this->configuration->registerMigration('1240', Version1Test::class);
-
- $commandTester = new CommandTester($this->command);
- $commandTester->execute(
+ $migrationClass = $this->createMock(AbstractMigration::class);
+
+ $this->migrationRepository->registerMigrationInstance(new Version('1231'), $migrationClass);
+ $this->migrationRepository->registerMigrationInstance(new Version('1232'), $migrationClass);
+ $this->migrationRepository->registerMigrationInstance(new Version('1234'), $migrationClass);
+
+ $result = new ExecutionResult(new Version('1234'), Direction::UP);
+ $this->metadataStorage->complete($result);
+
+ $this->commandTester->execute(
[
- '--add' => true,
- '--all' => true,
+ '--add' => true,
+ '--all' => true,
],
['interactive' => false]
);
- self::assertTrue($this->configuration->getVersion('1233')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1234')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1235')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1239')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1240')->isMigrated());
+ $executedMigrations = $this->metadataStorage->getExecutedMigrations();
+
+ self::assertTrue($executedMigrations->hasMigration(new Version('1231')));
+ self::assertTrue($executedMigrations->hasMigration(new Version('1232')));
+ self::assertTrue($executedMigrations->hasMigration(new Version('1234')));
}
/**
@@ -212,17 +219,17 @@ public function testAddAllOption() : void
*/
public function testDeleteAllOption() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->registerMigration('1234', Version1Test::class);
- $this->configuration->registerMigration('1235', Version1Test::class);
- $this->configuration->registerMigration('1239', Version1Test::class);
- $this->configuration->registerMigration('1240', Version1Test::class);
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('1233'), $migrationClass);
- $this->configuration->getVersion('1233')->markMigrated();
- $this->configuration->getVersion('1234')->markMigrated();
+ $result = new ExecutionResult(new Version('1233'), Direction::UP);
+ $this->metadataStorage->complete($result);
- $commandTester = new CommandTester($this->command);
- $commandTester->execute(
+ $result = new ExecutionResult(new Version('1234'), Direction::UP);
+ $this->metadataStorage->complete($result);
+
+ $this->command->setHelperSet(new HelperSet([new QuestionHelper()]));
+ $this->commandTester->execute(
[
'--delete' => true,
'--all' => true,
@@ -230,11 +237,10 @@ public function testDeleteAllOption() : void
['interactive' => false]
);
- self::assertFalse($this->configuration->getVersion('1233')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1234')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1235')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1239')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1240')->isMigrated());
+ $executedMigrations = $this->metadataStorage->getExecutedMigrations();
+
+ self::assertFalse($executedMigrations->hasMigration(new Version('1233')));
+ self::assertFalse($executedMigrations->hasMigration(new Version('1234')));
}
/**
@@ -242,14 +248,12 @@ public function testDeleteAllOption() : void
*/
public function testAddOption() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->registerMigration('1234', Version1Test::class);
- $this->configuration->registerMigration('1235', Version1Test::class);
+ $migrationClass = $this->createMock(AbstractMigration::class);
- $this->configuration->getVersion('1233')->markMigrated();
+ $this->migrationRepository->registerMigrationInstance(new Version('1232'), $migrationClass);
+ $this->migrationRepository->registerMigrationInstance(new Version('1234'), $migrationClass);
- $commandTester = new CommandTester($this->command);
- $commandTester->execute(
+ $this->commandTester->execute(
[
'--add' => true,
'version' => '1234',
@@ -257,9 +261,10 @@ public function testAddOption() : void
['interactive' => false]
);
- self::assertTrue($this->configuration->getVersion('1233')->isMigrated());
- self::assertTrue($this->configuration->getVersion('1234')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1235')->isMigrated());
+ $executedMigrations = $this->metadataStorage->getExecutedMigrations();
+
+ self::assertFalse($executedMigrations->hasMigration(new Version('1232')));
+ self::assertTrue($executedMigrations->hasMigration(new Version('1234')));
}
/**
@@ -267,14 +272,17 @@ public function testAddOption() : void
*/
public function testDeleteOption() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->registerMigration('1234', Version1Test::class);
- $this->configuration->registerMigration('1235', Version1Test::class);
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('1233'), $migrationClass);
+ $this->migrationRepository->registerMigrationInstance(new Version('1234'), $migrationClass);
- $this->configuration->getVersion('1234')->markMigrated();
+ $result = new ExecutionResult(new Version('1233'), Direction::UP);
+ $this->metadataStorage->complete($result);
- $commandTester = new CommandTester($this->command);
- $commandTester->execute(
+ $result = new ExecutionResult(new Version('1234'), Direction::UP);
+ $this->metadataStorage->complete($result);
+
+ $this->commandTester->execute(
[
'--delete' => true,
'version' => '1234',
@@ -282,9 +290,10 @@ public function testDeleteOption() : void
['interactive' => false]
);
- self::assertFalse($this->configuration->getVersion('1233')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1234')->isMigrated());
- self::assertFalse($this->configuration->getVersion('1235')->isMigrated());
+ $executedMigrations = $this->metadataStorage->getExecutedMigrations();
+
+ self::assertFalse($executedMigrations->hasMigration(new Version('1234')));
+ self::assertTrue($executedMigrations->hasMigration(new Version('1233')));
}
/**
@@ -292,15 +301,18 @@ public function testDeleteOption() : void
*/
public function testAddOptionIfVersionAlreadyMigrated() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->getVersion('1233')->markMigrated();
-
- $commandTester = new CommandTester($this->command);
-
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The version "1233" already exists in the version table.');
- $commandTester->execute(
+ $migrationClass = $this->createMock(AbstractMigration::class);
+
+ $this->migrationRepository->registerMigrationInstance(new Version('1233'), $migrationClass);
+ $this->migrationRepository->registerMigrationInstance(new Version('1234'), $migrationClass);
+
+ $result = new ExecutionResult(new Version('1233'), Direction::UP);
+ $this->metadataStorage->complete($result);
+
+ $this->commandTester->execute(
[
'--add' => true,
'version' => '1233',
@@ -314,14 +326,13 @@ public function testAddOptionIfVersionAlreadyMigrated() : void
*/
public function testDeleteOptionIfVersionNotMigrated() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
-
- $commandTester = new CommandTester($this->command);
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('1233'), $migrationClass);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The version "1233" does not exist in the version table.');
- $commandTester->execute(
+ $this->commandTester->execute(
[
'--delete' => true,
'version' => '1233',
@@ -335,16 +346,12 @@ public function testDeleteOptionIfVersionNotMigrated() : void
*/
public function testDeleteOptionIfVersionFileDoesNotExist() : void
{
- $this->configuration->registerMigration('1233', Version1Test::class);
- $this->configuration->getVersion('1233')->markMigrated();
-
- $this->configuration->getDependencyFactory()->getMigrationRepository()->clearVersions();
+ $result = new ExecutionResult(new Version('1233'), Direction::UP);
+ $this->metadataStorage->complete($result);
$this->command->setHelperSet(new HelperSet([new QuestionHelper()]));
- $commandTester = new CommandTester($this->command);
-
- $commandTester->execute(
+ $this->commandTester->execute(
[
'--delete' => true,
'version' => '1233',
@@ -352,6 +359,6 @@ public function testDeleteOptionIfVersionFileDoesNotExist() : void
['interactive' => false]
);
- self::assertContains('1233 deleted from the version table.', $commandTester->getDisplay());
+ self::assertContains('1233 deleted from the version table.', $this->commandTester->getDisplay(true));
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/RollupCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/RollupCommandTest.php
index f448453ba2..3b4f766cdd 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/RollupCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/RollupCommandTest.php
@@ -21,7 +21,7 @@ final class RollupCommandTest extends TestCase
/** @var Rollup|MockObject */
private $rollup;
- /** @var RollupCommand|MockObject */
+ /** @var RollupCommand */
private $rollupCommand;
public function testExecute() : void
@@ -29,14 +29,9 @@ public function testExecute() : void
$input = $this->createMock(InputInterface::class);
$output = $this->createMock(OutputInterface::class);
- $version = $this->createMock(Version::class);
- $version->expects(self::once())
- ->method('getVersion')
- ->willReturn('1234');
-
$this->rollup->expects(self::once())
->method('rollup')
- ->willReturn($version);
+ ->willReturn(new Version('1234'));
$output->expects(self::once())
->method('writeln')
@@ -50,12 +45,11 @@ protected function setUp() : void
$this->rollup = $this->createMock(Rollup::class);
$this->dependencyFactory = $this->createMock(DependencyFactory::class);
- $this->dependencyFactory->expects(self::any())
+ $this->dependencyFactory
+ ->expects(self::once())
->method('getRollup')
->willReturn($this->rollup);
- $this->rollupCommand = $this->createPartialMock(RollupCommand::class, []);
-
- $this->rollupCommand->setDependencyFactory($this->dependencyFactory);
+ $this->rollupCommand = new RollupCommand(null, $this->dependencyFactory);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php
index 7ffeaa3dc7..b921dc3f4d 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php
@@ -8,152 +8,172 @@
use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\MigrationRepository;
+use Doctrine\Migrations\Tests\MigrationTestCase;
use Doctrine\Migrations\Tools\Console\Command\StatusCommand;
-use Doctrine\Migrations\Tools\Console\Helper\MigrationStatusInfosHelper;
+use Doctrine\Migrations\Version\Direction;
+use Doctrine\Migrations\Version\ExecutionResult;
use Doctrine\Migrations\Version\Version;
-use PHPUnit\Framework\MockObject\MockObject;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-class StatusCommandTest extends TestCase
+use Symfony\Component\Console\Tester\CommandTester;
+use function array_map;
+use function explode;
+use function sprintf;
+use function str_pad;
+use function strlen;
+use function sys_get_temp_dir;
+use function trim;
+
+class StatusCommandTest extends MigrationTestCase
{
- /** @var Configuration|MockObject */
- private $configuration;
-
- /** @var DependencyFactory|MockObject */
- private $dependencyFactory;
+ /** @var StatusCommand */
+ private $command;
- /** @var MigrationRepository|MockObject */
+ /** @var MigrationRepository */
private $migrationRepository;
- /** @var MigrationStatusInfosHelper|MockObject */
- private $migrationStatusInfosHelper;
+ /** @var MetadataStorage */
+ private $metadataStorage;
- /** @var StatusCommand */
- private $statusCommand;
+ /** @var CommandTester */
+ private $commandTester;
- public function testExecute() : void
+ protected function setUp() : void
{
- $input = $this->createMock(InputInterface::class);
- $output = $this->createMock(OutputInterface::class);
-
- $this->migrationStatusInfosHelper->expects(self::once())
- ->method('getMigrationsInfos')
- ->willReturn(['name' => 'value']);
-
- $input->expects(self::once())
- ->method('getOption')
- ->with('show-versions')
- ->willReturn(true);
-
- $version1 = $this->createMock(Version::class);
- $migration1 = $this->createMock(AbstractMigration::class);
-
- $version1->expects(self::once())
- ->method('getVersion')
- ->willReturn('1');
-
- $version1->expects(self::once())
- ->method('getMigration')
- ->willReturn($migration1);
-
- $version1->expects(self::once())
- ->method('isMigrated')
- ->willReturn(true);
-
- $executedAt = new DateTimeImmutable('2018-05-16 11:14:40');
-
- $version1->expects(self::once())
- ->method('getExecutedAt')
- ->willReturn($executedAt);
-
- $migration1->expects(self::once())
- ->method('getDescription')
- ->willReturn('Test description.');
-
- $version2 = $this->createMock(Version::class);
- $migration2 = $this->createMock(AbstractMigration::class);
+ $configuration = new Configuration();
+ $configuration->setMetadataStorageConfiguration(new TableMetadataStorageConfiguration());
+ $configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir());
- $version2->expects(self::once())
- ->method('getVersion')
- ->willReturn('2');
+ $conn = $this->getSqliteConnection();
- $version2->expects(self::once())
- ->method('getMigration')
- ->willReturn($migration2);
+ $dependencyFactory = new DependencyFactory($configuration, $conn);
- $version2->expects(self::once())
- ->method('isMigrated')
- ->willReturn(false);
+ $this->migrationRepository = $dependencyFactory->getMigrationRepository();
+ $this->metadataStorage = $dependencyFactory->getMetadataStorage();
- $version2->expects(self::once())
- ->method('getExecutedAt')
- ->willReturn(null);
-
- $migration2->expects(self::once())
- ->method('getDescription')
- ->willReturn('Test description.');
-
- $this->migrationRepository->expects(self::once())
- ->method('getMigrations')
- ->willReturn([$version1, $version2]);
-
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['1234']);
-
- $this->configuration->expects(self::at(0))
- ->method('getDateTime')
- ->with('1234')
- ->willReturn('123456789');
-
- $output->expects(self::at(0))
- ->method('writeln')
- ->with("\n == Configuration\n");
-
- $output->expects(self::at(1))
- ->method('writeln')
- ->with(' >> name: value');
-
- $output->expects(self::at(2))
- ->method('writeln')
- ->with("\n == Available Migration Versions\n");
-
- $output->expects(self::at(3))
- ->method('writeln')
- ->with(' >> (1) migrated (executed at 2018-05-16 11:14:40) Test description.');
-
- $output->expects(self::at(4))
- ->method('writeln')
- ->with(' >> (2) not migrated Test description.');
-
- $output->expects(self::at(5))
- ->method('writeln')
- ->with("\n == Previously Executed Unavailable Migration Versions\n");
-
- $output->expects(self::at(6))
- ->method('writeln')
- ->with(' >> 123456789 (1234)');
+ $this->command = new StatusCommand(null, $dependencyFactory);
+ $this->commandTester = new CommandTester($this->command);
+ }
- $this->statusCommand->execute($input, $output);
+ public function testExecute() : void
+ {
+ $result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-01 02:03:04'));
+ $result->setTime(10);
+ $this->metadataStorage->complete($result);
+
+ $result = new ExecutionResult(new Version('1233'), Direction::UP);
+ $this->metadataStorage->complete($result);
+
+ $this->commandTester->execute(
+ [],
+ ['interactive' => false]
+ );
+
+ $lines = array_map('trim', explode("\n", trim($this->commandTester->getDisplay(true))));
+
+ $tempDir = sys_get_temp_dir();
+ $tempDir = str_pad($tempDir, 74-strlen($tempDir));
+
+ self::assertSame(
+ [
+ 0 => '+----------------------+----------------------+------------------------------------------------------------------------+',
+ 1 => '| Configuration |',
+ 2 => '+----------------------+----------------------+------------------------------------------------------------------------+',
+ 3 => '| Project | Doctrine Database Migrations |',
+ 4 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 5 => '| Project | Doctrine Database Migrations |',
+ 6 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 7 => '| Storage | Type | Doctrine\\Migrations\\Metadata\\Storage\\TableMetadataStorageConfiguration |',
+ 8 => '| | Table Name | doctrine_migration_versions |',
+ 9 => '| | Column Name | version |',
+ 10 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 11 => '| Database | Driver | pdo_sqlite |',
+ 12 => '| | Host | |',
+ 13 => '| | Name | |',
+ 14 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 15 => '| Versions | Previous | 1230 |',
+ 16 => '| | Current | 1233 |',
+ 17 => '| | Next | Already at latest version |',
+ 18 => '| | Latest | |',
+ 19 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 20 => '| Migrations | Executed | 2 |',
+ 21 => '| | Executed Unavailable | 2 |',
+ 22 => '| | Available | 0 |',
+ 23 => '| | New | 0 |',
+ 24 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 25 => sprintf('| Migration Namespaces | DoctrineMigrations | %s |', str_pad(sys_get_temp_dir(), 70)),
+ 26 => '+----------------------+----------------------+------------------------------------------------------------------------+',
+ ],
+ $lines
+ );
}
- protected function setUp() : void
+ public function testExecuteDetails() : void
{
- $this->configuration = $this->createMock(Configuration::class);
- $this->dependencyFactory = $this->createMock(DependencyFactory::class);
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
- $this->migrationStatusInfosHelper = $this->createMock(MigrationStatusInfosHelper::class);
-
- $this->dependencyFactory->expects(self::once())
- ->method('getMigrationStatusInfosHelper')
- ->willReturn($this->migrationStatusInfosHelper);
-
- $this->statusCommand = new StatusCommand();
- $this->statusCommand->setMigrationConfiguration($this->configuration);
- $this->statusCommand->setDependencyFactory($this->dependencyFactory);
- $this->statusCommand->setMigrationRepository($this->migrationRepository);
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ $this->migrationRepository->registerMigrationInstance(new Version('1231'), $migrationClass);
+ $this->migrationRepository->registerMigrationInstance(new Version('1230'), $migrationClass);
+
+ $result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-01 02:03:04'));
+ $result->setTime(10);
+ $this->metadataStorage->complete($result);
+
+ $result = new ExecutionResult(new Version('1233'), Direction::UP);
+ $this->metadataStorage->complete($result);
+
+ $this->commandTester->execute(
+ ['--show-versions' => true],
+ ['interactive' => false]
+ );
+
+ $lines = array_map('trim', explode("\n", trim($this->commandTester->getDisplay(true))));
+ self::assertSame(
+ [
+ 0 => '+----------------------+----------------------+------------------------------------------------------------------------+',
+ 1 => '| Configuration |',
+ 2 => '+----------------------+----------------------+------------------------------------------------------------------------+',
+ 3 => '| Project | Doctrine Database Migrations |',
+ 4 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 5 => '| Project | Doctrine Database Migrations |',
+ 6 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 7 => '| Storage | Type | Doctrine\\Migrations\\Metadata\\Storage\\TableMetadataStorageConfiguration |',
+ 8 => '| | Table Name | doctrine_migration_versions |',
+ 9 => '| | Column Name | version |',
+ 10 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 11 => '| Database | Driver | pdo_sqlite |',
+ 12 => '| | Host | |',
+ 13 => '| | Name | |',
+ 14 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 15 => '| Versions | Previous | 1230 |',
+ 16 => '| | Current | 1233 |',
+ 17 => '| | Next | 1231 |',
+ 18 => '| | Latest | 1231 |',
+ 19 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 20 => '| Migrations | Executed | 2 |',
+ 21 => '| | Executed Unavailable | 1 |',
+ 22 => '| | Available | 2 |',
+ 23 => '| | New | 1 |',
+ 24 => '|----------------------------------------------------------------------------------------------------------------------|',
+ 25 => sprintf('| Migration Namespaces | DoctrineMigrations | %s |', str_pad(sys_get_temp_dir(), 70)),
+ 26 => '+----------------------+----------------------+------------------------------------------------------------------------+',
+ 27 => '+-----------+--------------+---------------------+-------------+',
+ 28 => '| Available Migration Versions |',
+ 29 => '+-----------+--------------+---------------------+-------------+',
+ 30 => '| Migration | Migrated | Migrated At | Description |',
+ 31 => '+-----------+--------------+---------------------+-------------+',
+ 32 => '| 1230 | migrated | 2010-01-01 02:03:04 | |',
+ 33 => '| 1231 | not migrated | | |',
+ 34 => '+-----------+--------------+---------------------+-------------+',
+ 35 => '+---------------------------+---------------------------+',
+ 36 => '| Previously Executed Unavailable Migration Versions |',
+ 37 => '+---------------------------+---------------------------+',
+ 38 => '| Migration | Migrated At |',
+ 39 => '+---------------------------+---------------------------+',
+ 40 => '| 1233 | |',
+ 41 => '+---------------------------+---------------------------+',
+ ],
+ $lines
+ );
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/UpToDateCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/UpToDateCommandTest.php
index 60bdd14238..fbaf60f40a 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/UpToDateCommandTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/UpToDateCommandTest.php
@@ -4,59 +4,75 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Command;
+use Doctrine\Migrations\AbstractMigration;
+use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\DependencyFactory;
+use Doctrine\Migrations\Exception\MigrationException;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\MigrationRepository;
+use Doctrine\Migrations\Tests\MigrationTestCase;
use Doctrine\Migrations\Tools\Console\Command\UpToDateCommand;
+use Doctrine\Migrations\Version\Direction;
+use Doctrine\Migrations\Version\ExecutionResult;
use Doctrine\Migrations\Version\Version;
-use PHPUnit\Framework\MockObject\MockObject;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Tester\CommandTester;
+use function sys_get_temp_dir;
-class UpToDateCommandTest extends TestCase
+class UpToDateCommandTest extends MigrationTestCase
{
- /** @var MigrationRepository|MockObject */
+ /** @var MigrationRepository */
private $migrationRepository;
+ /** @var MetadataStorage */
+ private $metadataStorage;
+
+ /** @var CommandTester */
+ private $commandTester;
+
/** @var UpToDateCommand */
- private $upToDateCommand;
+ private $command;
protected function setUp() : void
{
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
+ $configuration = new Configuration();
+ $configuration->setMetadataStorageConfiguration(new TableMetadataStorageConfiguration());
+ $configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir());
+
+ $conn = $this->getSqliteConnection();
+
+ $dependencyFactory = new DependencyFactory($configuration, $conn);
+
+ $this->migrationRepository = $dependencyFactory->getMigrationRepository();
+ $this->metadataStorage = $dependencyFactory->getMetadataStorage();
- $this->upToDateCommand = new UpToDateCommand();
- $this->upToDateCommand->setMigrationRepository($this->migrationRepository);
+ $this->command = new UpToDateCommand(null, $dependencyFactory);
+ $this->commandTester = new CommandTester($this->command);
}
/**
- * @param Version[] $migrations
- * @param string[] $migratedVersions
+ * @param string[] $migrations
+ * @param string[] $migratedVersions
+ *
+ * @throws MigrationException
*
* @dataProvider dataIsUpToDate
*/
public function testIsUpToDate(array $migrations, array $migratedVersions, int $exitCode, bool $failOnUnregistered = false) : void
{
- $this->migrationRepository
- ->method('getMigrations')
- ->willReturn($migrations);
-
- $this->migrationRepository
- ->method('getMigratedVersions')
- ->willReturn($migratedVersions);
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ foreach ($migrations as $version) {
+ $this->migrationRepository->registerMigrationInstance(new Version($version), $migrationClass);
+ }
- $input = $this->createMock(InputInterface::class);
- $input->expects(self::any())
- ->method('getOption')
- ->with('fail-on-unregistered')
- ->willReturn($failOnUnregistered);
+ foreach ($migratedVersions as $version) {
+ $result = new ExecutionResult(new Version($version), Direction::UP);
+ $this->metadataStorage->complete($result);
+ }
- $output = $this->createMock(OutputInterface::class);
- $output->expects(self::once())
- ->method('writeln');
+ $this->commandTester->execute(['--fail-on-unregistered' => $failOnUnregistered]);
- $actual = $this->upToDateCommand->execute($input, $output);
-
- self::assertSame($exitCode, $actual);
+ self::assertSame($exitCode, $this->commandTester->getStatusCode());
}
/**
@@ -66,9 +82,7 @@ public function dataIsUpToDate() : array
{
return [
'up-to-date' => [
- [
- $this->createVersion('20160614015627'),
- ],
+ ['20160614015627'],
['20160614015627'],
0,
],
@@ -78,18 +92,16 @@ public function dataIsUpToDate() : array
0,
],
'one-migration-available' => [
- [
- $this->createVersion('20150614015627'),
- ],
+ ['20150614015627'],
[],
1,
],
'many-migrations-available' => [
[
- $this->createVersion('20110614015627'),
- $this->createVersion('20120614015627'),
- $this->createVersion('20130614015627'),
- $this->createVersion('20140614015627'),
+ '20110614015627',
+ '20120614015627',
+ '20130614015627',
+ '20140614015627',
],
['20110614015627'],
1,
@@ -107,14 +119,4 @@ public function dataIsUpToDate() : array
],
];
}
-
- private function createVersion(string $migration) : Version
- {
- $version = $this->createMock(Version::class);
-
- $version->method('getVersion')
- ->willReturn($migration);
-
- return $version;
- }
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/ConnectionLoaderTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/ConnectionLoaderTest.php
index 19e63b6888..fd85a01aa7 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/ConnectionLoaderTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/ConnectionLoaderTest.php
@@ -5,54 +5,127 @@
namespace Doctrine\Migrations\Tests\Tools\Console;
use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Configuration\Connection\ConnectionLoaderInterface;
-use Doctrine\Migrations\Configuration\Connection\Loader\ConnectionConfigurationChainLoader;
+use Doctrine\DBAL\Platforms\SqlitePlatform;
+use Doctrine\DBAL\Sharding\PoolingShardConnection;
+use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
+use Doctrine\Migrations\Configuration\Connection\Loader\Exception\InvalidConfiguration;
use Doctrine\Migrations\Tools\Console\ConnectionLoader;
-use PHPUnit\Framework\MockObject\MockObject;
+use Doctrine\Migrations\Tools\Console\Exception\ConnectionNotSpecified;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Helper\HelperSet;
-use Symfony\Component\Console\Input\InputInterface;
+use function chdir;
+use function getcwd;
class ConnectionLoaderTest extends TestCase
{
- /** @var Configuration|MockObject */
- private $configuration;
-
- /** @var ConnectionConfigurationChainLoader|MockObject */
- private $connectionConfigurationChainLoader;
-
/** @var ConnectionLoader */
private $connectionLoader;
- public function testGetConnection() : void
+ public function testGetConnectionFromArray() : void
+ {
+ $helperSet = $this->createMock(HelperSet::class);
+
+ $dir = getcwd() ?: '.';
+ chdir(__DIR__);
+ try {
+ $conn = $this->connectionLoader->getConnection('_files/sqlite-connection.php', null, $helperSet);
+ self::assertInstanceOf(SqlitePlatform::class, $conn->getDatabasePlatform());
+ } finally {
+ chdir($dir);
+ }
+ }
+
+ public function testGetConnectionFromArrayNotFound() : void
+ {
+ $this->expectException(ConnectionNotSpecified::class);
+ $helperSet = $this->createMock(HelperSet::class);
+
+ $dir = getcwd()?: '.';
+ chdir(__DIR__);
+ try {
+ $this->connectionLoader->getConnection(__DIR__ . '/_files/wrong.php', null, $helperSet);
+ } finally {
+ chdir($dir);
+ }
+ }
+
+ public function testGetConnectionFromArrayFromFallbackFile() : void
+ {
+ $helperSet = $this->createMock(HelperSet::class);
+
+ $dir = getcwd()?: '.';
+ chdir(__DIR__ . '/_files');
+ try {
+ $conn = $this->connectionLoader->getConnection(null, null, $helperSet);
+ self::assertInstanceOf(SqlitePlatform::class, $conn->getDatabasePlatform());
+ } finally {
+ chdir($dir);
+ }
+ }
+
+ public function testGetConnectionFromHelper() : void
{
- $input = $this->createMock(InputInterface::class);
- $helperSet = $this->createMock(HelperSet::class);
$connection = $this->createMock(Connection::class);
- $this->connectionConfigurationChainLoader->expects(self::once())
- ->method('chosen')
- ->wilLReturn($connection);
+ $helper = $this->createMock(ConnectionHelper::class);
+ $helper->expects(self::once())->method('getConnection')->willReturn($connection);
- self::assertSame($connection, $this->connectionLoader->getConnection($input, $helperSet));
+ $helperSet = new HelperSet();
+ $helperSet->set($helper, 'connection');
+
+ $dir = getcwd()?: '.';
+ chdir(__DIR__);
+ try {
+ self::assertSame($connection, $this->connectionLoader->getConnection(null, null, $helperSet));
+ } finally {
+ chdir($dir);
+ }
}
- protected function setUp() : void
+ public function testGetShardedConnectionNotSupported() : void
+ {
+ $this->expectException(InvalidConfiguration::class);
+ $this->expectExceptionMessage('The connection must implement shards configuration.');
+
+ $connection = $this->createMock(Connection::class);
+
+ $helper = $this->createMock(ConnectionHelper::class);
+ $helper->expects(self::once())->method('getConnection')->willReturn($connection);
+
+ $helperSet = new HelperSet();
+ $helperSet->set($helper, 'connection');
+
+ $dir = getcwd()?: '.';
+ chdir(__DIR__);
+ try {
+ self::assertSame($connection, $this->connectionLoader->getConnection(null, 'shardId', $helperSet));
+ } finally {
+ chdir($dir);
+ }
+ }
+
+ public function testGetShardedConnection() : void
{
- $this->configuration = $this->createMock(Configuration::class);
+ $connection = $this->createMock(PoolingShardConnection::class);
+ $connection->expects(self::once())->method('connect')->with('shardId');
- $this->connectionLoader = $this->getMockBuilder(ConnectionLoader::class)
- ->setConstructorArgs([$this->configuration])
- ->setMethods(['createConnectionConfigurationChainLoader'])
- ->getMock();
+ $helper = $this->createMock(ConnectionHelper::class);
+ $helper->expects(self::once())->method('getConnection')->willReturn($connection);
- $this->connectionConfigurationChainLoader = $this->createMock(
- ConnectionLoaderInterface::class
- );
+ $helperSet = new HelperSet();
+ $helperSet->set($helper, 'connection');
- $this->connectionLoader->expects(self::once())
- ->method('createConnectionConfigurationChainLoader')
- ->willReturn($this->connectionConfigurationChainLoader);
+ $dir = getcwd()?: '.';
+ chdir(__DIR__);
+ try {
+ self::assertSame($connection, $this->connectionLoader->getConnection(null, 'shardId', $helperSet));
+ } finally {
+ chdir($dir);
+ }
+ }
+
+ protected function setUp() : void
+ {
+ $this->connectionLoader = new ConnectionLoader();
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/ConfigurationHelperTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/ConfigurationHelperTest.php
index c775736414..a746681e01 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/ConfigurationHelperTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/ConfigurationHelperTest.php
@@ -4,9 +4,10 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Helper;
-use Doctrine\DBAL\Connection;
-use Doctrine\Migrations\Configuration\ArrayConfiguration;
-use Doctrine\Migrations\Configuration\JsonConfiguration;
+use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\Configuration\ConfigurationLoader;
+use Doctrine\Migrations\Configuration\Exception\UnknownLoader;
+use Doctrine\Migrations\Configuration\Loader\Loader;
use Doctrine\Migrations\Tests\MigrationTestCase;
use Doctrine\Migrations\Tools\Console\Helper\ConfigurationHelper;
use InvalidArgumentException;
@@ -14,110 +15,145 @@
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\StreamOutput;
-use function copy;
-use function trim;
-use function unlink;
+use function chdir;
+use function getcwd;
class ConfigurationHelperTest extends MigrationTestCase
{
- /** @var Connection */
- private $connection;
-
/** @var StreamOutput */
protected $output;
/** @var InputInterface|MockObject */
private $input;
- protected function setUp() : void
- {
- $this->connection = $this->getSqliteConnection();
+ /** @var MockObject */
+ private $loader;
- $this->output = $this->getOutputStream();
+ /** @var ConfigurationHelper */
+ private $configurationHelper;
+ protected function setUp() : void
+ {
$this->input = $this->getMockBuilder(ArrayInput::class)
->setConstructorArgs([[]])
->setMethods(['getOption'])
->getMock();
+
+ $this->loader = $this->createMock(ConfigurationLoader::class);
+ $this->configurationHelper = new ConfigurationHelper($this->loader);
}
/**
- * Used in other tests to see if xml or yaml or yml config files are loaded.
+ * Test that unsupported file type throws exception
*/
- protected function getConfigurationHelperLoadsASpecificFormat(
- string $baseFile,
- string $configFile
- ) : string {
- try {
- $file = 'tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/' . $baseFile;
- copy($file, $configFile);
+ public function testNoAvailableConfigGivesBackEmptyConfig() : void
+ {
+ $this->input->method('getOption')
+ ->with('configuration')
+ ->willReturn(null);
- $this->input->method('getOption')
- ->with('configuration')
- ->will(self::returnValue(null));
+ $confExpected = new Configuration();
- $configurationHelper = new ConfigurationHelper($this->getSqliteConnection());
- $configfileLoaded = $configurationHelper->getMigrationConfig($this->input);
+ $configLoader = $this->createMock(Loader::class);
- return trim($this->getOutputStreamContent($this->output));
+ $configLoader
+ ->expects(self::once())
+ ->method('load')
+ ->with([])
+ ->willReturn($confExpected);
+
+ $this->loader
+ ->expects(self::once())
+ ->method('getLoader')
+ ->with('array')
+ ->willReturn($configLoader);
+
+ $dir = getcwd()?: '.';
+ try {
+ chdir(__DIR__);
+ $this->configurationHelper->getConfiguration($this->input);
} finally {
- unlink($configFile); //i want to be really sure to cleanup this file
+ chdir($dir);
}
}
- public function testConfigurationHelperLoadsPhpArrayFormatFromCommandLine() : void
+ public function testConfigurationHelperFailsToLoadOtherFormat() : void
{
$this->input->method('getOption')
->with('configuration')
- ->will(self::returnValue(__DIR__ . '/files/config.php'));
+ ->will(self::returnValue('testconfig.wrong'));
+ $this->loader
+ ->expects(self::once())
+ ->method('getLoader')
+ ->with('wrong')
+ ->willThrowException(UnknownLoader::new('dummy'));
- $configurationHelper = new ConfigurationHelper($this->getSqliteConnection());
- $migrationConfig = $configurationHelper->getMigrationConfig($this->input);
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('Given config file type is not supported');
- self::assertInstanceOf(ArrayConfiguration::class, $migrationConfig);
- self::assertSame('DoctrineMigrationsTest', $migrationConfig->getMigrationsNamespace());
+ $dir = getcwd()?: '.';
+ try {
+ chdir(__DIR__);
+ $this->configurationHelper->getConfiguration($this->input);
+ } finally {
+ chdir($dir);
+ }
}
- public function testConfigurationHelperLoadsJsonFormatFromCommandLine() : void
+ public function testLoadsFile() : void
{
- $this->input->method('getOption')
- ->with('configuration')
- ->will(self::returnValue(__DIR__ . '/files/config.json'));
+ $confExpected = new Configuration();
+ $configLoader = $this->createMock(Loader::class);
- $configurationHelper = new ConfigurationHelper($this->getSqliteConnection());
- $migrationConfig = $configurationHelper->getMigrationConfig($this->input);
+ $configLoader
+ ->expects(self::once())
+ ->method('load')
+ ->with('config.php')
+ ->willReturn($confExpected);
- self::assertInstanceOf(JsonConfiguration::class, $migrationConfig);
- self::assertSame('DoctrineMigrationsTest', $migrationConfig->getMigrationsNamespace());
- }
+ $this->loader
+ ->expects(self::once())
+ ->method('getLoader')
+ ->with('php')
+ ->willReturn($configLoader);
- /**
- * Test that unsupported file type throws exception
- */
- public function testConfigurationHelperFailsToLoadOtherFormat() : void
- {
$this->input->method('getOption')
->with('configuration')
- ->will(self::returnValue('testconfig.wrong'));
-
- $configurationHelper = new ConfigurationHelper($this->getSqliteConnection());
+ ->will(self::returnValue('config.php'));
- $this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage('Given config file type is not supported');
+ $config = $this->configurationHelper->getConfiguration($this->input);
- $configurationHelper->getMigrationConfig($this->input);
+ self::assertSame($config, $confExpected);
}
- public function testConfigurationHelperWithoutConfigurationFromSetterAndWithoutOverrideFromCommandLineAndWithoutConfigInPath() : void
+ public function testLoadsDefaultFile() : void
{
- $this->input->method('getOption')
- ->with('configuration')
- ->will(self::returnValue(null));
+ $confExpected = new Configuration();
+ $configLoader = $this->createMock(Loader::class);
+
+ $configLoader
+ ->expects(self::once())
+ ->method('load')
+ ->with('migrations.php')
+ ->willReturn($confExpected);
- $configurationHelper = new ConfigurationHelper($this->connection, null);
+ $this->loader
+ ->expects(self::once())
+ ->method('getLoader')
+ ->with('php')
+ ->willReturn($configLoader);
- $migrationConfig = $configurationHelper->getMigrationConfig($this->input);
+ $this->input->method('getOption')
+ ->with('configuration')
+ ->willReturn(null);
- self::assertStringMatchesFormat('', $this->getOutputStreamContent($this->output));
+ $dir = getcwd()?: '.';
+ try {
+ chdir(__DIR__ . '/files');
+ $config = $this->configurationHelper->getConfiguration($this->input);
+ } finally {
+ chdir($dir);
+ }
+ self::assertSame($config, $confExpected);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/MigrationDirectoryHelperTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/MigrationDirectoryHelperTest.php
index 9599d8730e..321fc64279 100644
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/MigrationDirectoryHelperTest.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/MigrationDirectoryHelperTest.php
@@ -4,52 +4,84 @@
namespace Doctrine\Migrations\Tests\Tools\Console\Helper;
+use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\Tests\Helper;
use Doctrine\Migrations\Tests\MigrationTestCase;
use Doctrine\Migrations\Tools\Console\Helper\MigrationDirectoryHelper;
use InvalidArgumentException;
use const DIRECTORY_SEPARATOR;
use function date;
+use function mkdir;
+use function sys_get_temp_dir;
+use function tempnam;
+use function unlink;
class MigrationDirectoryHelperTest extends MigrationTestCase
{
- public function testMigrationDirectoryHelperReturnConfiguredDir() : void
+ /** @var MigrationDirectoryHelper */
+ private $mirationDirectoryHelper;
+
+ /** @var Configuration */
+ private $configuration;
+
+ /** @var string */
+ private $tempDir;
+
+ public function setUp() : void
+ {
+ $this->mirationDirectoryHelper = new MigrationDirectoryHelper();
+ $this->configuration = new Configuration();
+ $this->tempDir = tempnam(sys_get_temp_dir(), 'DoctrineMigrations-tests') ?: '/tmp';
+ @unlink($this->tempDir);
+ mkdir($this->tempDir);
+ $this->configuration->addMigrationsDirectory('DoctrineMigrations', $this->tempDir);
+ }
+
+ public function tearDown() : void
{
- $mirationDirectoryHelper = new MigrationDirectoryHelper($this->getSqliteConfiguration());
+ Helper::deleteDir($this->tempDir);
+ }
- self::assertSame($this->getSqliteConfiguration()->getMigrationsDirectory(), $mirationDirectoryHelper->getMigrationDirectory());
+ public function testMigrationDirectoryHelperReturnConfiguredDir() : void
+ {
+ foreach ($this->configuration->getMigrationDirectories() as $dir) {
+ $migrationDir = $this->mirationDirectoryHelper->getMigrationDirectory($this->configuration, $dir);
+ self::assertSame($dir, $migrationDir);
+ }
}
public function testMigrationDirectoryHelperReturnConfiguredDirWithYear() : void
{
- $configuration = $this->getSqliteConfiguration();
- $configuration->setMigrationsAreOrganizedByYear(true);
- $mirationDirectoryHelper = new MigrationDirectoryHelper($configuration);
+ $this->configuration->setMigrationsAreOrganizedByYear(true);
- $dir = $configuration->getMigrationsDirectory() . DIRECTORY_SEPARATOR . date('Y');
+ foreach ($this->configuration->getMigrationDirectories() as $dir) {
+ $migrationDir = $this->mirationDirectoryHelper->getMigrationDirectory($this->configuration, $dir);
+ $expectedDir = $dir . DIRECTORY_SEPARATOR . date('Y');
- self::assertSame($dir, $mirationDirectoryHelper->getMigrationDirectory());
+ self::assertSame($expectedDir, $migrationDir);
+ }
}
public function testMigrationDirectoryHelperReturnConfiguredDirWithYearAndMonth() : void
{
- $configuration = $this->getSqliteConfiguration();
- $configuration->setMigrationsAreOrganizedByYearAndMonth(true);
- $mirationDirectoryHelper = new MigrationDirectoryHelper($configuration);
+ $this->configuration->setMigrationsAreOrganizedByYearAndMonth(true);
- $dir = $configuration->getMigrationsDirectory() . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
+ foreach ($this->configuration->getMigrationDirectories() as $dir) {
+ $migrationDir = $this->mirationDirectoryHelper->getMigrationDirectory($this->configuration, $dir);
+ $expectedDir = $dir . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
- self::assertSame($dir, $mirationDirectoryHelper->getMigrationDirectory());
+ self::assertSame($expectedDir, $migrationDir);
+ }
}
public function testMigrationsDirectoryHelperWithFolderThatDoesNotExists() : void
{
- $dir = DIRECTORY_SEPARATOR . 'IDoNotExists';
- $configuration = $this->getSqliteConfiguration();
- $configuration->setMigrationsDirectory($dir);
- $mirationDirectoryHelper = new MigrationDirectoryHelper($configuration);
-
$this->expectException(InvalidArgumentException::class);
- $mirationDirectoryHelper->getMigrationDirectory();
+ $this->configuration->addMigrationsDirectory('DoctrineMigrations', '/non_exiting_folder');
+
+ foreach ($this->configuration->getMigrationDirectories() as $dir) {
+ $this->mirationDirectoryHelper->getMigrationDirectory($this->configuration, $dir);
+ }
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/MigrationStatusInfosHelperTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/MigrationStatusInfosHelperTest.php
deleted file mode 100644
index ee9d515775..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/MigrationStatusInfosHelperTest.php
+++ /dev/null
@@ -1,139 +0,0 @@
-driver->expects(self::once())
- ->method('getName')
- ->willReturn('pdo_mysql');
-
- $this->connection->expects(self::once())
- ->method('getHost')
- ->willReturn('localhost');
-
- $this->connection->expects(self::once())
- ->method('getDatabase')
- ->willReturn('dbname');
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsTableName')
- ->willReturn('table_name');
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsColumnName')
- ->willReturn('column_name');
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsNamespace')
- ->willReturn('Doctrine');
-
- $this->configuration->expects(self::once())
- ->method('getMigrationsDirectory')
- ->willReturn('/path/to/migrations');
-
- $this->configuration->expects(self::any())
- ->method('resolveVersionAlias')
- ->willReturn('001');
-
- $this->configuration->expects(self::any())
- ->method('getDateTime')
- ->willReturn('2017-09-01 01:01:01');
-
- $expected = [
- 'Name' => 'Doctrine Database Migrations',
- 'Database Driver' => 'pdo_mysql',
- 'Database Host' => 'localhost',
- 'Database Name' => 'dbname',
- 'Configuration Source' => 'manually configured',
- 'Version Table Name' => 'table_name',
- 'Version Column Name' => 'column_name',
- 'Migrations Namespace' => 'Doctrine',
- 'Migrations Directory' => '/path/to/migrations',
- 'Previous Version' => '2017-09-01 01:01:01 (001)',
- 'Current Version' => '2017-09-01 01:01:01 (001)',
- 'Next Version' => '2017-09-01 01:01:01 (001)',
- 'Latest Version' => '2017-09-01 01:01:01 (001)',
- 'Executed Migrations' => 3,
- 'Executed Unavailable Migrations' => 1,
- 'Available Migrations' => 3,
- 'New Migrations' => 1,
- ];
-
- $infos = $this->migrationStatusInfosHelper->getMigrationsInfos();
-
- self::assertSame($expected, $infos);
- }
-
- protected function setUp() : void
- {
- $this->configuration = $this->createMock(Configuration::class);
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
- $this->connection = $this->createMock(Connection::class);
- $this->driver = $this->createMock(Driver::class);
-
- $this->configuration->expects(self::any())
- ->method('getConnection')
- ->willReturn($this->connection);
-
- $this->connection->expects(self::any())
- ->method('getDriver')
- ->willReturn($this->driver);
-
- $this->migrationRepository->expects(self::once())
- ->method('getMigratedVersions')
- ->willReturn([
- '001',
- '002',
- '003',
- ]);
-
- $this->migrationRepository->expects(self::once())
- ->method('getAvailableVersions')
- ->willReturn([
- '001',
- '002',
- '004',
- ]);
-
- $this->migrationRepository->expects(self::once())
- ->method('getNewVersions')
- ->willReturn(['004']);
-
- $this->migrationRepository->expects(self::once())
- ->method('getExecutedUnavailableMigrations')
- ->willReturn(['001']);
-
- $this->migrationStatusInfosHelper = new MigrationStatusInfosHelper(
- $this->configuration,
- $this->migrationRepository
- );
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.json b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.json
deleted file mode 100644
index 6619af8f66..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "name": "Doctrine Sandbox Migrations",
- "migrations_namespace": "DoctrineMigrationsTest",
- "table_name": "doctrine_migration_versions_test",
- "migrations_directory": "tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files"
-}
-
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.xml b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.xml
deleted file mode 100644
index 79f290c037..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
- Doctrine Sandbox Migrations
- DoctrineMigrationsTest
-
- tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files
-
-
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.yml b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.yml
deleted file mode 100644
index b24060f158..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/config.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-name: Doctrine Sandbox Migrations
-migrations_namespace: DoctrineMigrationsTest
-table_name: doctrine_migration_versions_test
-migrations_directory: tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files
diff --git a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/migrations.php
similarity index 71%
rename from tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.php
rename to tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/migrations.php
index 7a2495bae5..bea97cb84c 100644
--- a/tests/Doctrine/Migrations/Tests/Configuration/_files/config_order_2.php
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files/migrations.php
@@ -4,8 +4,7 @@
return [
'name' => 'Doctrine Sandbox Migrations',
- 'migrations_directory' => '.',
'migrations_namespace' => 'DoctrineMigrationsTest',
'table_name' => 'doctrine_migration_versions_test',
- 'migrations' => [],
+ 'migrations_directory' => 'tests/Doctrine/Migrations/Tests/Tools/Console/Helper/files',
];
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/_files/migrations-db.php b/tests/Doctrine/Migrations/Tests/Tools/Console/_files/migrations-db.php
new file mode 100644
index 0000000000..dae54d0076
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/_files/migrations-db.php
@@ -0,0 +1,5 @@
+ 'pdo_sqlite', 'memory' => true];
diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/_files/sqlite-connection.php b/tests/Doctrine/Migrations/Tests/Tools/Console/_files/sqlite-connection.php
new file mode 100644
index 0000000000..dae54d0076
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/Tools/Console/_files/sqlite-connection.php
@@ -0,0 +1,5 @@
+ 'pdo_sqlite', 'memory' => true];
diff --git a/tests/Doctrine/Migrations/Tests/Tracking/TableDefinitionTest.php b/tests/Doctrine/Migrations/Tests/Tracking/TableDefinitionTest.php
deleted file mode 100644
index b7367076b9..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tracking/TableDefinitionTest.php
+++ /dev/null
@@ -1,126 +0,0 @@
-migrationTable->getName());
- }
-
- public function testGetColumnName() : void
- {
- self::assertSame('version_name', $this->migrationTable->getColumnName());
- }
-
- public function testGetColumnLength() : void
- {
- self::assertSame(200, $this->migrationTable->getColumnLength());
- }
-
- public function testGetExecutedAtColumnName() : void
- {
- self::assertSame('executed_datetime', $this->migrationTable->getExecutedAtColumnName());
- }
-
- public function testGetMigrationsColumn() : void
- {
- $column = $this->migrationTable->getMigrationsColumn();
-
- self::assertSame('version_name', $column->getName());
- self::assertSame(200, $column->getLength());
- }
-
- public function testGetExecutedAtColumn() : void
- {
- $column = $this->migrationTable->getExecutedAtColumn();
-
- self::assertSame('executed_datetime', $column->getName());
- self::assertTrue($column->getNotnull());
- }
-
- public function testGetColumnNames() : void
- {
- self::assertSame(['version_name', 'executed_datetime'], $this->migrationTable->getColumnNames());
- }
-
- public function testGetDBALTable() : void
- {
- $schemaConfig = $this->createMock(SchemaConfig::class);
-
- $this->schemaManager->expects(self::once())
- ->method('createSchemaConfig')
- ->willReturn($schemaConfig);
-
- $schemaConfig->expects(self::once())
- ->method('getDefaultTableOptions')
- ->willReturn(['test_option' => true]);
-
- $table = $this->migrationTable->getDBALTable();
-
- self::assertCount(2, $table->getColumns());
-
- self::assertTrue($table->hasOption('test_option'));
- self::assertTrue($table->getOption('test_option'));
-
- self::assertTrue($table->hasColumn('version_name'));
- self::assertTrue($table->getColumn('version_name')->getNotnull());
-
- self::assertTrue($table->hasColumn('executed_datetime'));
- self::assertFalse($table->getColumn('executed_datetime')->getNotnull());
- }
-
- public function testGetNewDBALTable() : void
- {
- $schemaConfig = $this->createMock(SchemaConfig::class);
-
- $this->schemaManager->expects(self::once())
- ->method('createSchemaConfig')
- ->willReturn($schemaConfig);
-
- $schemaConfig->expects(self::once())
- ->method('getDefaultTableOptions')
- ->willReturn(['test_option' => true]);
-
- $table = $this->migrationTable->getNewDBALTable();
-
- self::assertCount(2, $table->getColumns());
-
- self::assertTrue($table->hasOption('test_option'));
- self::assertTrue($table->getOption('test_option'));
-
- self::assertTrue($table->hasColumn('version_name'));
- self::assertTrue($table->getColumn('version_name')->getNotnull());
-
- self::assertTrue($table->hasColumn('executed_datetime'));
- self::assertTrue($table->getColumn('executed_datetime')->getNotnull());
- }
-
- protected function setUp() : void
- {
- $this->schemaManager = $this->createMock(AbstractSchemaManager::class);
-
- $this->migrationTable = new TableDefinition(
- $this->schemaManager,
- 'versions',
- 'version_name',
- 200,
- 'executed_datetime'
- );
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Tracking/TableManipulatorTest.php b/tests/Doctrine/Migrations/Tests/Tracking/TableManipulatorTest.php
deleted file mode 100644
index 95971e75de..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tracking/TableManipulatorTest.php
+++ /dev/null
@@ -1,137 +0,0 @@
-configuration->expects(self::once())
- ->method('validate');
-
- $this->configuration->expects(self::once())
- ->method('isDryRun')
- ->willReturn(false);
-
- $this->migrationTableStatus->expects(self::once())
- ->method('isCreated')
- ->willReturn(true);
-
- $this->migrationTableStatus->expects(self::once())
- ->method('isUpToDate')
- ->willReturn(true);
-
- self::assertFalse($this->migrationTableManipulator->createMigrationTable());
- }
-
- public function testCreateMigrationTableNotUpToDate() : void
- {
- $migrationTableManipulator = $this->getMockBuilder(TableManipulator::class)
- ->setConstructorArgs([
- $this->configuration,
- $this->schemaManager,
- $this->migrationTable,
- $this->migrationTableStatus,
- $this->migrationTableUpdater,
- ])
- ->setMethods(['createSchema'])
- ->getMock();
-
- $this->configuration->expects(self::once())
- ->method('validate');
-
- $this->configuration->expects(self::once())
- ->method('isDryRun')
- ->willReturn(false);
-
- $this->migrationTableStatus->expects(self::once())
- ->method('isCreated')
- ->willReturn(true);
-
- $this->migrationTableStatus->expects(self::once())
- ->method('isUpToDate')
- ->willReturn(false);
-
- $this->migrationTableUpdater->expects(self::once())
- ->method('updateMigrationTable');
-
- $this->migrationTableStatus->expects(self::once())
- ->method('setUpToDate')
- ->with(true);
-
- self::assertTrue($migrationTableManipulator->createMigrationTable());
- }
-
- public function testCreateMigrationTable() : void
- {
- $this->configuration->expects(self::once())
- ->method('validate');
-
- $this->configuration->expects(self::once())
- ->method('isDryRun')
- ->willReturn(false);
-
- $this->migrationTableStatus->expects(self::once())
- ->method('isCreated')
- ->willReturn(false);
-
- $table = $this->createMock(Table::class);
-
- $this->migrationTable->expects(self::once())
- ->method('getNewDBALTable')
- ->willReturn($table);
-
- $this->schemaManager->expects(self::once())
- ->method('createTable')
- ->with($table);
-
- self::assertTrue($this->migrationTableManipulator->createMigrationTable());
- }
-
- protected function setUp() : void
- {
- $this->configuration = $this->createMock(Configuration::class);
- $this->schemaManager = $this->createMock(AbstractSchemaManager::class);
- $this->migrationTable = $this->createMock(TableDefinition::class);
- $this->migrationTableStatus = $this->createMock(TableStatus::class);
- $this->migrationTableUpdater = $this->createMock(TableUpdater::class);
-
- $this->migrationTableManipulator = new TableManipulator(
- $this->configuration,
- $this->schemaManager,
- $this->migrationTable,
- $this->migrationTableStatus,
- $this->migrationTableUpdater
- );
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Tracking/TableStatusTest.php b/tests/Doctrine/Migrations/Tests/Tracking/TableStatusTest.php
deleted file mode 100644
index 67d393d92c..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tracking/TableStatusTest.php
+++ /dev/null
@@ -1,143 +0,0 @@
-migrationTableStatus->setCreated(true);
-
- self::assertTrue($this->migrationTableStatus->isCreated());
- }
-
- public function testIsCreatedTrue() : void
- {
- $this->migrationTable->expects(self::once())
- ->method('getName')
- ->willReturn('table_name');
-
- $this->schemaManager->expects(self::once())
- ->method('tablesExist')
- ->with(['table_name'])
- ->willReturn(true);
-
- self::assertTrue($this->migrationTableStatus->isCreated());
- }
-
- public function testIsCreatedFalse() : void
- {
- $this->migrationTable->expects(self::once())
- ->method('getName')
- ->willReturn('table_name');
-
- $this->schemaManager->expects(self::once())
- ->method('tablesExist')
- ->with(['table_name'])
- ->willReturn(false);
-
- self::assertFalse($this->migrationTableStatus->isCreated());
- }
-
- public function testSetUpToDate() : void
- {
- $this->migrationTableStatus->setUpToDate(true);
-
- self::assertTrue($this->migrationTableStatus->isUpToDate());
- }
-
- public function testIsUpToDateTrue() : void
- {
- $this->migrationTable->expects(self::once())
- ->method('getName')
- ->willReturn('table_name');
-
- $table = $this->createMock(Table::class);
-
- $this->schemaManager->expects(self::once())
- ->method('listTableDetails')
- ->with('table_name')
- ->willReturn($table);
-
- $this->migrationTable->expects(self::once())
- ->method('getColumnNames')
- ->willReturn([
- 'version',
- 'executed_at',
- ]);
-
- $table->expects(self::at(0))
- ->method('hasColumn')
- ->with('version')
- ->willReturn(true);
-
- $table->expects(self::at(1))
- ->method('hasColumn')
- ->with('executed_at')
- ->willReturn(true);
-
- self::assertTrue($this->migrationTableStatus->isUpToDate());
- }
-
- public function testIsUpToDateFalse() : void
- {
- $this->migrationTable->expects(self::once())
- ->method('getName')
- ->willReturn('table_name');
-
- $table = $this->createMock(Table::class);
-
- $this->schemaManager->expects(self::once())
- ->method('listTableDetails')
- ->with('table_name')
- ->willReturn($table);
-
- $this->migrationTable->expects(self::once())
- ->method('getColumnNames')
- ->willReturn([
- 'version',
- 'executed_at',
- ]);
-
- $table->expects(self::at(0))
- ->method('hasColumn')
- ->with('version')
- ->willReturn(true);
-
- $table->expects(self::at(1))
- ->method('hasColumn')
- ->with('executed_at')
- ->willReturn(false);
-
- self::assertFalse($this->migrationTableStatus->isUpToDate());
- }
-
- protected function setUp() : void
- {
- $this->schemaManager = $this->createMock(AbstractSchemaManager::class);
- $this->migrationTable = $this->createMock(TableDefinition::class);
-
- $this->migrationTableStatus = new TableStatus(
- $this->schemaManager,
- $this->migrationTable
- );
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Tracking/TableUpdaterTest.php b/tests/Doctrine/Migrations/Tests/Tracking/TableUpdaterTest.php
deleted file mode 100644
index 45467f8a10..0000000000
--- a/tests/Doctrine/Migrations/Tests/Tracking/TableUpdaterTest.php
+++ /dev/null
@@ -1,207 +0,0 @@
-migrationTable->expects(self::once())
- ->method('getName')
- ->willReturn('table_name');
-
- $this->migrationTable->expects(self::once())
- ->method('getColumnNames')
- ->willReturn([
- 'version',
- 'executed_at',
- ]);
-
- $table = $this->createMock(Table::class);
-
- $this->schemaManager->expects(self::once())
- ->method('listTableDetails')
- ->willReturn($table);
-
- $versionColumn = new Column(
- 'version',
- Type::getType('string'),
- ['length' => 255]
- );
-
- $executedAt = new Column(
- 'executed_at',
- Type::getType('datetime_immutable')
- );
-
- $this->migrationTable->expects(self::once())
- ->method('createDBALTable')
- ->with([
- $versionColumn,
- $executedAt,
- ])
- ->willReturn($table);
-
- $table->expects(self::any())
- ->method('getColumns')
- ->willReturn([
- $versionColumn,
- $executedAt,
- ]);
-
- $fromSchema = $this->createMock(Schema::class);
- $toSchema = $this->createMock(Schema::class);
-
- $this->migrationTableUpdater->expects(self::at(0))
- ->method('createSchema')
- ->willReturn($fromSchema);
-
- $this->migrationTableUpdater->expects(self::at(1))
- ->method('createSchema')
- ->willReturn($toSchema);
-
- $fromSchema->expects(self::once())
- ->method('getMigrateToSql')
- ->with($toSchema, $this->platform)
- ->willReturn(['ALTER TABLE table_name ADD COLUMN executed_at DATETIME DEFAULT NULL']);
-
- $this->connection->expects(self::once())
- ->method('beginTransaction');
-
- $this->connection->expects(self::once())
- ->method('executeQuery')
- ->with('ALTER TABLE table_name ADD COLUMN executed_at DATETIME DEFAULT NULL');
-
- $this->connection->expects(self::once())
- ->method('commit');
-
- $this->migrationTableUpdater->updateMigrationTable();
- }
-
- public function testUpdateMigrationTableRollback() : void
- {
- $this->expectException(Throwable::class);
- $this->expectExceptionMessage('Rolling back.');
-
- $this->migrationTable->expects(self::once())
- ->method('getName')
- ->willReturn('table_name');
-
- $this->migrationTable->expects(self::once())
- ->method('getColumnNames')
- ->willReturn([
- 'version',
- 'executed_at',
- ]);
-
- $table = $this->createMock(Table::class);
-
- $this->schemaManager->expects(self::once())
- ->method('listTableDetails')
- ->willReturn($table);
-
- $versionColumn = new Column(
- 'version',
- Type::getType('string'),
- ['length' => 255]
- );
-
- $executedAt = new Column(
- 'executed_at',
- Type::getType('datetime_immutable')
- );
-
- $this->migrationTable->expects(self::once())
- ->method('createDBALTable')
- ->with([
- $versionColumn,
- $executedAt,
- ])
- ->willReturn($table);
-
- $table->expects(self::any())
- ->method('getColumns')
- ->willReturn([
- $versionColumn,
- $executedAt,
- ]);
-
- $fromSchema = $this->createMock(Schema::class);
- $toSchema = $this->createMock(Schema::class);
-
- $this->migrationTableUpdater->expects(self::at(0))
- ->method('createSchema')
- ->willReturn($fromSchema);
-
- $this->migrationTableUpdater->expects(self::at(1))
- ->method('createSchema')
- ->willReturn($toSchema);
-
- $fromSchema->expects(self::once())
- ->method('getMigrateToSql')
- ->with($toSchema, $this->platform)
- ->willReturn(['ALTER TABLE table_name ADD COLUMN executed_at DATETIME DEFAULT NULL']);
-
- $this->connection->expects(self::once())
- ->method('beginTransaction');
-
- $this->connection->expects(self::once())
- ->method('executeQuery')
- ->with('ALTER TABLE table_name ADD COLUMN executed_at DATETIME DEFAULT NULL')
- ->willThrowException(new Exception('Rolling back.'));
-
- $this->connection->expects(self::once())
- ->method('rollback');
-
- $this->migrationTableUpdater->updateMigrationTable();
- }
-
- protected function setUp() : void
- {
- $this->connection = $this->createMock(Connection::class);
- $this->schemaManager = $this->createMock(AbstractSchemaManager::class);
- $this->migrationTable = $this->createMock(TableDefinition::class);
- $this->platform = $this->createMock(AbstractPlatform::class);
-
- $this->migrationTableUpdater = $this->getMockBuilder(TableUpdater::class)
- ->setConstructorArgs([
- $this->connection,
- $this->schemaManager,
- $this->migrationTable,
- $this->platform,
- ])
- ->setMethods(['createSchema'])
- ->getMock();
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/Version/AliasResolverTest.php b/tests/Doctrine/Migrations/Tests/Version/AliasResolverTest.php
index d2c105a135..c364315208 100644
--- a/tests/Doctrine/Migrations/Tests/Version/AliasResolverTest.php
+++ b/tests/Doctrine/Migrations/Tests/Version/AliasResolverTest.php
@@ -4,44 +4,102 @@
namespace Doctrine\Migrations\Tests\Version;
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\DriverManager;
+use Doctrine\Migrations\AbstractMigration;
+use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\Exception\NoMigrationsFoundWithCriteria;
+use Doctrine\Migrations\Exception\UnknownMigrationVersion;
+use Doctrine\Migrations\Finder\RecursiveRegexFinder;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorage;
+use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
+use Doctrine\Migrations\MigrationPlanCalculator;
use Doctrine\Migrations\MigrationRepository;
use Doctrine\Migrations\Version\AliasResolver;
-use PHPUnit\Framework\MockObject\MockObject;
+use Doctrine\Migrations\Version\Direction;
+use Doctrine\Migrations\Version\ExecutionResult;
+use Doctrine\Migrations\Version\MigrationFactory;
+use Doctrine\Migrations\Version\Version;
use PHPUnit\Framework\TestCase;
+use function sys_get_temp_dir;
final class AliasResolverTest extends TestCase
{
- /** @var MigrationRepository|MockObject */
+ /** @var MigrationRepository */
private $migrationRepository;
/** @var AliasResolver */
private $versionAliasResolver;
+ /** @var TableMetadataStorage */
+ private $metadataStorage;
+
+ /** @var MigrationPlanCalculator */
+ private $planCalculator;
+
/**
* @dataProvider getAliases
*/
- public function testResolveVersionAlias(
- string $alias,
- ?string $expectedVersion,
- ?string $expectedMethod,
- ?string $expectedArgument
- ) : void {
- $this->migrationRepository->expects(self::once())
- ->method('hasVersion')
- ->with($alias)
- ->willReturn(false);
-
- if ($expectedMethod !== null) {
- $expectation = $this->migrationRepository->expects(self::once())
- ->method($expectedMethod)
- ->willReturn($expectedVersion);
-
- if ($expectedArgument !== null) {
- $expectation->with($expectedArgument);
- }
+ public function testAliases(string $alias, ?string $expectedVersion, ?string $expectedException = null) : void
+ {
+ if ($expectedException !== null) {
+ $this->expectException($expectedException);
+ }
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ foreach (['A', 'B', 'C'] as $version) {
+ $this->migrationRepository->registerMigrationInstance(new Version($version), $migrationClass);
+ }
+
+ foreach (['A', 'B'] as $version) {
+ $result = new ExecutionResult(new Version($version), Direction::UP);
+ $this->metadataStorage->complete($result);
+ }
+
+ $resolvedAlias = $this->versionAliasResolver->resolveVersionAlias($alias);
+ if ($expectedVersion === null) {
+ return;
+ }
+
+ self::assertEquals(new Version($expectedVersion), $resolvedAlias);
+ }
+
+ /**
+ * @dataProvider getAliasesWithNoExecuted
+ */
+ public function testAliasesWithNoExecuted(string $alias, ?string $expectedVersion, ?string $expectedException = null) : void
+ {
+ if ($expectedException !== null) {
+ $this->expectException($expectedException);
}
- self::assertSame($expectedVersion, $this->versionAliasResolver->resolveVersionAlias($alias));
+ $migrationClass = $this->createMock(AbstractMigration::class);
+ foreach (['A', 'B', 'C'] as $version) {
+ $this->migrationRepository->registerMigrationInstance(new Version($version), $migrationClass);
+ }
+ $resolvedAlias = $this->versionAliasResolver->resolveVersionAlias($alias);
+ if ($expectedVersion === null) {
+ return;
+ }
+
+ self::assertEquals(new Version($expectedVersion), $resolvedAlias);
+ }
+
+ /**
+ * @return mixed[][]
+ */
+ public function getAliasesWithNoExecuted() : array
+ {
+ return [
+ ['first', 'A'],
+ ['current', '0'],
+ ['prev', '0'],
+ ['next', 'A'],
+ ['latest', 'C'],
+ ['current-1', null, NoMigrationsFoundWithCriteria::class],
+ ['current+1', 'A'],
+ ['B', 'B'],
+ ['X', null, UnknownMigrationVersion::class],
+ ];
}
/**
@@ -50,30 +108,47 @@ public function testResolveVersionAlias(
public function getAliases() : array
{
return [
- ['first', '0', null, null],
- ['current', '5', 'getCurrentVersion', null],
- ['prev', '4', 'getPrevVersion', null],
- ['next', '6', 'getNextVersion', null],
- ['latest', '7', 'getLatestVersion', null],
- ['current-5', '2', 'getDeltaVersion', -5],
- ['test-5', null, null, null],
+ ['first', 'A'],
+ ['current', 'B'],
+ ['prev', 'A'],
+ ['next', 'C'],
+ ['latest', 'C'],
+ ['current-1', 'A'],
+ ['current+1', 'C'],
+ ['B', 'B'],
+ ['X', null, UnknownMigrationVersion::class],
];
}
- public function testResolveVersionAliasHasVersion() : void
+ protected function setUp() : void
{
- $this->migrationRepository->expects(self::once())
- ->method('hasVersion')
- ->with('test')
- ->willReturn(true);
+ $configuration = new Configuration();
+ $configuration->setMetadataStorageConfiguration(new TableMetadataStorageConfiguration());
+ $configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir());
- self::assertSame('test', $this->versionAliasResolver->resolveVersionAlias('test'));
+ $conn = $this->getSqliteConnection();
+
+ $versionFactory = $this->createMock(MigrationFactory::class);
+
+ $this->migrationRepository = new MigrationRepository(
+ [],
+ [],
+ new RecursiveRegexFinder('#.*\\.php$#i'),
+ $versionFactory
+ );
+ $this->metadataStorage = new TableMetadataStorage($conn);
+ $this->planCalculator = new MigrationPlanCalculator($this->migrationRepository, $this->metadataStorage);
+ $this->versionAliasResolver = new AliasResolver(
+ $this->migrationRepository,
+ $this->metadataStorage,
+ $this->planCalculator
+ );
}
- protected function setUp() : void
+ private function getSqliteConnection() : Connection
{
- $this->migrationRepository = $this->createMock(MigrationRepository::class);
+ $params = ['driver' => 'pdo_sqlite', 'memory' => true];
- $this->versionAliasResolver = new AliasResolver($this->migrationRepository);
+ return DriverManager::getConnection($params);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Version/ExecutionResultTest.php b/tests/Doctrine/Migrations/Tests/Version/ExecutionResultTest.php
index af66b92494..a651207412 100644
--- a/tests/Doctrine/Migrations/Tests/Version/ExecutionResultTest.php
+++ b/tests/Doctrine/Migrations/Tests/Version/ExecutionResultTest.php
@@ -4,8 +4,11 @@
namespace Doctrine\Migrations\Tests\Version;
+use DateTimeImmutable;
use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\Version\Direction;
use Doctrine\Migrations\Version\ExecutionResult;
+use Doctrine\Migrations\Version\Version;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use RuntimeException;
@@ -24,26 +27,10 @@ public function testGetSetSql() : void
{
self::assertSame(['SELECT 1'], $this->versionExecutionResult->getSql());
- $this->versionExecutionResult->setSql(['SELECT 2']);
+ $this->versionExecutionResult->setSql(['SELECT 2'], [2], [3]);
self::assertSame(['SELECT 2'], $this->versionExecutionResult->getSql());
- }
-
- public function testGetSetParams() : void
- {
- self::assertSame([1], $this->versionExecutionResult->getParams());
-
- $this->versionExecutionResult->setParams([2]);
-
self::assertSame([2], $this->versionExecutionResult->getParams());
- }
-
- public function testGetTypes() : void
- {
- self::assertSame([2], $this->versionExecutionResult->getTypes());
-
- $this->versionExecutionResult->setTypes([3]);
-
self::assertSame([3], $this->versionExecutionResult->getTypes());
}
@@ -88,11 +75,24 @@ public function testExceptionNull() : void
self::assertNull($this->versionExecutionResult->getException());
}
+ public function testExecutedAt() : void
+ {
+ $date = new DateTimeImmutable();
+ $this->versionExecutionResult->setExecutedAt($date);
+
+ self::assertSame($date, $this->versionExecutionResult->getExecutedAt());
+ }
+
+ public function testGetVersion() : void
+ {
+ self::assertSame('foo', (string) $this->versionExecutionResult->getVersion());
+ }
+
public function testException() : void
{
$exception = new InvalidArgumentException();
- $this->versionExecutionResult->setException($exception);
+ $this->versionExecutionResult->setError(true, $exception);
self::assertSame($exception, $this->versionExecutionResult->getException());
}
@@ -117,6 +117,10 @@ public function testToSchemaThrowsRuntimExceptionWhenToSchemaIsNull() : void
protected function setUp() : void
{
$this->versionExecutionResult = new ExecutionResult(
+ new Version('foo'),
+ Direction::UP
+ );
+ $this->versionExecutionResult->setSql(
['SELECT 1'],
[1],
[2]
diff --git a/tests/Doctrine/Migrations/Tests/Version/ExecutorTest.php b/tests/Doctrine/Migrations/Tests/Version/ExecutorTest.php
index de4fd93969..1c5de212f9 100644
--- a/tests/Doctrine/Migrations/Tests/Version/ExecutorTest.php
+++ b/tests/Doctrine/Migrations/Tests/Version/ExecutorTest.php
@@ -4,39 +4,39 @@
namespace Doctrine\Migrations\Tests\Version;
+use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;
-use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-use Doctrine\Migrations\Configuration\Configuration;
+use Doctrine\Migrations\EventDispatcher;
+use Doctrine\Migrations\Events;
+use Doctrine\Migrations\Metadata\MigrationPlan;
+use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\MigratorConfiguration;
-use Doctrine\Migrations\OutputWriter;
-use Doctrine\Migrations\ParameterFormatter;
use Doctrine\Migrations\ParameterFormatterInterface;
-use Doctrine\Migrations\Provider\SchemaDiffProviderInterface;
+use Doctrine\Migrations\Provider\SchemaDiffProvider;
use Doctrine\Migrations\Stopwatch;
+use Doctrine\Migrations\Tests\TestLogger;
use Doctrine\Migrations\Version\Direction;
+use Doctrine\Migrations\Version\ExecutionResult;
use Doctrine\Migrations\Version\Executor;
+use Doctrine\Migrations\Version\State;
use Doctrine\Migrations\Version\Version;
+use Exception;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Stopwatch\StopwatchEvent;
+use Throwable;
class ExecutorTest extends TestCase
{
- /** @var Configuration|MockObject */
- private $configuration;
-
/** @var Connection|MockObject */
private $connection;
- /** @var SchemaDiffProviderInterface|MockObject */
+ /** @var SchemaDiffProvider|MockObject */
private $schemaDiffProvider;
- /** @var OutputWriter|MockObject */
- private $outputWriter;
-
- /** @var ParameterFormatter|MockObject */
+ /** @var ParameterFormatterInterface|MockObject */
private $parameterFormatter;
/** @var Stopwatch|MockObject */
@@ -51,6 +51,18 @@ class ExecutorTest extends TestCase
/** @var VersionExecutorTestMigration */
private $migration;
+ /** @var TestLogger */
+ private $logger;
+
+ /** @var EventDispatcher */
+ private $eventDispatcher;
+
+ /** @var EventManager */
+ private $eventManager;
+
+ /** @var MockObject */
+ private $metadataStorage;
+
public function testAddSql() : void
{
$this->versionExecutor->addSql('SELECT 1', [1], [2]);
@@ -62,172 +74,401 @@ public function testAddSql() : void
public function testExecuteUp() : void
{
- $this->outputWriter->expects(self::at(0))
- ->method('write')
- ->with("\n ++ migrating 001\n");
-
- $this->outputWriter->expects(self::at(1))
- ->method('write')
- ->with(' -> SELECT 1');
-
- $this->outputWriter->expects(self::at(2))
- ->method('write')
- ->with(' 100ms');
-
- $this->outputWriter->expects(self::at(3))
- ->method('write')
- ->with(' -> SELECT 2');
-
- $this->outputWriter->expects(self::at(4))
- ->method('write')
- ->with(' 100ms');
-
- $this->outputWriter->expects(self::at(5))
- ->method('write')
- ->with("\n ++ migrated (took 100ms, used 100 memory)");
+ $this->metadataStorage
+ ->expects(self::once())
+ ->method('complete')->willReturnCallback(static function (ExecutionResult $result) : void {
+ self::assertSame(Direction::UP, $result->getDirection());
+ self::assertNotNull($result->getTime());
+ self::assertNotNull($result->getExecutedAt());
+ });
$migratorConfiguration = (new MigratorConfiguration())
->setTimeAllQueries(true);
- $versionExecutionResult = $this->versionExecutor->execute(
- $this->version,
- $this->migration,
- Direction::UP,
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::UP);
+
+ $result = $this->versionExecutor->execute(
+ $plan,
$migratorConfiguration
);
- self::assertSame(['SELECT 1', 'SELECT 2'], $versionExecutionResult->getSql());
- self::assertSame([[1], [2]], $versionExecutionResult->getParams());
- self::assertSame([[3], [4]], $versionExecutionResult->getTypes());
- self::assertNotNull($versionExecutionResult->getTime());
- self::assertSame('No State', $this->version->getExecutionState());
+ self::assertSame(['SELECT 1', 'SELECT 2'], $result->getSql());
+ self::assertSame([[1]], $result->getParams());
+ self::assertSame([[3]], $result->getTypes());
+ self::assertNotNull($result->getTime());
+ self::assertSame(State::NONE, $result->getState());
self::assertTrue($this->migration->preUpExecuted);
self::assertTrue($this->migration->postUpExecuted);
self::assertFalse($this->migration->preDownExecuted);
self::assertFalse($this->migration->postDownExecuted);
+
+ self::assertSame([
+ 0 => '++ migrating test',
+ 1 => 'SELECT 1 ',
+ 2 => '100ms',
+ 3 => 'SELECT 2 ',
+ 4 => '100ms',
+ 5 => 'Migration test migrated (took 100ms, used 100 memory)',
+ ], $this->logger->logs);
}
- /**
- * @test
- */
- public function executeUpShouldAppendDescriptionWhenItIsNotEmpty() : void
+ public function testExecuteUsedExecuteUpdate() : void
{
- $this->outputWriter->expects(self::at(0))
- ->method('write')
- ->with("\n ++ migrating 001 (testing)\n");
+ $this->connection
+ ->expects(self::never())
+ ->method('executeQuery');
+
+ $this->connection
+ ->expects(self::exactly(2))
+ ->method('executeUpdate');
$migratorConfiguration = (new MigratorConfiguration())
->setTimeAllQueries(true);
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::UP);
+
$this->versionExecutor->execute(
- $this->version,
- new VersionExecutorTestMigration($this->version, 'testing'),
- Direction::UP,
+ $plan,
$migratorConfiguration
);
}
- public function testExecuteDown() : void
+ /**
+ * @test
+ */
+ public function executeUpShouldAppendDescriptionWhenItIsNotEmpty() : void
{
- $this->outputWriter->expects(self::at(0))
- ->method('write')
- ->with("\n -- reverting 001\n");
-
- $this->outputWriter->expects(self::at(1))
- ->method('write')
- ->with(' -> SELECT 3');
+ $this->migration->setDescription('testing');
- $this->outputWriter->expects(self::at(2))
- ->method('write')
- ->with(' 100ms');
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::UP);
+ $migratorConfiguration = (new MigratorConfiguration())
+ ->setTimeAllQueries(true);
- $this->outputWriter->expects(self::at(3))
- ->method('write')
- ->with(' -> SELECT 4');
+ $this->versionExecutor->execute($plan, $migratorConfiguration);
- $this->outputWriter->expects(self::at(4))
- ->method('write')
- ->with(' 100ms');
+ self::assertSame('++ migrating test (testing)', $this->logger->logs[0]);
+ }
- $this->outputWriter->expects(self::at(5))
- ->method('write')
- ->with("\n -- reverted (took 100ms, used 100 memory)");
+ public function testExecuteDown() : void
+ {
+ $this->metadataStorage
+ ->expects(self::once())
+ ->method('complete')->willReturnCallback(static function (ExecutionResult $result) : void {
+ self::assertSame(Direction::DOWN, $result->getDirection());
+ self::assertNotNull($result->getTime());
+ self::assertNotNull($result->getExecutedAt());
+ });
$migratorConfiguration = (new MigratorConfiguration())
->setTimeAllQueries(true);
- $versionExecutionResult = $this->versionExecutor->execute(
- $this->version,
- $this->migration,
- Direction::DOWN,
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::DOWN);
+
+ $result = $this->versionExecutor->execute(
+ $plan,
$migratorConfiguration
);
- self::assertSame(['SELECT 3', 'SELECT 4'], $versionExecutionResult->getSql());
- self::assertSame([[5], [6]], $versionExecutionResult->getParams());
- self::assertSame([[7], [8]], $versionExecutionResult->getTypes());
- self::assertNotNull($versionExecutionResult->getTime());
- self::assertSame('No State', $this->version->getExecutionState());
+ self::assertSame(['SELECT 3', 'SELECT 4'], $result->getSql());
+ self::assertSame([[5], [6]], $result->getParams());
+ self::assertSame([[7], [8]], $result->getTypes());
+ self::assertNotNull($result->getTime());
+ self::assertSame(State::NONE, $result->getState());
self::assertFalse($this->migration->preUpExecuted);
self::assertFalse($this->migration->postUpExecuted);
self::assertTrue($this->migration->preDownExecuted);
self::assertTrue($this->migration->postDownExecuted);
+
+ self::assertSame([
+ 0 => '++ reverting test',
+ 1 => 'SELECT 3 ',
+ 2 => '100ms',
+ 3 => 'SELECT 4 ',
+ 4 => '100ms',
+ 5 => 'Migration test reverted (took 100ms, used 100 memory)',
+ ], $this->logger->logs);
}
/**
* @test
*/
- public function executeDownShouldAppendDescriptionWhenItIsNotEmpty() : void
+ public function testSkipMigration() : void
+ {
+ $this->metadataStorage
+ ->expects(self::never())
+ ->method('complete');
+
+ $migratorConfiguration = (new MigratorConfiguration())
+ ->setTimeAllQueries(true);
+
+ $listener = new class() {
+ /** @var bool */
+ public $onMigrationsVersionExecuting = false;
+ /** @var bool */
+ public $onMigrationsVersionExecuted = false;
+ /** @var bool */
+ public $onMigrationsVersionSkipped = false;
+
+ public function onMigrationsVersionExecuting() : void
+ {
+ $this->onMigrationsVersionExecuting = true;
+ }
+
+ public function onMigrationsVersionExecuted() : void
+ {
+ $this->onMigrationsVersionExecuted = true;
+ }
+
+ public function onMigrationsVersionSkipped() : void
+ {
+ $this->onMigrationsVersionSkipped = true;
+ }
+ };
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuting, $listener);
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuted, $listener);
+ $this->eventManager->addEventListener(Events::onMigrationsVersionSkipped, $listener);
+
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::UP);
+ $this->migration->skip = true;
+
+ $result = $this->versionExecutor->execute(
+ $plan,
+ $migratorConfiguration
+ );
+
+ self::assertTrue($result->isSkipped());
+ self::assertSame([], $result->getSql());
+ self::assertSame(State::EXEC, $result->getState());
+ self::assertTrue($this->migration->preUpExecuted);
+ self::assertFalse($this->migration->postUpExecuted);
+ self::assertFalse($this->migration->preDownExecuted);
+ self::assertFalse($this->migration->postDownExecuted);
+
+ self::assertFalse($listener->onMigrationsVersionExecuted);
+ self::assertTrue($listener->onMigrationsVersionSkipped);
+ self::assertTrue($listener->onMigrationsVersionExecuting);
+ }
+
+ /**
+ * @test
+ */
+ public function testMigrationEvents() : void
+ {
+ $migratorConfiguration = (new MigratorConfiguration())
+ ->setTimeAllQueries(true);
+
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::UP);
+
+ $listener = new class() {
+ /** @var bool */
+ public $onMigrationsVersionExecuting = false;
+ /** @var bool */
+ public $onMigrationsVersionExecuted = false;
+
+ public function onMigrationsVersionExecuting() : void
+ {
+ $this->onMigrationsVersionExecuting = true;
+ }
+
+ public function onMigrationsVersionExecuted() : void
+ {
+ $this->onMigrationsVersionExecuted = true;
+ }
+ };
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuting, $listener);
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuted, $listener);
+
+ $this->versionExecutor->execute(
+ $plan,
+ $migratorConfiguration
+ );
+ self::assertTrue($listener->onMigrationsVersionExecuted);
+ self::assertTrue($listener->onMigrationsVersionExecuting);
+ }
+
+ /**
+ * @test
+ */
+ public function testErrorMigration() : void
{
- $this->outputWriter->expects(self::at(0))
- ->method('write')
- ->with("\n -- reverting 001 (testing)\n");
+ $this->metadataStorage
+ ->expects(self::never())
+ ->method('complete');
+
+ $migratorConfiguration = (new MigratorConfiguration())
+ ->setTimeAllQueries(true);
+
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::UP);
+ $this->migration->error = true;
+
+ $listener = new class() {
+ /** @var bool */
+ public $onMigrationsVersionExecuting = false;
+ /** @var bool */
+ public $onMigrationsVersionExecuted = false;
+ /** @var bool */
+ public $onMigrationsVersionSkipped = false;
+
+ public function onMigrationsVersionExecuting() : void
+ {
+ $this->onMigrationsVersionExecuting = true;
+ }
+
+ public function onMigrationsVersionExecuted() : void
+ {
+ $this->onMigrationsVersionExecuted = true;
+ }
+
+ public function onMigrationsVersionSkipped() : void
+ {
+ $this->onMigrationsVersionSkipped = true;
+ }
+ };
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuting, $listener);
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuted, $listener);
+ $this->eventManager->addEventListener(Events::onMigrationsVersionSkipped, $listener);
+
+ $migrationSucceed = false;
+ try {
+ $this->versionExecutor->execute(
+ $plan,
+ $migratorConfiguration
+ );
+ $migrationSucceed = true;
+ } catch (Throwable $e) {
+ self::assertFalse($listener->onMigrationsVersionExecuted);
+ self::assertTrue($listener->onMigrationsVersionSkipped);
+ self::assertTrue($listener->onMigrationsVersionExecuting);
+
+ $result = $plan->getResult();
+ self::assertNotNull($result);
+ self::assertSame([], $result->getSql());
+ self::assertSame([], $result->getSql());
+ self::assertSame(State::EXEC, $result->getState());
+ self::assertTrue($this->migration->preUpExecuted);
+ self::assertFalse($this->migration->postUpExecuted);
+ self::assertFalse($this->migration->preDownExecuted);
+ self::assertFalse($this->migration->postDownExecuted);
+ }
+ self::assertFalse($migrationSucceed);
+ }
+
+ public function testChangesNotCommittedIfMetadataFailure() : void
+ {
+ $this->metadataStorage
+ ->expects(self::once())
+ ->method('complete')
+ ->willThrowException(new Exception('foo'));
+
+ $this->connection
+ ->expects(self::never())
+ ->method('commit');
+
+ $this->connection
+ ->expects(self::once())
+ ->method('rollBack');
+
+ $migratorConfiguration = (new MigratorConfiguration())
+ ->setTimeAllQueries(true);
+
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::UP);
+
+ $listener = new class() {
+ /** @var bool */
+ public $onMigrationsVersionExecuting = false;
+ /** @var bool */
+ public $onMigrationsVersionExecuted = false;
+ /** @var bool */
+ public $onMigrationsVersionSkipped = false;
+
+ public function onMigrationsVersionExecuting() : void
+ {
+ $this->onMigrationsVersionExecuting = true;
+ }
+
+ public function onMigrationsVersionExecuted() : void
+ {
+ $this->onMigrationsVersionExecuted = true;
+ }
+
+ public function onMigrationsVersionSkipped() : void
+ {
+ $this->onMigrationsVersionSkipped = true;
+ }
+ };
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuting, $listener);
+ $this->eventManager->addEventListener(Events::onMigrationsVersionExecuted, $listener);
+ $this->eventManager->addEventListener(Events::onMigrationsVersionSkipped, $listener);
+
+ $migrationSucceed = false;
+ try {
+ $this->versionExecutor->execute(
+ $plan,
+ $migratorConfiguration
+ );
+ $migrationSucceed = true;
+ } catch (Throwable $e) {
+ self::assertFalse($listener->onMigrationsVersionExecuted);
+ self::assertTrue($listener->onMigrationsVersionSkipped);
+ self::assertTrue($listener->onMigrationsVersionExecuting);
+
+ $result = $plan->getResult();
+ self::assertNotNull($result);
+ self::assertSame([], $result->getSql());
+ self::assertSame([], $result->getSql());
+ self::assertSame(State::POST, $result->getState());
+ self::assertTrue($this->migration->preUpExecuted);
+ self::assertTrue($this->migration->postUpExecuted);
+ self::assertFalse($this->migration->preDownExecuted);
+ self::assertFalse($this->migration->postDownExecuted);
+ }
+ self::assertFalse($migrationSucceed);
+ }
+ /**
+ * @test
+ */
+ public function executeDownShouldAppendDescriptionWhenItIsNotEmpty() : void
+ {
$migratorConfiguration = (new MigratorConfiguration())
->setTimeAllQueries(true);
+ $plan = new MigrationPlan($this->version, $this->migration, Direction::DOWN);
+
$this->versionExecutor->execute(
- $this->version,
- new VersionExecutorTestMigration($this->version, 'testing'),
- Direction::DOWN,
+ $plan,
$migratorConfiguration
);
+
+ self::assertSame('++ reverting test', $this->logger->logs[0]);
}
protected function setUp() : void
{
- $this->configuration = $this->createMock(Configuration::class);
+ $this->metadataStorage = $this->createMock(MetadataStorage::class);
$this->connection = $this->createMock(Connection::class);
- $this->schemaDiffProvider = $this->createMock(SchemaDiffProviderInterface::class);
- $this->outputWriter = $this->createMock(OutputWriter::class);
+ $this->schemaDiffProvider = $this->createMock(SchemaDiffProvider::class);
$this->parameterFormatter = $this->createMock(ParameterFormatterInterface::class);
- $this->stopwatch = $this->createMock(Stopwatch::class);
+
+ $this->eventManager = new EventManager();
+ $this->eventDispatcher = new EventDispatcher($this->connection, $this->eventManager);
+
+ $this->stopwatch = $this->createMock(Stopwatch::class);
+ $this->logger = new TestLogger();
$this->versionExecutor = new Executor(
- $this->configuration,
+ $this->metadataStorage,
+ $this->eventDispatcher,
$this->connection,
$this->schemaDiffProvider,
- $this->outputWriter,
+ $this->logger,
$this->parameterFormatter,
$this->stopwatch
);
- $this->configuration->expects(self::any())
- ->method('getConnection')
- ->willReturn($this->connection);
-
- $this->connection->expects(self::any())
- ->method('getDatabasePlatform')
- ->willReturn($this->createMock(AbstractPlatform::class));
+ $this->version = new Version('test');
- $this->version = new Version(
- $this->configuration,
- '001',
- VersionExecutorTestMigration::class,
- $this->versionExecutor
- );
-
- $this->migration = new VersionExecutorTestMigration($this->version);
+ $this->migration = new VersionExecutorTestMigration($this->connection, $this->logger);
$stopwatchEvent = $this->createMock(StopwatchEvent::class);
@@ -263,39 +504,48 @@ class VersionExecutorTestMigration extends AbstractMigration
public $postDownExecuted = false;
/** @var string */
- private $description;
-
- public function __construct(Version $version, string $description = '')
- {
- parent::__construct($version);
+ private $description = '';
- $this->description = $description;
- }
+ /** @var bool */
+ public $skip = false;
+ /** @var bool */
+ public $error = false;
public function getDescription() : string
{
return $this->description;
}
+ public function setDescription(string $description) : void
+ {
+ $this->description = $description;
+ }
+
public function preUp(Schema $fromSchema) : void
{
$this->preUpExecuted = true;
+ parent::preUp($fromSchema);
}
public function up(Schema $schema) : void
{
+ $this->skipIf($this->skip);
+ $this->abortIf($this->error);
+
$this->addSql('SELECT 1', [1], [3]);
- $this->addSql('SELECT 2', [2], [4]);
+ $this->addSql('SELECT 2');
}
public function postUp(Schema $toSchema) : void
{
$this->postUpExecuted = true;
+ parent::postUp($toSchema);
}
public function preDown(Schema $fromSchema) : void
{
$this->preDownExecuted = true;
+ parent::preDown($fromSchema);
}
public function down(Schema $schema) : void
@@ -307,5 +557,6 @@ public function down(Schema $schema) : void
public function postDown(Schema $toSchema) : void
{
$this->postDownExecuted = true;
+ parent::postDown($toSchema);
}
}
diff --git a/tests/Doctrine/Migrations/Tests/Version/FactoryTest.php b/tests/Doctrine/Migrations/Tests/Version/FactoryTest.php
index 766aa3049e..84db7b22dc 100644
--- a/tests/Doctrine/Migrations/Tests/Version/FactoryTest.php
+++ b/tests/Doctrine/Migrations/Tests/Version/FactoryTest.php
@@ -4,43 +4,47 @@
namespace Doctrine\Migrations\Tests\Version;
+use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
-use Doctrine\Migrations\Configuration\Configuration;
-use Doctrine\Migrations\Version\ExecutorInterface;
-use Doctrine\Migrations\Version\Factory;
+use Doctrine\Migrations\Version\MigrationFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
+use Psr\Log\LoggerInterface;
+use ReflectionProperty;
final class FactoryTest extends TestCase
{
- /** @var Configuration */
- private $configuration;
+ /** @var MockObject|Connection */
+ private $connection;
+ /** @var MockObject|LoggerInterface */
+ private $logger;
- /** @var ExecutorInterface */
- private $versionExecutor;
-
- /** @var Factory */
+ /** @var MigrationFactory */
private $versionFactory;
public function testCreateVersion() : void
{
- $version = $this->versionFactory->createVersion(
- '001',
+ $migration = $this->versionFactory->createVersion(
VersionFactoryTestMigration::class
);
- self::assertSame($this->configuration, $version->getConfiguration());
- self::assertInstanceOf(VersionFactoryTestMigration::class, $version->getMigration());
+ self::assertInstanceOf(VersionFactoryTestMigration::class, $migration);
+ self::assertSame($this->connection, $migration->getConnection());
+
+ $ref = new ReflectionProperty(AbstractMigration::class, 'logger');
+ $ref->setAccessible(true);
+ self::assertSame($this->logger, $ref->getValue($migration));
}
protected function setUp() : void
{
- $this->configuration = $this->createMock(Configuration::class);
- $this->versionExecutor = $this->createMock(ExecutorInterface::class);
+ $this->connection = $this->createMock(Connection::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
- $this->versionFactory = new Factory(
- $this->configuration,
- $this->versionExecutor
+ $this->versionFactory = new MigrationFactory(
+ $this->connection,
+ $this->logger
);
}
}
@@ -54,4 +58,9 @@ public function up(Schema $schema) : void
public function down(Schema $schema) : void
{
}
+
+ public function getConnection() : Connection
+ {
+ return $this->connection;
+ }
}
diff --git a/tests/Doctrine/Migrations/Tests/Version/VersionTest.php b/tests/Doctrine/Migrations/Tests/Version/VersionTest.php
deleted file mode 100644
index 634d611c5b..0000000000
--- a/tests/Doctrine/Migrations/Tests/Version/VersionTest.php
+++ /dev/null
@@ -1,710 +0,0 @@
-getSqliteConfiguration();
-
- $version = $this->createTestVersion(
- $configuration,
- $versionName,
- VersionDummy::class
- );
-
- self::assertSame($versionName, $version->getVersion());
- }
-
- public function testShowSqlStatementsParameters() : void
- {
- $outputWriter = $this->getOutputWriter();
-
- $configuration = $this->getSqliteConfiguration();
- $configuration->setOutputWriter($outputWriter);
-
- $version = $this->createTestVersion($configuration, '0004', VersionOutputSqlWithParam::class);
- $migration = $version->getMigration();
-
- self::assertInstanceOf(VersionOutputSqlWithParam::class, $migration);
-
- $migration->setParam([
- 0 => 456,
- 1 => 'tralala',
- 2 => 456,
- ]);
-
- $version->execute(Direction::UP);
-
- self::assertContains('([456], [tralala], [456])', $this->getOutputStreamContent($this->output));
- }
-
- public function testShowSqlStatementsParametersWithTypes() : void
- {
- $outputWriter = $this->getOutputWriter();
-
- $configuration = $this->getSqliteConfiguration();
- $configuration->setOutputWriter($outputWriter);
-
- $version = $this->createTestVersion($configuration, '0004', VersionOutputSqlWithParamAndType::class);
- $migration = $version->getMigration();
-
- self::assertInstanceOf(VersionOutputSqlWithParamAndType::class, $migration);
-
- $migration->setParam([
- 0 => [
- 456,
- 3,
- 456,
- ],
- ]);
-
- $migration->setType([Connection::PARAM_INT_ARRAY]);
-
- $version->execute(Direction::UP, (new MigratorConfiguration())
- ->setDryRun(true));
-
- self::assertContains('([456, 3, 456])', $this->getOutputStreamContent($this->output));
- }
-
- public function testCreateVersionWithCustomName() : void
- {
- $versionName = '003';
- $versionDescription = 'My super migration';
-
- $configuration = $this->getSqliteConfiguration();
-
- $version = $this->createTestVersion(
- $configuration,
- $versionName,
- VersionDummyDescription::class
- );
-
- self::assertSame($versionName, $version->getVersion());
- self::assertSame($versionDescription, $version->getMigration()->getDescription());
- }
-
- /** @dataProvider stateProvider */
- public function testGetExecutionState(string $state) : void
- {
- $configuration = $this->getSqliteConfiguration();
-
- $version = $this->createTestVersion(
- $configuration,
- '003',
- VersionDummy::class
- );
-
- $reflectionVersion = new ReflectionClass(Version::class);
-
- $stateProperty = $reflectionVersion->getProperty('state');
- $stateProperty->setAccessible(true);
- $stateProperty->setValue($version, $state);
-
- self::assertNotEmpty($version->getExecutionState());
- }
-
- /** @return mixed[][] */
- public function stateProvider() : array
- {
- return [
- [State::NONE],
- [State::EXEC],
- [State::POST],
- [State::PRE],
- [-1],
- ];
- }
-
- public function testAddSql() : void
- {
- $configuration = $this->getSqliteConfiguration();
-
- $versionExecutor = $this->createMock(ExecutorInterface::class);
-
- $versionExecutor->expects(self::once())
- ->method('addSql')
- ->with('SELECT * FROM foo WHERE id = ?', [1], [PDO::PARAM_INT]);
-
- $version = new Version($configuration, '003', VersionDummy::class, $versionExecutor);
-
- $version->addSql('SELECT * FROM foo WHERE id = ?', [1], [PDO::PARAM_INT]);
- }
-
- /**
- * @param string[] $getSqlReturn
- *
- * @dataProvider writeSqlFileProvider
- */
- public function testWriteSqlFile(string $path, string $direction, array $getSqlReturn) : void
- {
- $version = '1';
-
- $connection = $this->getSqliteConnection();
- $outputWriter = $this->createMock(OutputWriter::class);
- $queryWriter = $this->createMock(QueryWriter::class);
-
- $outputWriter->expects(self::atLeastOnce())
- ->method('write');
-
- /** @var Configuration|PHPUnit_Framework_MockObject_MockObject $config */
- $config = $this->getMockBuilder(Configuration::class)
- ->disableOriginalConstructor()
- ->setMethods(['getConnection', 'getOutputWriter', 'getQueryWriter'])
- ->getMock();
-
- $config->method('getOutputWriter')
- ->willReturn($outputWriter);
-
- $config->method('getConnection')
- ->willReturn($connection);
-
- $config->method('getQueryWriter')
- ->willReturn($queryWriter);
-
- /** @var Version|PHPUnit_Framework_MockObject_MockObject $version */
- $version = $this->getMockBuilder(Version::class)
- ->setConstructorArgs($this->getMockVersionConstructorArgs($config, $version, TestMigration::class))
- ->setMethods(['execute'])
- ->getMock();
-
- $versionExecutionResult = new ExecutionResult($getSqlReturn);
-
- $version->expects(self::once())
- ->method('execute')
- ->with($direction)
- ->willReturn($versionExecutionResult);
-
- $queryWriter->method('write')
- ->with($path, $direction, [$version->getVersion() => $getSqlReturn])
- ->willReturn(true);
-
- self::assertTrue($version->writeSqlFile($path, $direction));
- }
-
- /** @return mixed[][] */
- public function writeSqlFileProvider() : array
- {
- return [
- [__DIR__, 'up', ['1' => ['SHOW DATABASES;']]], // up
- [__DIR__, 'down', ['1' => ['SHOW DATABASES;']]], // up
- [__DIR__ . '/tmpfile.sql', 'up', ['1' => ['SHOW DATABASES']]], // tests something actually got written
- ];
- }
-
- public function testWarningWhenNoSqlStatementIsOutputed() : void
- {
- $outputWriter = $this->getOutputWriter();
-
- $config = $this->getSqliteConfiguration();
- $config->setOutputWriter($outputWriter);
-
- $version = $this->createTestVersion(
- $config,
- '003',
- VersionDummy::class
- );
-
- $version->execute('up');
-
- self::assertContains(
- 'Migration 003 was executed but did not result in any SQL statements.',
- $this->getOutputStreamContent($this->output)
- );
- }
-
- public function testCatchExceptionDuringMigration() : void
- {
- $outputWriter = $this->getOutputWriter();
-
- $config = $this->getSqliteConfiguration();
- $config->setOutputWriter($outputWriter);
-
- $version = $this->createTestVersion(
- $config,
- '004',
- ExceptionVersionDummy::class
- );
-
- try {
- $version->execute('up');
- } catch (Throwable $e) {
- self::assertContains(
- 'Migration 004 failed during Execution. Error Super Exception',
- $this->getOutputStreamContent($this->output)
- );
- }
- }
-
- public function testReturnTheSql() : void
- {
- $config = $this->getSqliteConfiguration();
-
- $version = $this->createTestVersion(
- $config,
- '005',
- VersionOutputSql::class
- );
-
- self::assertContains('Select 1', $version->execute('up')->getSql());
- self::assertContains('Select 1', $version->execute('down')->getSql());
- }
-
- public function testReturnTheSqlWithParams() : void
- {
- $config = $this->getSqliteConfiguration();
-
- $version = $this->createTestVersion(
- $config,
- '006',
- VersionOutputSqlWithParam::class
- );
-
- $this->expectException(MigrationException::class);
- $this->expectExceptionMessage('contains a prepared statement.');
-
- $version->writeSqlFile('tralala');
- }
-
- /** @dataProvider sqlWriteProvider */
- public function testWriteSqlWriteToTheCorrectColumnName(
- string $direction,
- string $tableName,
- string $columnName,
- string $executedAtColumnName
- ) : void {
- $configuration = $this->getSqliteConfiguration();
- $configuration->setMigrationsTableName($tableName);
- $configuration->setMigrationsColumnName($columnName);
- $configuration->setMigrationsExecutedAtColumnName($executedAtColumnName);
-
- $versionName = '005';
-
- $version = $this->createTestVersion(
- $configuration,
- $versionName,
- VersionOutputSql::class
- );
-
- $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'migrations';
-
- $version->writeSqlFile($path, $direction);
-
- $files = $this->getSqlFilesList($path);
-
- foreach ($files as $file) {
- $contents = file_get_contents($file);
-
- self::assertNotEmpty($contents);
-
- if ($direction === Direction::UP) {
- $sql = sprintf(
- "INSERT INTO %s (%s, %s) VALUES ('%s', CURRENT_TIMESTAMP);",
- $tableName,
- $columnName,
- $executedAtColumnName,
- $versionName
- );
-
- self::assertContains($sql, $contents);
- } else {
- $sql = sprintf(
- "DELETE FROM %s WHERE %s = '%s'",
- $tableName,
- $columnName,
- $versionName
- );
-
- self::assertContains($sql, $contents);
- }
-
- unlink($file);
- }
- }
-
- /** @return string[][] */
- public function sqlWriteProvider() : array
- {
- return [
- [Direction::UP, 'fkqsdmfjl', 'balalala', 'executed_at'],
- [Direction::UP, 'balalala', 'fkqsdmfjl', 'executedAt'],
- [Direction::DOWN, 'fkqsdmfjl', 'balalala', 'executed_at'],
- [Direction::DOWN, 'balalala', 'fkqsdmfjl', 'executedAt'],
- ];
- }
-
- public function testWriteSqlFileShouldUseStandardCommentMarkerInSql() : void
- {
- $version = '1';
- $direction = Direction::UP;
-
- $connection = $this->getSqliteConnection();
-
- /** @var Configuration|PHPUnit_Framework_MockObject_MockObject $migration */
- $config = $this->getMockBuilder(Configuration::class)
- ->disableOriginalConstructor()
- ->setMethods([
- 'getOutputWriter',
- 'getConnection',
- 'getQuotedMigrationsColumnName',
- 'getQuotedMigrationsExecutedAtColumnName',
- ])
- ->getMock();
-
- $config->method('getOutputWriter')
- ->willReturn($this->getOutputWriter());
-
- $config->method('getConnection')
- ->willReturn($connection);
-
- $config->method('getQuotedMigrationsColumnName')
- ->willReturn('version');
-
- $config->method('getQuotedMigrationsExecutedAtColumnName')
- ->willReturn('executed_at');
-
- /** @var Version|PHPUnit_Framework_MockObject_MockObject $migration */
- $migration = $this->getMockBuilder(Version::class)
- ->setConstructorArgs($this->getMockVersionConstructorArgs($config, $version, TestMigration::class))
- ->setMethods(['execute'])
- ->getMock();
-
- $versionExecutionResult = new ExecutionResult(['SHOW DATABASES;']);
-
- $migration->method('execute')
- ->with($direction)
- ->willReturn($versionExecutionResult);
-
- $sqlFilesDir = vfsStream::setup('sql_files_dir');
- $migration->writeSqlFile(vfsStream::url('sql_files_dir'), $direction);
-
- self::assertRegExp('/^\s*-- Version 1/m', $this->getOutputStreamContent($this->output));
-
- /** @var vfsStreamFile $sqlMigrationFile */
- $sqlMigrationFile = current($sqlFilesDir->getChildren());
-
- self::assertNotRegExp('/^\s*#/m', $sqlMigrationFile->getContent());
- }
-
- public function testDryRunCausesSqlToBeOutputViaTheOutputWriter() : void
- {
- $messages = [];
-
- $ow = new OutputWriter(static function ($msg) use (&$messages) : void {
- $messages[] = trim($msg);
- });
-
- $config = $this->getSqliteConfiguration();
- $config->setOutputWriter($ow);
-
- $version = $this->createTestVersion(
- $config,
- '006',
- VersionDryRunWithoutParams::class
- );
-
- $version->execute(Direction::UP, (new MigratorConfiguration())
- ->setDryRun(true));
-
- self::assertCount(3, $messages, 'should have written three messages (header, footer, 1 SQL statement)');
- self::assertContains('SELECT 1 WHERE 1', $messages[1]);
- }
-
- public function testDryRunWithQuestionMarkedParamsOutputsParamsWithSqlStatement() : void
- {
- $messages = [];
-
- $ow = new OutputWriter(static function ($msg) use (&$messages) : void {
- $messages[] = trim($msg);
- });
-
- $config = $this->getSqliteConfiguration();
- $config->setOutputWriter($ow);
-
- $version = $this->createTestVersion(
- $config,
- '006',
- VersionDryRunQuestionMarkParams::class
- );
-
- $version->execute(Direction::UP, (new MigratorConfiguration())
- ->setDryRun(true));
-
- self::assertCount(3, $messages, 'should have written three messages (header, footer, 1 SQL statement)');
- self::assertContains('INSERT INTO test VALUES (?, ?)', $messages[1]);
- self::assertContains('with parameters ([one], [two])', $messages[1]);
- }
-
- public function testDryRunWithNamedParametersOutputsParamsAndNamesWithSqlStatement() : void
- {
- $messages = [];
-
- $ow = new OutputWriter(static function ($msg) use (&$messages) : void {
- $messages[] = trim($msg);
- });
-
- $config = $this->getSqliteConfiguration();
- $config->setOutputWriter($ow);
-
- $version = $this->createTestVersion(
- $config,
- '006',
- VersionDryRunNamedParams::class
- );
-
- $version->execute(Direction::UP, (new MigratorConfiguration())
- ->setDryRun(true));
-
- self::assertCount(3, $messages, 'should have written three messages (header, footer, 1 SQL statement)');
- self::assertContains('INSERT INTO test VALUES (:one, :two)', $messages[1]);
- self::assertContains('with parameters (:one => [one], :two => [two])', $messages[1]);
- }
-
- /** @return mixed[][] */
- public static function dryRunTypes() : array
- {
- return [
- 'datetime' => [[new DateTime('2016-07-05 01:00:00')], ['datetime'], '[2016-07-05 01:00:00]'],
- 'array' => [[['one' => 'two']], ['array'], '[' . serialize(['one' => 'two']) . ']'],
- 'doctrine_param' => [[[1, 2, 3, 4, 5]], [Connection::PARAM_INT_ARRAY], '[1, 2, 3, 4, 5]'],
- 'doctrine_param_grouped' => [[[1, 2], [3, 4, 5]], [Connection::PARAM_INT_ARRAY, Connection::PARAM_INT_ARRAY], '[1, 2], [3, 4, 5]'],
- 'boolean' => [[true], [''], '[true]'],
- 'object' => [[new stdClass()], [''], '[?]'],
- ];
- }
-
- /**
- * @param mixed[] $value
- * @param mixed[] $type
- *
- * @dataProvider dryRunTypes
- */
- public function testDryRunWithParametersOfComplexTypesCorrectFormatsParameters(
- array $value,
- array $type,
- string $output
- ) : void {
- $messages = [];
-
- $ow = new OutputWriter(static function ($msg) use (&$messages) : void {
- $messages[] = trim($msg);
- });
-
- $config = $this->getSqliteConfiguration();
- $config->setOutputWriter($ow);
-
- $version = $this->createTestVersion(
- $config,
- '006',
- VersionDryRunTypes::class
- );
- $migration = $version->getMigration();
-
- self::assertInstanceOf(VersionDryRunTypes::class, $migration);
-
- $migration->setParam($value, $type);
-
- $version->execute(Direction::UP, (new MigratorConfiguration())
- ->setDryRun(true));
-
- self::assertCount(3, $messages, 'should have written three messages (header, footer, 1 SQL statement)');
- self::assertContains('INSERT INTO test VALUES (?)', $messages[1]);
- self::assertContains(sprintf('with parameters (%s)', $output), $messages[1]);
- }
-
- public function testRunWithInsertNullValue() : void
- {
- $messages = [];
-
- $ow = new OutputWriter(static function ($msg) use (&$messages) : void {
- $messages[] = trim($msg);
- });
-
- $config = $this->getSqliteConfiguration();
- $config->setOutputWriter($ow);
-
- $version = $this->createTestVersion(
- $config,
- '001',
- VersionDryRunTypes::class
- );
-
- $migration = $version->getMigration();
-
- self::assertInstanceOf(VersionDryRunTypes::class, $migration);
-
- $migration->setParam([null], []);
-
- $version->execute(Direction::UP, (new MigratorConfiguration())
- ->setDryRun(true));
-
- self::assertCount(3, $messages, 'should have written three messages (header, footer, 1 SQL statement)');
- self::assertContains('INSERT INTO test VALUES (?)', $messages[1]);
- self::assertContains('with parameters ([])', $messages[1]);
- }
-
- /**
- * @dataProvider getExecutedAtTimeZones
- */
- public function testExecutedAtTimeZone(string $timeZone) : void
- {
- $this->iniSet('date.timezone', $timeZone);
-
- $config = $this->getSqliteConfiguration();
-
- $version = $this->createTestVersion(
- $config,
- '001',
- VersionDryRunTypes::class
- );
-
- $version->markVersion(Direction::UP);
-
- $versionData = $config->getVersionData($version);
-
- $now = (new DateTimeImmutable('now'))->setTimezone(new DateTimeZone('UTC'));
-
- self::assertSame($now->format('Y-m-d H:i'), date('Y-m-d H:i', strtotime($versionData['executed_at'])));
-
- $executedAt = $version->getExecutedAt();
-
- self::assertNotNull($executedAt);
-
- self::assertSame($timeZone, $executedAt->getTimezone()->getName());
- }
-
- /**
- * @return string[][]
- */
- public function getExecutedAtTimeZones() : array
- {
- return [
- ['America/New_York'],
- ['Indian/Chagos'],
- ['UTC'],
- ];
- }
-
- /**
- * @return mixed[]
- */
- private function getMockVersionConstructorArgs(
- Configuration $configuration,
- string $versionName,
- string $className
- ) : array {
- $schemaDiffProvider = $this->createMock(SchemaDiffProviderInterface::class);
-
- $parameterFormatter = new ParameterFormatter($configuration->getConnection());
-
- $symfonyStopwatch = new SymfonyStopwatch();
- $stopwatch = new Stopwatch($symfonyStopwatch);
-
- $versionExecutor = new Executor(
- $configuration,
- $configuration->getConnection(),
- $schemaDiffProvider,
- $configuration->getOutputWriter(),
- $parameterFormatter,
- $stopwatch
- );
-
- return [$configuration, $versionName, $className, $versionExecutor];
- }
-
- private function createTestVersion(
- Configuration $configuration,
- string $versionName,
- string $className
- ) : Version {
- $schemaDiffProvider = $this->createMock(SchemaDiffProviderInterface::class);
-
- $parameterFormatter = new ParameterFormatter($configuration->getConnection());
-
- $symfonyStopwatch = new SymfonyStopwatch();
- $stopwatch = new Stopwatch($symfonyStopwatch);
-
- $versionExecutor = new Executor(
- $configuration,
- $configuration->getConnection(),
- $schemaDiffProvider,
- $configuration->getOutputWriter(),
- $parameterFormatter,
- $stopwatch
- );
-
- return new Version($configuration, $versionName, $className, $versionExecutor);
- }
-}
-
-class TestMigration extends AbstractMigration
-{
- public function up(Schema $schema) : void
- {
- }
-
- public function down(Schema $schema) : void
- {
- }
-}
diff --git a/tests/Doctrine/Migrations/Tests/doctrine-migrations-phpstan-app.php b/tests/Doctrine/Migrations/Tests/doctrine-migrations-phpstan-app.php
new file mode 100644
index 0000000000..a779732c09
--- /dev/null
+++ b/tests/Doctrine/Migrations/Tests/doctrine-migrations-phpstan-app.php
@@ -0,0 +1,18 @@
+set(new QuestionHelper(), 'question');
+
+return ConsoleRunner::createApplication($helperSet, [new DiffCommand()]);
diff --git a/tests/Doctrine/Migrations/Tests/realpath.php b/tests/Doctrine/Migrations/Tests/realpath.php
deleted file mode 100644
index 15088d1287..0000000000
--- a/tests/Doctrine/Migrations/Tests/realpath.php
+++ /dev/null
@@ -1,24 +0,0 @@
-