diff --git a/.gitattributes b/.gitattributes
index 949650b4..a33e50e1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,13 +1,13 @@
* text=auto
.github/ export-ignore
+.run/ export-ignore
+docs/ export-ignore
tests/ export-ignore
-.codecov.yml export-ignore
.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
-.scrutinizer.yml export-ignore
-.styleci.yml export-ignore
+package.json export-ignore
phpunit.xml export-ignore
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 35a98d65..dfc1470e 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,8 +1,6 @@
-name: Bug
+name: Bug Report
description: Report a bug or other issue
-labels: '👓 needs review'
-
body:
- type: markdown
attributes:
@@ -20,10 +18,10 @@ body:
Tip: Use the `php artisan --version` command to get information for Laravel Framework.
Tip: Use the `php -v` command to get information for PHP.
value: |
- - Migration Actions Version:
- - Laravel Version:
- PHP Version:
- Database Driver & Version:
+ - Migration Actions Version:
+ - Laravel Version:
validations:
required: true
@@ -50,4 +48,4 @@ body:
- type: markdown
attributes:
value: |
- ❤️ The Dragon Code? Please consider supporting our collective: https://opencollective.com/dragon-code
+ ❤️ The Dragon Code? Please consider supporting [`our collective`](https://opencollective.com/dragon-code).
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index bbaac841..751fd8f2 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -1,17 +1,7 @@
name: Feature Proposal
description: Propose a new feature
-labels:
- - '💪 feature request'
-
body:
- - type: markdown
- attributes:
- value: |
- Thanks for taking the time to fill out this bug report!
-
- ⚠️Review existing issues to see whether someone else has already reported your issue.
-
- type: textarea
id: description
attributes:
@@ -23,23 +13,7 @@ body:
validations:
required: true
- - type: textarea
- id: environment
- attributes:
- label: Environment
- description: |
- Tip: Use the `composer info dragon-code/laravel-migration-actions` command to get information for Laravel Lang.
- Tip: Use the `php artisan --version` command to get information for your application.
- Tip: Use the `php -v` command to get information for PHP.
- value: |
- - Migration Actions Version:
- - Laravel Version:
- - PHP Version:
- - Database Driver & Version:
- validations:
- required: false
-
- type: markdown
attributes:
value: |
- ❤️ The Dragon Code? Please consider supporting our collective: https://opencollective.com/dragon-code
+ ❤️ The Dragon Code? Please consider supporting [`our collective`](https://opencollective.com/dragon-code).
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
new file mode 100644
index 00000000..3d6d3135
--- /dev/null
+++ b/.github/workflows/changelog.yml
@@ -0,0 +1,54 @@
+name: changelog
+
+on:
+ release:
+ types:
+ - released
+
+permissions: write-all
+
+jobs:
+ update:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ extensions: curl, mbstring, zip, pcntl, pdo, pdo_sqlite, iconv, json
+ coverage: none
+
+ - name: Git setup
+ if: success()
+ run: |
+ git config --local user.email "action@github.com"
+ git config --local user.name "GitHub Action"
+
+ - name: Update
+ uses: stefanzweifel/changelog-updater-action@v1
+ if: success()
+ with:
+ release-date: ${{ steps.release_date.outputs.date }}
+ release-notes: ${{ github.event.release.body }}
+ latest-version: ${{ github.event.release.tag_name }}
+ compare-url-target-revision: ${{ github.event.release.target_commitish }}
+ path-to-changelog: docs/prologue/changelog/3.x.md
+
+ - name: Storing
+ id: changelog
+ if: success()
+ run: |
+ IS_DIRTY=1
+
+ { git add . && git commit -a -m "🧾 Update CHANGELOG"; } || IS_DIRTY=0
+
+ echo ::set-output name=is_dirty::${IS_DIRTY}
+
+ - name: Push changes
+ uses: ad-m/github-push-action@master
+ if: success() && steps.changelog.outputs.is_dirty == 1
+ with:
+ github_token: ${{ secrets.COMPOSER_TOKEN }}
diff --git a/.github/workflows/code-style.yml b/.github/workflows/code-style.yml
new file mode 100644
index 00000000..665db2e4
--- /dev/null
+++ b/.github/workflows/code-style.yml
@@ -0,0 +1,35 @@
+name: code-style
+
+on:
+ push:
+ pull_request:
+
+permissions: write-all
+
+jobs:
+ check:
+ if: ${{ ! (github.event_name == 'push' && github.ref == 'refs/heads/main') }}
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Checking PHP Syntax
+ uses: TheDragonCode/codestyler@v2.6.2
+
+ fix:
+ if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Checking PHP Syntax
+ uses: TheDragonCode/codestyler@v2.6.2
+ with:
+ github_token: ${{ secrets.COMPOSER_TOKEN }}
+ fix: true
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 00000000..577992dc
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,66 @@
+name: docs
+
+on:
+ push:
+ branches:
+ - main
+ workflow_run:
+ workflows:
+ - changelog
+ types:
+ - completed
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: true
+
+jobs:
+ generate:
+ runs-on: ubuntu-latest
+
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v2
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v3
+
+ - name: Cache dependencies
+ uses: actions/cache@v3
+ id: npm-cache
+ with:
+ path: |
+ **/node_modules
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+
+ - name: Install dependencies
+ run: npm i
+
+ - name: Build VuePress site
+ run: npm run build
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v1
+ with:
+ path: './docs/.vuepress/dist'
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v1
diff --git a/.github/workflows/laravel-6.yml b/.github/workflows/laravel-6.yml
deleted file mode 100644
index 11a7b029..00000000
--- a/.github/workflows/laravel-6.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: "Laravel 6"
-on: [ push ]
-
-jobs:
- build:
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: true
- matrix:
- php: [ "7.3", "7.4", "8.0" ]
- laravel: [ "6.0" ]
-
- name: PHP ${{ matrix.php }}
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php }}
- extensions: curl, mbstring, zip, pcntl, pdo, pdo_sqlite, iconv
- coverage: none
-
- - name: Install dependencies
- run: composer require --dev laravel/framework:^${{ matrix.laravel }}
-
- - name: Execute tests
- run: sudo vendor/bin/phpunit
diff --git a/.github/workflows/laravel-7.yml b/.github/workflows/laravel-7.yml
deleted file mode 100644
index f1af2202..00000000
--- a/.github/workflows/laravel-7.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: "Laravel 7"
-on: [ push ]
-
-jobs:
- build:
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: true
- matrix:
- php: [ "7.3", "7.4", "8.0" ]
- laravel: [ "7.0" ]
-
- name: PHP ${{ matrix.php }}
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php }}
- extensions: curl, mbstring, zip, pcntl, pdo, pdo_sqlite, iconv
- coverage: none
-
- - name: Install dependencies
- run: composer require --dev laravel/framework:^${{ matrix.laravel }}
-
- - name: Execute tests
- run: sudo vendor/bin/phpunit
diff --git a/.github/workflows/laravel-8.yml b/.github/workflows/laravel-8.yml
deleted file mode 100644
index b5ed48a4..00000000
--- a/.github/workflows/laravel-8.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: "Laravel 8"
-on: [ push ]
-
-jobs:
- build:
- runs-on: ubuntu-latest
-
- strategy:
- fail-fast: true
- matrix:
- php: [ "7.3", "7.4", "8.0", "8.1" ]
- laravel: [ "8.0" ]
-
- name: PHP ${{ matrix.php }}
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php }}
- extensions: curl, mbstring, zip, pcntl, pdo, pdo_sqlite, iconv
- coverage: none
-
- - name: Install dependencies
- run: composer require --dev laravel/framework:^${{ matrix.laravel }}
-
- - name: Execute tests
- run: sudo vendor/bin/phpunit
diff --git a/.github/workflows/laravel-9.yml b/.github/workflows/laravel.yml
similarity index 59%
rename from .github/workflows/laravel-9.yml
rename to .github/workflows/laravel.yml
index 508c7620..a1f4763c 100644
--- a/.github/workflows/laravel-9.yml
+++ b/.github/workflows/laravel.yml
@@ -1,4 +1,4 @@
-name: "Laravel 9"
+name: laravel
on: [ push ]
jobs:
@@ -9,9 +9,19 @@ jobs:
fail-fast: true
matrix:
php: [ "8.0", "8.1" ]
- laravel: [ "9.0" ]
+ laravel: [ "7.0", "8.0", "9.0" ]
+ prefer: [ "stable", "lowest" ]
+ exclude:
+ - laravel: "7.0"
+ php: "8.1"
- name: PHP ${{ matrix.php }}
+ - laravel: "7.0"
+ php: "8.2"
+
+ - laravel: "10.0"
+ php: "8.0"
+
+ name: PHP ${{ matrix.php }}, Laravel ${{ matrix.laravel }} ${{ matrix.prefer }}
steps:
- name: Checkout code
@@ -25,7 +35,7 @@ jobs:
coverage: none
- name: Install dependencies
- run: composer require --dev laravel/framework:^${{ matrix.laravel }}
+ run: composer require --dev laravel/framework:^${{ matrix.laravel }} --prefer-${{ matrix.prefer }}
- name: Execute tests
run: sudo vendor/bin/phpunit
diff --git a/.github/workflows/lint-check.yml b/.github/workflows/lint-check.yml
deleted file mode 100644
index cf847b8d..00000000
--- a/.github/workflows/lint-check.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-name: "Code-Style Check"
-
-on: [ push, pull_request ]
-
-jobs:
- check:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Checking PHP Syntax
- uses: TheDragonCode/codestyler@v2.6.2
diff --git a/.github/workflows/lint-fixer.yml b/.github/workflows/lint-fixer.yml
deleted file mode 100644
index 1663da75..00000000
--- a/.github/workflows/lint-fixer.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: "Code-Style Fixer"
-
-on:
- push:
- branches: [ main ]
-
-jobs:
- fix:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Checking PHP Syntax
- uses: TheDragonCode/codestyler@v2.6.2
- with:
- github_token: ${{ secrets.COMPOSER_TOKEN }}
- fix: true
diff --git a/.gitignore b/.gitignore
index ba34f846..227cca8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,16 @@
.idea/
-vendor/
+_site/
build/
+node_modules/
+tmp/
+vendor/
+
+.cache
+.DS_Store
+.env
+.php_cs.cache
+.phpintel
+.temp
*.bak
*.cache
@@ -8,3 +18,4 @@ build/
*.orig
composer.lock
+package-lock.json
diff --git a/.run/build.run.xml b/.run/build.run.xml
new file mode 100644
index 00000000..2c9d697a
--- /dev/null
+++ b/.run/build.run.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/dev.run.xml b/.run/dev.run.xml
new file mode 100644
index 00000000..bf645908
--- /dev/null
+++ b/.run/dev.run.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 1bf0fbbb..b6486978 100644
--- a/README.md
+++ b/README.md
@@ -8,498 +8,12 @@
[![Github Workflow Status][badge_build]][link_build]
[![License][badge_license]][link_license]
-> Actions are like version control for your migration process, allowing your team to modify and share the application's actionable schema. If you have ever had to tell a teammate
-> to manually perform any action on a producton server, you've come across an issue that actions solves.
+> Actions are like version control for your actions process, allowing your team to modify and share the application's actionable schema. If you have ever had to tell a teammate
+> to manually perform any action on a production server, you've come across an issue that actions solves.
-## Installation
+## Documentation
-To get the latest version of Laravel Actions, simply require the project using [Composer](https://getcomposer.org):
-
-```bash
-$ composer require dragon-code/laravel-migration-actions
-```
-
-Or manually update `require` block of `composer.json` and run `composer update`.
-
-```json
-{
- "require": {
- "dragon-code/laravel-migration-actions": "^2.9"
- }
-}
-```
-
-### Upgrade From `dragon-code/laravel-actions`
-
-1. In your `composer.json` file, replace `dragon-code/laravel-actions` with `dragon-code/laravel-migration-actions`.
-3. Run the `command composer` update.
-4. Profit!
-
-### Upgrade From `andrey-helldar/laravel-actions`
-
-1. In your `composer.json` file, replace `"andrey-helldar/laravel-actions": "^1.0"` with `"dragon-code/laravel-migration-actions": "^2.0"`.
-2. Replace the `Helldar\LaravelActions` namespace prefix with `DragonCode\LaravelActions` in your app;
-3. Run the `command composer` update.
-4. Profit!
-
-#### Laravel Framework
-
-Nothing else needs to be done. All is ready 😊
-
-#### Lumen Framework
-
-This package is focused on Laravel development, but it can also be used in Lumen with some workarounds. Because Lumen works a little different, as it is like a barebone version of
-Laravel and the main configuration parameters are instead located in `bootstrap/app.php`, some alterations must be made.
-
-You can install `Laravel Actions` in `app/Providers/AppServiceProvider.php`, and uncommenting this line that registers the App Service Providers so it can properly load.
-
-```
-// $app->register(App\Providers\AppServiceProvider::class);
-```
-
-If you are not using that line, that is usually handy to manage gracefully multiple Lumen installations, you will have to add this line of code under
-the `Register Service Providers` section of your `bootstrap/app.php`.
-
-```php
-$app->register(\DragonCode\LaravelActions\ServiceProvider::class);
-```
-
-## How To Use
-
-### Creating Actions
-
-To create a migration, use the `make:migration:action` Artisan command:
-
-```
-php artisan make:migration:action my_action
-```
-
-The new action will be placed in your `database/actions` directory. Each action file name contains a timestamp, which allows Laravel to determine the order of the actions.
-
-> At the first start, you need to create a table by running the `migrate:actions:install` command.
->
-> If you execute `migrate:actions` with the first command, the `migrate:actions:install` command will be called automatically.
->
-> Starting from version 2.9 the `down` method will not be shown by default when creating actions files. If you need this method, just override it in the class.
-
-#### Automatically Generate A File Name
-
-If you are not worried about the names of your files, then in version [2.6](https://github.com/TheDragonCode/laravel-migration-actions/releases/tag/v2.6.0) we added the ability to
-automatically generate file names.
-
-Just don't include the name attribute when creating the migration.
-
-If a git repository is found in the main folder, then the name of the current active branch will be taken as a prefix:
-
-```bash
-php artisan make:migration:action
-
-### Before Laravel 8.37
-# 2022_01_28_184116_main_1643384476.php
-# 2022_01_28_184117_main_1643384477.php
-# 2022_01_28_184118_crm_2345_1643384478.php
-# 2022_01_28_184119_crm_2345_1643384479.php
-
-### Laravel 8.37 or higher
-# 2022_01_28_184116_main.php
-# 2022_01_28_184117_main.php
-# 2022_01_28_184118_crm_2345.php
-# 2022_01_28_184119_crm_2345.php
-```
-
-If the git repository is not found, then the default prefix will be used:
-
-```bash
-php artisan make:migration:action
-
-### Before Laravel 8.37
-# 2022_01_28_184116_auto_1643384476.php
-# 2022_01_28_184117_auto_1643384477.php
-# 2022_01_28_184118_auto_1643384478.php
-
-### Laravel 8.37 or higher
-# 2022_01_28_184116_auto.php
-# 2022_01_28_184117_auto.php
-# 2022_01_28_184118_auto.php
-```
-
-If you are using Laravel prior to version [8.37](https://github.com/laravel/framework/releases/tag/v8.37.0), then to ensure backward compatibility, if the current git repository
-branch name starts with a number, the `branch` prefix will be automatically added to it:
-
-```bash
-php artisan make:migration:action
-```
-
-```php
-/* 2022_01_28_184116_branch_2x_1643384476.php */
-class Branch2x1643384476 extends Actionable { }
-```
-
-### Running actions
-
-To run all of your outstanding actions, execute the `migrate:actions` Artisan command:
-
-```
-php artisan migrate:actions
-```
-
-#### Forcing Actions To Run In Production
-
-Some action operations are destructive, which means they may cause you to lose data. In order to protect you from running these commands against your production database, you will
-be prompted for confirmation before the commands are executed. To force the commands to run without a prompt, use the `--force` flag:
-
-```
-php artisan migrate:actions --force
-```
-
-#### Execution Every Time
-
-In some cases, you need to call the code every time you deploy the application. For example, to call reindexing.
-
-To do this, override the `$once` variable in the action file:
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- protected $once = false;
-
- public function up(): void
- {
- // your code
- }
-};
-```
-
-If the value is `$once = false`, the `up` method will be called every time the `migrate:actions` command called.
-
-In this case, information about it will not be written to the `migration_actions` table and, therefore, the `down` method will not be called when the rollback command is called.
-
-> Note
->
-> When using the `before` parameter to run command, it is recommended to override the value of the `$before` attribute to `false`, otherwise this action will be executed twice.
-
-#### Execution In A Specific Environment
-
-In some cases, it becomes necessary to execute an action in a specific environment. For example `production`.
-
-For this you can use the `$environment` parameter:
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- /** @var string|array|null */
- protected $environment = 'production';
-
- public function up(): void
- {
- // your code
- }
-};
-```
-
-You can also specify multiple environment names:
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- /** @var string|array|null */
- protected $environment = ['testing', 'staging'];
-
- public function up(): void
- {
- // your code
- }
-};
-```
-
-By default, the action will run in all environments. The same will happen if you specify `null` or `[]` as the value.
-
-#### Execution Excluding Certain Environments
-
-In some cases, it becomes necessary to execute an action excluding certain environments. For example `production`.
-
-For this you can use the `$except_environment` parameter:
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- /** @var string|array|null */
- protected $except_environment = 'production';
-
- public function up(): void
- {
- // your code
- }
-};
-```
-
-You can also specify multiple environment names:
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- /** @var string|array|null */
- protected $except_environment = ['testing', 'staging'];
-
- public function up(): void
- {
- // your code
- }
-};
-```
-
-By default, no actions will be excluded. The same happens if you specify `null` or `[]` value.
-
-#### Split Launch Option
-
-Sometimes it becomes necessary to launch actions separately, for example, to notify about the successful deployment of a project.
-
-There is a `before` option for this when calling actions:
-
-```bash
-php artisan migrate:actions --before
-```
-
-When calling the `migrate:actions` command with the `before` parameter, the script will execute only those actions within which the value of the `before` parameter is `true`.
-
-For backwards compatibility, the `before` parameter is set to `true` by default, but actions will only be executed if the option is explicitly passed.
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- protected $before = false;
-
- public function up(): void
- {
- // your code
- }
-};
-```
-
-For example, you need to call actions when deploying an application. Some actions should be run after the migrations are deployed, and others after the application is fully
-launched.
-
-To run, you need to pass the `before` parameter. For example, when using [`deployer`](https://github.com/deployphp/deployer) it would look like this:
-
-```php
-task('deploy', [
- // ...
- 'artisan:migrate',
- 'artisan:migrate:actions --before', // here
- 'deploy:publish',
- 'php-fpm:reload',
- 'artisan:queue:restart',
- 'artisan:migrate:actions', // here
-]);
-```
-
-Thus, when `migrate:actions` is called, all actions whose `before` parameter is `true` will be executed, and after that, the remaining tasks will be executed.
-
-> Note:
-> If you call the `migrate:actions` command without the `before` parameter, then all tasks will be executed regardless of the value of the `$before` attribute inside the action
-> class.
-
-#### Database Transactions
-
-In some cases, it becomes necessary to undo previously performed actions in the database. For example, when code execution throws an error. To do this, the code must be wrapped in
-a transaction.
-
-By setting the `$transactions = true` parameter, you will ensure that your code is wrapped in a transaction without having to manually call the `DB::transaction()` method. This
-will reduce the time it takes to create the action.
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- protected $transactions = true;
-
- protected $transaction_attempts = 3;
-
- public function up(): void
- {
- // ...
-
- $post = Post::create([
- 'title' => 'Random Title'
- ]);
-
- $post->tags()->sync($ids);
- }
-};
-```
-
-### Rolling Back Actions
-
-To roll back the latest action operation, you may use the `rollback` command. This command rolls back the last "batch" of actions, which may include multiple action files:
-
-```
-php artisan migrate:actions:rollback
-```
-
-You may roll back a limited number of actions by providing the `step` option to the rollback command. For example, the following command will roll back the last five actions:
-
-```
-php artisan migrate:actions:rollback --step=5
-```
-
-The `migrate:actions:reset` command will roll back all of your application's migrations:
-
-```
-php artisan migrate:actions:reset
-```
-
-### Roll Back & Action Using A Single Command
-
-The `migrate:actions:refresh` command will roll back all of your migrations and then execute the `migrate:actions` command. This command effectively re-creates your entire
-database:
-
-```
-php artisan migrate:actions:refresh
-```
-
-You may roll back & re-migrate a limited number of migrations by providing the `step` option to the `refresh` command. For example, the following command will roll back &
-re-migrate the last five migrations:
-
-```
-php artisan migrate:actions:refresh --step=5
-```
-
-### Drop All Actions & Migrate Actions
-
-The `migrate:actions:fresh` command will drop all actions records from the actions table and then execute the migrate command:
-
-```
-php artisan migrate:actions:fresh
-```
-
-### Actions Status
-
-The `migrate:actions:status` command displays the execution status of actions. In it you can see which actions were executed and which were not:
-
-```
-php artisan migrate:actions:status
-```
-
-### Execution Status
-
-You can also override the `success` and `failed` methods, which are called on success or failure processing.
-
-#### If Success
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-use Illuminate\Support\Facade\Log;
-
-return new class extends Actionable
-{
- public function up(): void
- {
- //
- }
-
- public function down(): void
- {
- //
- }
-
- public function success(): void
- {
- Log::info('success');
- }
-
- public function failed(): void
- {
- Log::info('failed');
- }
-};
-```
-
-Call the `php artisan migrate:actions` command.
-
-The log file will contain two `success` entries.
-
-#### If Failed
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-use Exeption;
-use Illuminate\Support\Facade\Log;
-
-return new class extends Actionable
-{
- public function up(): void
- {
- throw new Exeption();
- }
-
- public function down(): void
- {
- throw new Exeption();
- }
-
- public function success(): void
- {
- Log::info('success');
- }
-
- public function failed(): void
- {
- Log::info('failed');
- }
-};
-```
-
-Call the `php artisan migrate:actions` command.
-
-The log file will contain two `failed` entries.
-
-### Artisan Command
-
-Quite often, when working with actions, it becomes necessary to run one or another console command, and each time you have to write the following code:
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-use Illuminate\Support\Facades\Artisan;
-
-return new class extends Actionable
-{
- public function up()
- {
- Artisan::call('command-name', [
- // parameters
- ]);
- }
-};
-```
-
-Since version [`2.3`](https://github.com/TheDragonCode/laravel-migration-actions/releases/tag/v2.3.0) we have added a method call. Now calling commands has become much easier:
-
-```php
-use DragonCode\LaravelActions\Support\Actionable;
-
-return new class extends Actionable
-{
- public function up()
- {
- $this->artisan('command-name', [
- // parameters
- ]);
- }
-};
-```
+See the [documentation](docs/index.md) for detailed installation and usage instructions.
## License
diff --git a/composer.json b/composer.json
index b9b158bd..557d3dc6 100644
--- a/composer.json
+++ b/composer.json
@@ -24,19 +24,42 @@
"issues": "https://github.com/TheDragonCode/laravel-migration-actions/issues",
"source": "https://github.com/TheDragonCode/laravel-migration-actions"
},
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/TheDragonCode"
+ },
+ {
+ "type": "open_collective",
+ "url": "https://opencollective.com/dragon-code"
+ },
+ {
+ "type": "boosty",
+ "url": "https://boosty.to/dragon-code"
+ },
+ {
+ "type": "yoomoney",
+ "url": "https://yoomoney.ru/to/410012608840929"
+ }
+ ],
"require": {
- "php": "^7.3 || ^8.0",
- "dragon-code/contracts": "^2.15",
- "dragon-code/laravel-support": "^3.3",
- "illuminate/console": "^6.0 || ^7.0 || ^8.0 || ^9.0",
- "illuminate/database": "^6.0 || ^7.0 || ^8.0 || ^9.0",
- "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0",
- "symfony/console": "^4.3 || ^5.0 || ^6.0"
+ "php": "^8.0.2",
+ "composer-runtime-api": "^2.2",
+ "doctrine/dbal": "^2.13 || ^3.4",
+ "dragon-code/laravel-support": "^3.4",
+ "dragon-code/simple-dto": "^2.5.1",
+ "dragon-code/support": "^6.6",
+ "illuminate/console": "^7.30.6 || ^8.75 || ^9.0",
+ "illuminate/container": "^7.30.6 || ^8.75 || ^9.0",
+ "illuminate/database": "^7.30.6 || ^8.75 || ^9.0",
+ "illuminate/support": "^7.30.6 || ^8.75 || ^9.0",
+ "symfony/console": "^5.3 || ^6.0"
},
"require-dev": {
"mockery/mockery": "^1.3.1",
- "orchestra/testbench": "^4.0 || ^5.0 || ^6.0 || ^7.0",
- "phpunit/phpunit": "^8.0 || ^9.0",
+ "nesbot/carbon": "^2.62.1",
+ "orchestra/testbench": "^5.20 || ^6.25 || ^7.9",
+ "phpunit/phpunit": "^9.5",
"ramsey/uuid": "^3.7 || ^4.0"
},
"conflict": {
diff --git a/config/actions.php b/config/actions.php
new file mode 100644
index 00000000..82d8321f
--- /dev/null
+++ b/config/actions.php
@@ -0,0 +1,39 @@
+ env('DB_CONNECTION'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Actions Repository Table
+ |--------------------------------------------------------------------------
+ |
+ | This table keeps track of all the actions that have already run for
+ | your application. Using this information, we can determine which of
+ | the actions on disk haven't actually been run in the database.
+ |
+ */
+
+ 'table' => 'migration_actions',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Actions Path
+ |--------------------------------------------------------------------------
+ |
+ | This option defines the path to the action directory.
+ |
+ */
+
+ 'path' => base_path('actions'),
+];
diff --git a/config/database.php b/config/database.php
deleted file mode 100644
index 1cda7188..00000000
--- a/config/database.php
+++ /dev/null
@@ -1,16 +0,0 @@
- 'migration_actions',
-];
diff --git a/database/migrations/anonymous/2022_08_18_180137_change_migration_actions_table.php b/database/migrations/anonymous/2022_08_18_180137_change_migration_actions_table.php
new file mode 100644
index 00000000..467330e1
--- /dev/null
+++ b/database/migrations/anonymous/2022_08_18_180137_change_migration_actions_table.php
@@ -0,0 +1,7 @@
+
+ fs.statSync(path.join(dir, item)).isFile() &&
+ ! names.includes(item.toLowerCase()) &&
+ extension.includes(path.extname(item))
+ )
+ .sort((a, b) => {
+ a = resolveNumeric(a)
+ b = resolveNumeric(b)
+
+ if (a < b) return sort === 'asc' ? -1 : 1
+ if (a > b) return sort === 'asc' ? 1 : -1
+
+ return 0
+ }).map(item => `/${ folder }/${ item }`)
+}
+
+function resolveNumeric(value) {
+ const sub = value.substring(0, value.indexOf('.'))
+
+ const num = Number(sub)
+
+ return isNaN(num) ? value : num
+}
diff --git a/docs/.vuepress/public/CNAME b/docs/.vuepress/public/CNAME
new file mode 100644
index 00000000..4e605bca
--- /dev/null
+++ b/docs/.vuepress/public/CNAME
@@ -0,0 +1 @@
+actions.dragon-code.pro
diff --git a/docs/.vuepress/public/fonts/Nunito-SemiBold.woff2 b/docs/.vuepress/public/fonts/Nunito-SemiBold.woff2
new file mode 100644
index 00000000..0f41dd93
Binary files /dev/null and b/docs/.vuepress/public/fonts/Nunito-SemiBold.woff2 differ
diff --git a/docs/.vuepress/public/images/logo.svg b/docs/.vuepress/public/images/logo.svg
new file mode 100644
index 00000000..96a5a57a
--- /dev/null
+++ b/docs/.vuepress/public/images/logo.svg
@@ -0,0 +1,63 @@
+
+
+
diff --git a/docs/.vuepress/styles/_fonts.scss b/docs/.vuepress/styles/_fonts.scss
new file mode 100644
index 00000000..8299f17b
--- /dev/null
+++ b/docs/.vuepress/styles/_fonts.scss
@@ -0,0 +1,9 @@
+@charset "UTF-8";
+
+@font-face {
+ font-family: 'Nunito';
+ src: local('Nunito'), url(/fonts/Nunito-SemiBold.woff2) format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
diff --git a/docs/.vuepress/styles/index.scss b/docs/.vuepress/styles/index.scss
new file mode 100644
index 00000000..ea2a8670
--- /dev/null
+++ b/docs/.vuepress/styles/index.scss
@@ -0,0 +1,13 @@
+@charset "UTF-8";
+
+@import 'fonts';
+
+:root {
+ --content-width: 800px;
+}
+
+.code-group {
+ &__nav-tab {
+ font-family: Nunito, system-ui, sans-serif;
+ }
+}
diff --git a/docs/getting-started/installation/index.md b/docs/getting-started/installation/index.md
new file mode 100644
index 00000000..f2e14d55
--- /dev/null
+++ b/docs/getting-started/installation/index.md
@@ -0,0 +1,45 @@
+# Installation
+
+To get the latest version of Laravel Actions, simply require the project using [Composer](https://getcomposer.org):
+
+```bash
+composer require dragon-code/laravel-migration-actions
+```
+
+Or manually update `require` block of `composer.json` and run `composer update` console command.
+
+```json
+{
+ "require": {
+ "dragon-code/laravel-migration-actions": "^3.0"
+ }
+}
+```
+
+## Laravel Framework
+
+Run the `php artisan vendor:publish --provider="DragonCode\LaravelActions\ServiceProvider"` console command for the config file publishing.
+
+## Lumen Framework
+
+This package is focused on Laravel development, but it can also be used in Lumen with some workarounds. Because Lumen works a little different, as it is like a barebone version of
+Laravel and the main configuration parameters are instead located in `bootstrap/app.php`, some alterations must be made.
+
+You can install `Laravel Actions` in `app/Providers/AppServiceProvider.php`, and uncommenting this line that registers the App Service Providers so it can properly load.
+
+```php
+// $app->register(App\Providers\AppServiceProvider::class);
+```
+
+If you are not using that line, that is usually handy to manage gracefully multiple Lumen installations, you will have to add this line of code under
+the `Register Service Providers` section of your `bootstrap/app.php`.
+
+```php
+$app->register(\DragonCode\LaravelActions\ServiceProvider::class);
+```
+
+Next, you can copy the config file:
+
+```bash
+cp vendor/dragon-code/laravel-migration-actions/config/actions.php config/actions.php
+```
diff --git a/docs/helpers/artisan.md b/docs/helpers/artisan.md
new file mode 100644
index 00000000..ba4458fe
--- /dev/null
+++ b/docs/helpers/artisan.md
@@ -0,0 +1,17 @@
+# Artisan Command
+
+Quite often, when working with actions, it becomes necessary to run one or another console command, and each time you have to write the following code:
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ public function __invoke(): void
+ {
+ $this->artisan('some_command', [
+ // parameters
+ ]);
+ }
+};
+```
diff --git a/docs/helpers/events.md b/docs/helpers/events.md
new file mode 100644
index 00000000..fa3cc576
--- /dev/null
+++ b/docs/helpers/events.md
@@ -0,0 +1,51 @@
+# Events
+
+You can also handle events when executing actions:
+
+```
+DragonCode\LaravelActions\Events\ActionStarted
+DragonCode\LaravelActions\Events\ActionEnded
+DragonCode\LaravelActions\Events\ActionFailed
+DragonCode\LaravelActions\Events\NoPendingActions
+```
+
+If there are no action files to execute, the `NoPendingActions` event will be sent.
+
+In other cases, the `ActionStarted` event will be sent before processing starts, and the `ActionEnded` event will be sent after processing.
+
+For example:
+
+```php
+namespace App\Providers;
+
+use App\Listeners\SomeActionsListener;
+use DragonCode\LaravelActions\Events\ActionEnded;
+use DragonCode\LaravelActions\Events\ActionStarted;
+use DragonCode\LaravelActions\Events\NoPendingActions;
+use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
+
+class EventServiceProvider extends ServiceProvider
+{
+ protected $listen = [
+ ActionStarted::class => [SomeActionsListener::class],
+ ActionEnded::class => [SomeActionsListener::class],
+ ActionFailed::class => [SomeActionsListener::class],
+ NoPendingActions::class => [SomeActionsListener::class],
+ ];
+}
+```
+
+```php
+namespace App\Listeners;
+
+use DragonCode\LaravelActions\Events\BaseEvent;
+
+class SomeActionsListener
+{
+ public function handle(BaseEvent $event): void
+ {
+ $method = $event->method; // `up` or `down` string value
+ $isBefore = $event->before; // boolean
+ }
+}
+```
diff --git a/docs/helpers/execution-status.md b/docs/helpers/execution-status.md
new file mode 100644
index 00000000..a93b2d0d
--- /dev/null
+++ b/docs/helpers/execution-status.md
@@ -0,0 +1,71 @@
+# Execution Status
+
+You can also override the `success` and `failed` methods, which are called on success or failure processing.
+
+## If Success
+
+```php
+use DragonCode\LaravelActions\Action;use Illuminate\Support\Facade\Log;
+
+return new class () extends Action
+{
+ public function up(): void
+ {
+ //
+ }
+
+ public function down(): void
+ {
+ //
+ }
+
+ public function success(): void
+ {
+ Log::info('success');
+ }
+
+ public function failed(): void
+ {
+ Log::info('failed');
+ }
+};
+```
+
+Call the `php artisan migrate:actions` command.
+
+The log file will contain two `success` entries.
+
+## If Failed
+
+```php
+use DragonCode\LaravelActions\Action;
+use Exeption;
+use Illuminate\Support\Facade\Log;
+
+return new class extends Action
+{
+ public function up(): void
+ {
+ throw new Exeption();
+ }
+
+ public function down(): void
+ {
+ throw new Exeption();
+ }
+
+ public function success(): void
+ {
+ Log::info('success');
+ }
+
+ public function failed(): void
+ {
+ Log::info('failed');
+ }
+};
+```
+
+Call the `php artisan migrate:actions` command.
+
+The log file will contain two `failed` entries.
diff --git a/docs/how-to-use/creating.md b/docs/how-to-use/creating.md
new file mode 100644
index 00000000..9dc1879e
--- /dev/null
+++ b/docs/how-to-use/creating.md
@@ -0,0 +1,133 @@
+# Creating Actions
+
+To create an action use the `make:migration:action` artisan command:
+
+```bash
+php artisan make:migration:action some_name
+```
+
+The new action's file will be placed in your `actions` directory in the base path of your app.
+
+Each action file name contains a timestamp, which allows Laravel to determine the order of the actions.
+
+
+## Automatically Generate A File Name
+
+If you do not specify the "name" attribute, then the file name will be generated automatically according to the rule:
+
+> git branch name ?: 'auto'
+
+```bash
+php artisan make:migration:action
+
+### When the git repository is found (`base_path('.git')` directory is exists) and HEAD branch name is 'qwerty'
+# 2022_10_11_225116_qwerty.php
+# 2022_10_11_225118_qwerty.php
+# 2022_10_11_225227_qwerty.php
+
+### When the git repository is not found (`base_path('.git')` directory doesn't exists).
+# 2022_10_11_225116_auto.php
+# 2022_10_11_225118_auto.php
+# 2022_10_11_225227_auto.php
+```
+
+## Nested Files
+
+You can use nested paths to create actions:
+
+```bash
+php artisan make:migration:action Foo/Bar/QweRty
+php artisan make:migration:action Foo/Bar/QweRty.php
+
+php artisan make:migration:action Foo\Bar\QweRty
+php artisan make:migration:action Foo\Bar\QweRty.php
+
+php artisan make:migration:action foo\bar\QweRty
+php artisan make:migration:action foo\bar\QweRty.php
+```
+
+All of these commands will create a file called `actions/foo/bar/Y_m_d_His_qwe_rty.php`.
+
+For example:
+
+```bash
+php artisan make:migration:action foo\bar\QweRty
+# actions/foo/bar/2022_10_11_225734_qwe_rty.php
+
+php artisan make:migration:action foo\bar\QweRty.php
+# actions/foo/bar/2022_10_11_225734_qwe_rty.php
+
+php artisan make:migration:action foo/bar/QweRty
+# actions/foo/bar/2022_10_11_225734_qwe_rty.php
+
+php artisan make:migration:action foo/bar/QweRty.php
+# actions/foo/bar/2022_10_11_225734_qwe_rty.php
+```
+
+## Invokable Method
+
+By default, the new action class will contain the `__invoke` method, but you can easily replace it with public `up` name.
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
+
+> Note that the `__invoke` method has been added as a single call.
+> This means that when the action is running, it will be called, but not when it is rolled back.
+>
+> You should also pay attention to the fact that if there is an `__invoke` method in the class, the `down` method will not be called.
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ public function __invoke(): void {} // called when `php artisan migrate:actions` running
+
+ public function down(): void {} // doesn't call when `php artisan migrate:rollback` running
+ // and any other commands to revert the action.
+};
+```
+
+## Dependency Injection
+
+You can also use the dependency injection with `__invoke`, `up` and `down` methods:
+
+```php
+use DragonCode\LaravelActions\Action;
+use Tests\Concerns\Some;
+
+return new class () extends Action
+{
+ public function __invoke(Some $some): void
+ {
+ $value = $some->get('qwerty');
+ }
+};
+```
+
+```php
+use DragonCode\LaravelActions\Action;
+use Tests\Concerns\Some;
+
+return new class () extends Action
+{
+ public function up(Some $some): void
+ {
+ $value = $some->get('qwerty');
+ }
+
+ public function down(Some $some): void
+ {
+ $value = $some->get('qwerty');
+ }
+};
+```
diff --git a/docs/how-to-use/rollback.md b/docs/how-to-use/rollback.md
new file mode 100644
index 00000000..7044da3b
--- /dev/null
+++ b/docs/how-to-use/rollback.md
@@ -0,0 +1,71 @@
+# Rolling Back Actions
+
+To roll back the latest action operation, you may use the `rollback` command. This command rolls back the last "batch" of actions, which may include multiple action files:
+
+```
+php artisan migrate:actions:rollback
+```
+
+You may roll back a limited number of actions by providing the `step` option to the rollback command. For example, the following command will roll back the last five actions:
+
+```
+php artisan migrate:actions:rollback --step=5
+```
+
+The `migrate:actions:reset` command will roll back all of your application's migrations:
+
+```
+php artisan migrate:actions:reset
+```
+
+For example:
+
+```bash
+php artisan migrate:actions:rollback
+# action batch
+# 2022_10_12_021837_some 1
+# 2022_10_12_021838_some 2
+# 2022_10_12_021839_some 2
+# 2022_10_12_021840_some 3 // will be canceled
+# 2022_10_12_021841_some 3 // will be canceled
+
+php artisan migrate:actions:rollback --step=1
+# action batch
+# 2022_10_12_021837_some 1
+# 2022_10_12_021838_some 2
+# 2022_10_12_021839_some 2
+# 2022_10_12_021840_some 3 // will be canceled
+# 2022_10_12_021841_some 3 // will be canceled
+
+php artisan migrate:actions:rollback --step=2
+# action batch
+# 2022_10_12_021837_some 1
+# 2022_10_12_021838_some 2 // will be canceled
+# 2022_10_12_021839_some 2 // will be canceled
+# 2022_10_12_021840_some 3 // will be canceled
+# 2022_10_12_021841_some 3 // will be canceled
+```
+
+## Roll Back & Action Using A Single Command
+
+The `migrate:actions:refresh` command will roll back all of your migrations and then execute the `migrate:actions` command. This command effectively re-creates your entire
+database:
+
+```
+php artisan migrate:actions:refresh
+```
+
+You may roll back & re-migrate a limited number of migrations by providing the `step` option to the `refresh` command. For example, the following command will roll back &
+re-migrate the last five migrations:
+
+```
+php artisan migrate:actions:refresh --step=5
+```
+
+## Drop All Actions & Rerun Actions
+
+The `migrate:actions:fresh` command will drop all actions records from the actions table and then execute the migrate command:
+
+```
+php artisan migrate:actions:fresh
+```
diff --git a/docs/how-to-use/running.md b/docs/how-to-use/running.md
new file mode 100644
index 00000000..bad1eadf
--- /dev/null
+++ b/docs/how-to-use/running.md
@@ -0,0 +1,203 @@
+# Running Actions
+
+To run all of your outstanding actions, execute the `migrate:actions` artisan command:
+
+```bash
+php artisan migrate:actions
+```
+
+## Split Launch Option
+
+Sometimes it becomes necessary to launch actions separately, for example, to notify about the successful deployment of a project.
+
+There is a `before` option for this when calling actions:
+
+```bash
+php artisan migrate:actions --before
+```
+
+When calling the `migrate:actions` command with the `before` parameter, the script will execute only those actions within which the value of the `before` parameter is `true`.
+
+For backwards compatibility, the `before` parameter is set to `true` by default, but actions will only be executed if the option is explicitly passed.
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ protected $before = false;
+
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
+
+For example, you need to call actions when deploying an application. Some actions should be run after the migrations are deployed, and others after the application is fully
+launched.
+
+To run, you need to pass the `before` parameter. For example, when using [`deployer`](https://github.com/deployphp/deployer) it would look like this:
+
+```php
+task('deploy', [
+ // ...
+ 'artisan:migrate',
+ 'artisan:migrate:actions --before', // here
+ 'deploy:publish',
+ 'php-fpm:reload',
+ 'artisan:queue:restart',
+ 'artisan:migrate:actions', // here
+]);
+```
+
+Thus, when `migrate:actions` is called, all actions whose `before` parameter is `true` will be executed, and after that, the remaining tasks will be executed.
+
+> Note:
+> If you call the `migrate:actions` command without the `before` parameter,
+> then all tasks will be executed regardless of the value of the `$before`
+> attribute inside the action class.
+
+## Forcing Actions To Run In Production
+
+> Some commands cannot be executed in production without confirmation.
+> These include all commands except `migrate:actions:status` and `migrate:actions`.
+
+Some action operations are destructive, which means they may cause you to lose data. In order to protect you from running these commands against your production database,
+you will be prompted for confirmation before the commands are executed. To force the commands to run without a prompt, use the `--force` flag:
+
+```bash
+php artisan migrate:actions:install --force
+```
+
+## Execution Every Time
+
+In some cases, you need to call the code every time you deploy the application. For example, to call reindexing.
+
+To do this, override the `$once` variable in the action file:
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ protected $once = false;
+
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
+
+If the value is `$once = false`, the `up` method will be called every time the `migrate:actions` command called.
+
+In this case, information about it will not be written to the `migration_actions` table and, therefore, the `down` method will not be called when the rollback command is called.
+
+> Note
+>
+> When using the `before` parameter to run command, it is recommended to override the value of the `$before` attribute to `false`, otherwise this action will be executed twice.
+
+## Execution In A Specific Environment
+
+In some cases, it becomes necessary to execute an action in a specific environment. For example `production`.
+
+For this you can use the `$environment` parameter:
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ /** @var string|array|null */
+ protected $environment = 'production';
+
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
+
+You can also specify multiple environment names:
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ /** @var string|array|null */
+ protected $environment = ['testing', 'staging'];
+
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
+
+By default, the action will run in all environments. The same will happen if you specify `null` or `[]` as the value.
+
+## Execution Excluding Certain Environments
+
+In some cases, it becomes necessary to execute an action excluding certain environments. For example `production`.
+
+For this you can use the `$except_environment` parameter:
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ /** @var string|array|null */
+ protected $exceptEnvironment = 'production';
+
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
+
+You can also specify multiple environment names:
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ /** @var string|array|null */
+ protected $exceptEnvironment = ['testing', 'staging'];
+
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
+
+By default, no actions will be excluded. The same happens if you specify `null` or `[]` value.
+
+## Database Transactions
+
+In some cases, it becomes necessary to undo previously performed actions in the database. For example, when code execution throws an error. To do this, the code must be wrapped in
+a transaction.
+
+By setting the `$transactions = true` parameter, you will ensure that your code is wrapped in a transaction without having to manually call the `DB::transaction()` method. This
+will reduce the time it takes to create the action.
+
+```php
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action
+{
+ protected $transactions = true;
+
+ protected $transactionAttempts = 3;
+
+ public function __invoke(): void
+ {
+ // some code
+ }
+};
+```
diff --git a/docs/how-to-use/status.md b/docs/how-to-use/status.md
new file mode 100644
index 00000000..3e170404
--- /dev/null
+++ b/docs/how-to-use/status.md
@@ -0,0 +1,7 @@
+# Actions Status
+
+The `migrate:actions:status` command displays the execution status of actions. In it you can see which actions were executed and which were not:
+
+```
+php artisan migrate:actions:status
+```
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..624d4aaf
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,49 @@
+# Laravel Migration Actions
+
+
+
+[![Stable Version][badge_stable]][link_packagist]
+[![Unstable Version][badge_unstable]][link_packagist]
+[![Total Downloads][badge_downloads]][link_packagist]
+[![Github Workflow Status][badge_build]][link_build]
+[![License][badge_license]][link_license]
+
+> Actions are like version control for your actions process, allowing your team to modify and share the application's actionable schema. If you have ever had to tell a teammate
+> to manually perform any action on a production server, you've come across an issue that actions solves.
+
+## Table of contents
+
+* Prologue
+ * [Upgrade Guide](prologue/upgrade.md)
+* Getting Started
+ * [Installation](getting-started/installation/index.md)
+ * How to use
+ * [Creating](how-to-use/creating.md)
+ * [Running Actions](how-to-use/running.md)
+ * [Rolling Back](how-to-use/rollback.md)
+ * [Status](how-to-use/status.md)
+ * Helpers
+ * [Execution Status](helpers/execution-status.md)
+ * [Events](helpers/events.md)
+ * [Artisan Command](helpers/artisan.md)
+
+## License
+
+This package is licensed under the [MIT License](prologue/license.md).
+
+
+[badge_build]: https://img.shields.io/github/workflow/status/TheDragonCode/laravel-migration-actions/phpunit?style=flat-square
+
+[badge_downloads]: https://img.shields.io/packagist/dt/dragon-code/laravel-migration-actions.svg?style=flat-square
+
+[badge_license]: https://img.shields.io/packagist/l/dragon-code/laravel-migration-actions.svg?style=flat-square
+
+[badge_stable]: https://img.shields.io/github/v/release/TheDragonCode/laravel-migration-actions?label=stable&style=flat-square
+
+[badge_unstable]: https://img.shields.io/badge/unstable-dev--main-orange?style=flat-square
+
+[link_build]: https://github.com/TheDragonCode/laravel-migration-actions/actions
+
+[link_license]: prologue/license.md
+
+[link_packagist]: https://packagist.org/packages/dragon-code/laravel-migration-actions
diff --git a/docs/prologue/changelog/3.x.md b/docs/prologue/changelog/3.x.md
new file mode 100644
index 00000000..7d5c0e7e
--- /dev/null
+++ b/docs/prologue/changelog/3.x.md
@@ -0,0 +1,5 @@
+# 3.x
+
+# 3.0.0
+
+- Coming Soon
diff --git a/docs/prologue/changelog/index.md b/docs/prologue/changelog/index.md
new file mode 100644
index 00000000..f190dbd7
--- /dev/null
+++ b/docs/prologue/changelog/index.md
@@ -0,0 +1,3 @@
+# Changelog
+
+- [3.x](3.x.md)
diff --git a/docs/prologue/license.md b/docs/prologue/license.md
new file mode 100644
index 00000000..9697f77c
--- /dev/null
+++ b/docs/prologue/license.md
@@ -0,0 +1,21 @@
+# MIT License
+
+Copyright (c) 2022 Andrey Helldar
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/docs/prologue/upgrade.md b/docs/prologue/upgrade.md
new file mode 100644
index 00000000..baaa0261
--- /dev/null
+++ b/docs/prologue/upgrade.md
@@ -0,0 +1,93 @@
+# Upgrade Guide
+
+## High Impact Changes
+
+- Replacing named classes with anonymous ones
+- Change the location of the configuration file
+- Changing the namespace of the parent class
+- Changing variable names from `snake_case` to `camelCase`
+- Added recursive search for actions in a folder
+- PHP 7.3 and 7.4 was dropped
+- Laravel 6.0 was dropped
+- Dragon Code: Contracts (`dragon-code/contracts`) was dropped
+
+## Medium Impact Changes
+
+- Changing the name of an action column in the database
+- Action storage directory changed
+
+## Upgrading To 3.x from 2.x
+
+### Updating Dependencies
+
+#### PHP 8.0.2 Required
+
+Laravel Actions now requires PHP 8.0.2 or greater.
+
+#### Composer Dependencies
+
+You should update the following dependency in your application's `composer.json` file:
+
+- `dragon-code/laravel-migration-actions` to `^3.0`
+
+### Call Upgrade Command
+
+For your convenience, we have created an upgrade console command:
+
+```bash
+php artisan migrate:actions:upgrade
+```
+
+It will do the following:
+
+- Change the namespace of the abstract class
+- Add a strict type declaration
+- Replace the `up` method with `__invoke` if the class does not have a `down` method
+- Replace named classes with anonymous ones
+- Create a configuration file according to the data saved in your project
+
+> Note
+> If you used inheritance of actions from other actions, then you will need to process these files manually.
+
+### Configuration
+
+Publish the config file and migrate the settings from the `config/database.php` file.
+
+```bash
+php artisan vendor:publish --provider="DragonCode\LaravelActions\ServiceProvider"
+```
+
+### Actions Location
+
+Move the action files to the `actions` folder in the project root, or update the `actions.path` option in the configuration file.
+
+
+### Parent Namespace
+
+Replace `DragonCode\LaravelActions\Support\Actionable` with `DragonCode\LaravelActions\Action`.
+
+### Anonymous Classes
+
+Replace named calls to your application's classes with anonymous ones.
+
+For example:
+
+```php
+// before
+use DragonCode\LaravelActions\Support\Actionable;
+
+class Some extends Actionable {}
+
+// after
+use DragonCode\LaravelActions\Action;
+
+return new class () extends Action {};
+```
+
+### Invokable Method
+
+If your class does not contain a `down` method, then you can replace the `up` method with `__invoke`.
+
+### Changed Migration Repository
+
+Just call the `php artisan migrate` command to make changes to the action repository table.
diff --git a/ide.json b/ide.json
index 0182c9d1..6e27b12b 100644
--- a/ide.json
+++ b/ide.json
@@ -7,29 +7,11 @@
"inputFilter": "migration",
"files": [
{
- "directory": "/database/actions",
+ "directory": "/actions",
"name": "${CURRENT_TIME|format:yyyy_MM_dd_HHmmss}_${INPUT_CLASS|className|snakeCase}.php",
"template": {
"type": "stub",
- "path": "resources/stubs/action-named.stub",
- "parameters": {
- "DummyClass": "${INPUT_FQN|className}"
- }
- }
- }
- ]
- },
- {
- "id": "dragon-code.create-anonymous-action",
- "name": "Create Anonymous Migration Action",
- "inputFilter": "migration",
- "files": [
- {
- "directory": "/database/actions",
- "name": "${CURRENT_TIME|format:yyyy_MM_dd_HHmmss}_${INPUT_CLASS|className|snakeCase}.php",
- "template": {
- "type": "stub",
- "path": "resources/stubs/action-anonymous.stub"
+ "path": "resources/stubs/action.stub"
}
}
]
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..511db31a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "docs",
+ "version": "1.0.0",
+ "description": "Performing actions with saving the list of called files",
+ "author": "Andrey Helldar ",
+ "license": "MIT",
+ "homepage": "https://github.com/TheDragonCode/laravel-migration-actions",
+ "bugs": {
+ "url": "https://github.com/TheDragonCode/laravel-migration-actions/issues"
+ },
+ "scripts": {
+ "dev": "vuepress dev docs --debug",
+ "build": "vuepress build docs"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/TheDragonCode/laravel-migration-actions.git"
+ },
+ "devDependencies": {
+ "@vuepress/plugin-theme-data": "^2.0.0-beta.51",
+ "@vueuse/core": "^7.5.5",
+ "dotenv": "^15.0.0",
+ "vuepress": "^2.0.0-beta.51"
+ },
+ "engines": {
+ "node": ">=16.16"
+ }
+}
diff --git a/resources/stubs/action-anonymous.stub b/resources/stubs/action-anonymous.stub
deleted file mode 100644
index 09847ca5..00000000
--- a/resources/stubs/action-anonymous.stub
+++ /dev/null
@@ -1,15 +0,0 @@
-transaction_attempts;
+ return $this->transactionAttempts;
}
/**
@@ -115,7 +107,7 @@ public function onEnvironment(): array
*/
public function exceptEnvironment(): array
{
- return Arr::wrap($this->except_environment);
+ return Arr::wrap($this->exceptEnvironment);
}
/**
diff --git a/src/Concerns/About.php b/src/Concerns/About.php
new file mode 100644
index 00000000..9e0d3121
--- /dev/null
+++ b/src/Concerns/About.php
@@ -0,0 +1,50 @@
+getPackageName(), fn () => [
+ 'Version' => $this->getPackageVersion(),
+ ]);
+ }
+ }
+
+ protected function getPackageName(): string
+ {
+ return Str::of($this->loadPackageName())
+ ->after('/')
+ ->snake()
+ ->replace('_', ' ')
+ ->title()
+ ->toString();
+ }
+
+ protected function getPackageVersion(): string
+ {
+ return InstalledVersions::getPrettyVersion($this->loadPackageName());
+ }
+
+ protected function loadPackageName(): string
+ {
+ if (! is_null($this->packageName)) {
+ return $this->packageName;
+ }
+
+ return $this->packageName = Arr::ofFile($this->composer)->get('name');
+ }
+}
diff --git a/src/Concerns/Anonymous.php b/src/Concerns/Anonymous.php
index a33a3b74..5b957646 100644
--- a/src/Concerns/Anonymous.php
+++ b/src/Concerns/Anonymous.php
@@ -1,20 +1,13 @@
allowAnonymous();
+ return AppVersion::is('8.37');
}
}
diff --git a/src/Concerns/Argumentable.php b/src/Concerns/Argumentable.php
deleted file mode 100644
index f8c2ec33..00000000
--- a/src/Concerns/Argumentable.php
+++ /dev/null
@@ -1,51 +0,0 @@
-argument('name')) {
- return trim($name);
- }
-
- return $this->makeName();
- }
-
- protected function makeName(): string
- {
- if ($this->allowAnonymous()) {
- return $this->getAutoPrefix();
- }
-
- return $this->getAutoPrefix() . '_' . time();
- }
-
- protected function getAutoPrefix(): string
- {
- return $this->getGitBranchName() ?: $this->auto_prefix;
- }
-
- protected function getGitBranchName(): ?string
- {
- $name = Git::currentBranch(base_path('.git'));
-
- preg_match('/^\d.*$/', $name, $output);
-
- if (! empty($output) && $this->disallowAnonymous()) {
- return $this->branch_prefix . '_' . $name;
- }
-
- return $name;
- }
-}
diff --git a/src/Concerns/Artisan.php b/src/Concerns/Artisan.php
index 5cf56103..d25af9c4 100644
--- a/src/Concerns/Artisan.php
+++ b/src/Concerns/Artisan.php
@@ -4,7 +4,7 @@
namespace DragonCode\LaravelActions\Concerns;
-use Illuminate\Support\Facades\Artisan as ArtisanSupport;
+use Illuminate\Support\Facades\Artisan as Command;
trait Artisan
{
@@ -18,6 +18,6 @@ trait Artisan
*/
protected function artisan(string $command, array $parameters = []): void
{
- ArtisanSupport::call($command, $parameters);
+ Command::call($command, $parameters);
}
}
diff --git a/src/Concerns/ConfirmableTrait.php b/src/Concerns/ConfirmableTrait.php
new file mode 100644
index 00000000..06ab4714
--- /dev/null
+++ b/src/Concerns/ConfirmableTrait.php
@@ -0,0 +1,19 @@
+secure || $this->confirmToProceed();
+ }
+}
diff --git a/src/Concerns/Database.php b/src/Concerns/Database.php
deleted file mode 100644
index b8d8acae..00000000
--- a/src/Concerns/Database.php
+++ /dev/null
@@ -1,21 +0,0 @@
-laravel->databasePath('actions');
- }
-
- protected function getMigrationPaths(): array
- {
- if ($paths = $this->optionPath()) {
- return $paths;
- }
-
- return [$this->getMigrationPath()];
- }
-}
diff --git a/src/Concerns/Infoable.php b/src/Concerns/Infoable.php
deleted file mode 100644
index 7c4af5ba..00000000
--- a/src/Concerns/Infoable.php
+++ /dev/null
@@ -1,39 +0,0 @@
-output) {
- $string = Information::replace($string);
-
- $styled = $style ? "<$style>$string$style>" : $string;
-
- $this->output->writeln($styled, $this->parsedVerbosity($verbosity));
- }
- }
-
- protected function note($message)
- {
- $this->line($message);
- }
-
- protected function parsedVerbosity($verbosity = null)
- {
- return method_exists($this, 'parseVerbosity')
- ? $this->parseVerbosity($verbosity)
- : OutputInterface::VERBOSITY_NORMAL;
- }
-}
diff --git a/src/Concerns/Optionable.php b/src/Concerns/Optionable.php
index 3e29bc78..14357b28 100644
--- a/src/Concerns/Optionable.php
+++ b/src/Concerns/Optionable.php
@@ -1,49 +1,59 @@
input->getOption('before');
+ $this->specifyParameters();
}
- protected function optionDatabase(): ?string
+ protected function getOptions(): array
{
- return $this->input->getOption('database');
+ return Arr::of($this->availableOptions())
+ ->filter(fn (array $option) => in_array($option[0], $this->options))
+ ->toArray();
}
- protected function optionStep(?int $default = null): ?int
+ protected function getArguments(): array
{
- return $this->input->getOption('step') ?: $default;
+ return Arr::of($this->availableArguments())
+ ->filter(fn (array $argument) => in_array($argument[0], $this->arguments))
+ ->toArray();
}
- protected function optionPath(): ?array
+ protected function availableOptions(): array
{
- if (! $this->hasOption('path')) {
- return null;
- }
-
- if ($path = $this->option('path')) {
- return collect($path)->map(function ($path) {
- if ($this->usingRealPath()) {
- return $path;
- }
-
- $filename = $this->getMigrationPath() . DIRECTORY_SEPARATOR . $path;
-
- if (is_dir($filename) || file_exists($filename)) {
- return $filename;
- }
-
- return Str::finish($filename, '.php');
- })->all();
- }
+ return [
+ [Options::BEFORE, null, InputOption::VALUE_NONE, 'Run actions marked as before'],
+ [Options::CONNECTION, null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
+ [Options::FORCE, null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
+ [Options::PATH, null, InputOption::VALUE_OPTIONAL, 'The path to the actions files to be executed'],
+ [Options::REALPATH, null, InputOption::VALUE_NONE, 'Indicate any provided action file paths are pre-resolved absolute path'],
+ [Options::STEP, null, InputOption::VALUE_OPTIONAL, 'Force the actions to be run so they can be rolled back individually'],
+ ];
+ }
- return null;
+ protected function availableArguments(): array
+ {
+ return [
+ [Options::NAME, InputArgument::OPTIONAL, 'The name of the action'],
+ ];
}
}
diff --git a/src/Console/Command.php b/src/Console/Command.php
new file mode 100644
index 00000000..a08a83bc
--- /dev/null
+++ b/src/Console/Command.php
@@ -0,0 +1,56 @@
+allowToProceed()) {
+ $this->resolveProcessor()->handle();
+ $this->forgetProcessor();
+
+ return 0;
+ }
+
+ return 1;
+ }
+
+ protected function resolveProcessor(): Processor
+ {
+ return $this->container()->make($this->processor, [
+ 'options' => $this->getOptionsDto(),
+ 'input' => $this->input,
+ 'output' => $this->output,
+ ]);
+ }
+
+ protected function forgetProcessor(): void
+ {
+ $this->container()->forgetInstance($this->processor);
+ }
+
+ protected function container(): Container
+ {
+ return Container::getInstance();
+ }
+
+ protected function getOptionsDto(): OptionsDto
+ {
+ return OptionsDto::fromArray(array_merge($this->options(), $this->arguments()));
+ }
+}
diff --git a/src/Console/Fresh.php b/src/Console/Fresh.php
index 189ce835..cc31fa4e 100644
--- a/src/Console/Fresh.php
+++ b/src/Console/Fresh.php
@@ -4,61 +4,23 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Optionable;
use DragonCode\LaravelActions\Constants\Names;
-use Illuminate\Database\Console\Migrations\FreshCommand;
-use Illuminate\Support\Facades\Schema;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Fresh as FreshProcessor;
+use DragonCode\LaravelActions\Processors\Processor;
-class Fresh extends FreshCommand
+class Fresh extends Command
{
- use Optionable;
-
- /**
- * The console command name.
- *
- * @var string
- */
protected $name = Names::FRESH;
- /**
- * The console command description.
- *
- * @var string
- */
protected $description = 'Drop and re-run all actions';
- public function handle()
- {
- if (! $this->confirmToProceed()) {
- return 1;
- }
-
- $database = $this->optionDatabase();
-
- $this->dropTable();
- $this->migrate($database);
-
- return 0;
- }
-
- protected function dropTable(): void
- {
- Schema::dropIfExists($this->getTableName());
- }
-
- protected function migrate(?string $database): void
- {
- $this->call(
- Names::MIGRATE,
- array_filter([
- '--database' => $database,
- '--force' => true,
- ])
- );
- }
+ protected Processor|string $processor = FreshProcessor::class;
- protected function getTableName(): string
- {
- return config('database.actions');
- }
+ protected array $options = [
+ Options::CONNECTION,
+ Options::FORCE,
+ Options::PATH,
+ Options::REALPATH,
+ ];
}
diff --git a/src/Console/Install.php b/src/Console/Install.php
index 9bf5869f..c2d4ab7d 100644
--- a/src/Console/Install.php
+++ b/src/Console/Install.php
@@ -2,27 +2,21 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Database;
-use DragonCode\LaravelActions\Concerns\Infoable;
use DragonCode\LaravelActions\Constants\Names;
-use Illuminate\Database\Console\Migrations\InstallCommand as BaseCommand;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Install as InstallProcessor;
+use DragonCode\LaravelActions\Processors\Processor;
-class Install extends BaseCommand
+class Install extends Command
{
- use Database;
- use Infoable;
-
- /**
- * The console command name.
- *
- * @var string
- */
protected $name = Names::INSTALL;
- /**
- * The console command description.
- *
- * @var string
- */
protected $description = 'Create the actions repository';
+
+ protected Processor|string $processor = InstallProcessor::class;
+
+ protected array $options = [
+ Options::CONNECTION,
+ Options::FORCE,
+ ];
}
diff --git a/src/Console/Make.php b/src/Console/Make.php
index 9eb88666..52020688 100644
--- a/src/Console/Make.php
+++ b/src/Console/Make.php
@@ -2,95 +2,27 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Argumentable;
-use DragonCode\LaravelActions\Concerns\Database;
-use DragonCode\LaravelActions\Concerns\Infoable;
use DragonCode\LaravelActions\Constants\Names;
-use Exception;
-use Illuminate\Database\Console\Migrations\BaseCommand;
-use Illuminate\Database\Migrations\MigrationCreator;
-use Illuminate\Support\Composer;
-use Illuminate\Support\Str;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Make as MakeProcessor;
+use DragonCode\LaravelActions\Processors\Processor;
-class Make extends BaseCommand
+class Make extends Command
{
- use Argumentable;
- use Database;
- use Infoable;
+ protected $signature = Names::MAKE;
- /**
- * The console command name.
- *
- * @var string
- */
- protected $signature = Names::MAKE
- . ' {name? : The name of the action}';
-
- /**
- * The console command description.
- *
- * @var string
- */
protected $description = 'Create a new action file';
- /**
- * The migration creator instance.
- *
- * @var \Illuminate\Database\Migrations\MigrationCreator
- */
- protected $creator;
-
- /**
- * The Composer instance.
- *
- * @var \Illuminate\Support\Composer
- */
- protected $composer;
-
- /**
- * Create a new action install command instance.
- *
- * @param \Illuminate\Database\Migrations\MigrationCreator $creator
- * @param \Illuminate\Support\Composer $composer
- */
- public function __construct(MigrationCreator $creator, Composer $composer)
- {
- parent::__construct();
-
- $this->creator = $creator;
- $this->composer = $composer;
- }
-
- /**
- * Execute the console command.
- *
- * @throws Exception
- */
- public function handle()
- {
- $this->writeMigration(
- Str::snake($this->argumentName())
- );
-
- $this->composer->dumpAutoloads();
- }
-
- /**
- * Write the action file to disk.
- *
- * @param string $name
- *
- * @throws Exception
- */
- protected function writeMigration(string $name)
- {
- $file = $this->creator->create(
- $name,
- $this->getMigrationPath()
- );
+ protected Processor|string $processor = MakeProcessor::class;
- $path = pathinfo($file, PATHINFO_FILENAME);
+ protected array $arguments = [
+ Options::NAME,
+ ];
- $this->line("Created Action: {$path}");
- }
+ protected array $options = [
+ Options::CONNECTION,
+ Options::FORCE,
+ Options::PATH,
+ Options::REALPATH,
+ ];
}
diff --git a/src/Console/Migrate.php b/src/Console/Migrate.php
index 3a53f88c..6aab749c 100644
--- a/src/Console/Migrate.php
+++ b/src/Console/Migrate.php
@@ -2,74 +2,25 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Database;
-use DragonCode\LaravelActions\Concerns\Infoable;
-use DragonCode\LaravelActions\Concerns\Optionable;
use DragonCode\LaravelActions\Constants\Names;
-use Illuminate\Database\Console\Migrations\MigrateCommand as BaseCommand;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Migrate as MigrateProcessor;
+use DragonCode\LaravelActions\Processors\Processor;
-class Migrate extends BaseCommand
+class Migrate extends Command
{
- use Database;
- use Infoable;
- use Optionable;
+ protected $signature = Names::MIGRATE;
- /**
- * The console command name.
- *
- * @var string
- */
- protected $signature = Names::MIGRATE
- . ' {--database= : The database connection to use}'
- . ' {--force : Force the operation to run when in production}'
- . ' {--step : Force the actions to be run so they can be rolled back individually}'
- . ' {--path=* : The path(s) to the migrations files to be executed}'
- . ' {--realpath : Indicate any provided migration file paths are pre-resolved absolute paths}'
- . ' {--before : Run actions marked as before}';
-
- /**
- * The console command description.
- *
- * @var string
- */
protected $description = 'Run the actions';
- /**
- * Execute the console command.
- *
- * @return int
- */
- public function handle()
- {
- if (! $this->confirmToProceed()) {
- return 1;
- }
-
- $this->migrator->usingConnection($this->optionDatabase(), function () {
- $this->prepareDatabase();
-
- $this->migrator->setOutput($this->output)
- ->run($this->getMigrationPaths(), [
- 'step' => $this->optionStep(),
- 'before' => $this->optionBefore(),
- ]);
- });
+ protected Processor|string $processor = MigrateProcessor::class;
- return 0;
- }
+ protected bool $secure = false;
- /**
- * Prepare the action database for running.
- */
- protected function prepareDatabase(): void
- {
- if (! $this->migrator->repositoryExists()) {
- $this->call(
- Names::INSTALL,
- array_filter([
- '--database' => $this->optionDatabase(),
- ])
- );
- }
- }
+ protected array $options = [
+ Options::BEFORE,
+ Options::CONNECTION,
+ Options::PATH,
+ Options::REALPATH,
+ ];
}
diff --git a/src/Console/Refresh.php b/src/Console/Refresh.php
index c789adcf..2d665a62 100644
--- a/src/Console/Refresh.php
+++ b/src/Console/Refresh.php
@@ -2,105 +2,23 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Database;
-use DragonCode\LaravelActions\Concerns\Infoable;
-use DragonCode\LaravelActions\Concerns\Optionable;
use DragonCode\LaravelActions\Constants\Names;
-use Illuminate\Console\Command as BaseCommand;
-use Illuminate\Console\ConfirmableTrait;
-use Illuminate\Contracts\Events\Dispatcher;
-use Illuminate\Database\Events\DatabaseRefreshed;
-use Symfony\Component\Console\Input\InputOption;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Processor;
+use DragonCode\LaravelActions\Processors\Refresh as RefreshProcessor;
-class Refresh extends BaseCommand
+class Refresh extends Command
{
- use ConfirmableTrait;
- use Database;
- use Infoable;
- use Optionable;
-
- /**
- * The console command name.
- *
- * @var string
- */
protected $name = Names::REFRESH;
- /**
- * The console command description.
- *
- * @var string
- */
protected $description = 'Reset and re-run all actions';
- public function handle()
- {
- if (! $this->confirmToProceed()) {
- return 1;
- }
-
- $database = $this->optionDatabase();
- $step = $this->optionStep(0);
-
- $step > 0
- ? $this->runRollback($database, $step)
- : $this->runReset($database);
-
- $this->call(Names::MIGRATE, array_filter([
- '--database' => $database,
- '--force' => true,
- ]));
-
- if ($this->laravel->bound(Dispatcher::class) && class_exists(DatabaseRefreshed::class)) {
- $this->laravel[Dispatcher::class]->dispatch(
- new DatabaseRefreshed()
- );
- }
-
- return 0;
- }
-
- /**
- * Run the rollback command.
- *
- * @param string|null $database
- * @param int|null $step
- */
- protected function runRollback(?string $database, ?int $step)
- {
- $this->call(Names::ROLLBACK, array_filter([
- '--database' => $database,
- '--step' => $step,
- '--force' => true,
- ]));
- }
-
- /**
- * Run the reset command.
- *
- * @param string|null $database
- */
- protected function runReset(?string $database)
- {
- $this->call(Names::RESET, array_filter([
- '--database' => $database,
- '--force' => true,
- ]));
- }
-
- /**
- * Get the console command options.
- *
- * @return array
- */
- protected function getOptions(): array
- {
- return [
- ['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
-
- ['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
+ protected Processor|string $processor = RefreshProcessor::class;
- ['step', null, InputOption::VALUE_OPTIONAL, 'The number of actions to be reverted & re-run'],
- ];
- }
+ protected array $options = [
+ Options::CONNECTION,
+ Options::FORCE,
+ Options::PATH,
+ Options::REALPATH,
+ ];
}
diff --git a/src/Console/Reset.php b/src/Console/Reset.php
index a4658b8f..b96d764b 100644
--- a/src/Console/Reset.php
+++ b/src/Console/Reset.php
@@ -2,92 +2,23 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Database;
-use DragonCode\LaravelActions\Concerns\Infoable;
-use DragonCode\LaravelActions\Concerns\Optionable;
use DragonCode\LaravelActions\Constants\Names;
-use DragonCode\LaravelActions\Support\Migrator;
-use Illuminate\Console\ConfirmableTrait;
-use Illuminate\Database\Console\Migrations\BaseCommand;
-use Symfony\Component\Console\Input\InputOption;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Processor;
+use DragonCode\LaravelActions\Processors\Reset as ResetProcessor;
-class Reset extends BaseCommand
+class Reset extends Command
{
- use ConfirmableTrait;
- use Database;
- use Infoable;
- use Optionable;
-
- /**
- * The console command name.
- *
- * @var string
- */
protected $name = Names::RESET;
- /**
- * The console command description.
- *
- * @var string
- */
- protected $description = 'Rollback all database actions';
-
- /**
- * The migrator instance.
- *
- * @var \DragonCode\LaravelActions\Support\Migrator
- */
- protected $migrator;
-
- /**
- * Create a new migration rollback command instance.
- *
- * @param \DragonCode\LaravelActions\Support\Migrator $migrator
- */
- public function __construct(Migrator $migrator)
- {
- parent::__construct();
-
- $this->migrator = $migrator;
- }
-
- /**
- * Execute the console command.
- *
- * @return int|void
- */
- public function handle()
- {
- if (! $this->confirmToProceed()) {
- return 1;
- }
-
- return $this->migrator->usingConnection($this->optionDatabase(), function () {
- if (! $this->migrator->repositoryExists()) {
- $this->comment('Actions table not found.');
-
- return 1;
- }
-
- $this->migrator->setOutput($this->output)->reset(
- $this->getMigrationPaths()
- );
-
- return 0;
- });
- }
+ protected $description = 'Rollback all actions';
- /**
- * Get the console command options.
- *
- * @return array
- */
- protected function getOptions(): array
- {
- return [
- ['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
+ protected Processor|string $processor = ResetProcessor::class;
- ['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
- ];
- }
+ protected array $options = [
+ Options::CONNECTION,
+ Options::FORCE,
+ Options::PATH,
+ Options::REALPATH,
+ ];
}
diff --git a/src/Console/Rollback.php b/src/Console/Rollback.php
index 8bee9364..d4c23fda 100644
--- a/src/Console/Rollback.php
+++ b/src/Console/Rollback.php
@@ -2,67 +2,24 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Database;
-use DragonCode\LaravelActions\Concerns\Infoable;
-use DragonCode\LaravelActions\Concerns\Optionable;
use DragonCode\LaravelActions\Constants\Names;
-use Illuminate\Database\Console\Migrations\RollbackCommand;
-use Symfony\Component\Console\Input\InputOption;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Processor;
+use DragonCode\LaravelActions\Processors\Rollback as RollbackProcessor;
-class Rollback extends RollbackCommand
+class Rollback extends Command
{
- use Database;
- use Infoable;
- use Optionable;
-
- /**
- * The console command name.
- *
- * @var string
- */
protected $name = Names::ROLLBACK;
- /**
- * The console command description.
- *
- * @var string
- */
- protected $description = 'Rollback the last database action';
-
- /**
- * Execute the console command.
- *
- * @return int
- */
- public function handle()
- {
- if (! $this->confirmToProceed()) {
- return 1;
- }
-
- $this->migrator->usingConnection($this->optionDatabase(), function () {
- $this->migrator->setOutput($this->output)->rollback(
- $this->getMigrationPaths(),
- ['step' => $this->optionStep()]
- );
- });
-
- return 0;
- }
-
- /**
- * Get the console command options.
- *
- * @return array
- */
- protected function getOptions()
- {
- return [
- ['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
+ protected $description = 'Rollback the last action';
- ['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
+ protected Processor|string $processor = RollbackProcessor::class;
- ['step', null, InputOption::VALUE_OPTIONAL, 'The number of actions to be reverted'],
- ];
- }
+ protected array $options = [
+ Options::CONNECTION,
+ Options::FORCE,
+ Options::PATH,
+ Options::REALPATH,
+ Options::STEP,
+ ];
}
diff --git a/src/Console/Status.php b/src/Console/Status.php
index aef015ac..072b55d8 100644
--- a/src/Console/Status.php
+++ b/src/Console/Status.php
@@ -2,29 +2,24 @@
namespace DragonCode\LaravelActions\Console;
-use DragonCode\LaravelActions\Concerns\Database;
-use DragonCode\LaravelActions\Concerns\Infoable;
-use DragonCode\LaravelActions\Concerns\Optionable;
use DragonCode\LaravelActions\Constants\Names;
-use Illuminate\Database\Console\Migrations\StatusCommand as BaseCommand;
+use DragonCode\LaravelActions\Constants\Options;
+use DragonCode\LaravelActions\Processors\Processor;
+use DragonCode\LaravelActions\Processors\Status as StatusProcessor;
-class Status extends BaseCommand
+class Status extends Command
{
- use Database;
- use Infoable;
- use Optionable;
-
- /**
- * The console command name.
- *
- * @var string
- */
protected $name = Names::STATUS;
- /**
- * The console command description.
- *
- * @var string
- */
protected $description = 'Show the status of each action';
+
+ protected Processor|string $processor = StatusProcessor::class;
+
+ protected bool $secure = false;
+
+ protected array $options = [
+ Options::CONNECTION,
+ Options::PATH,
+ Options::REALPATH,
+ ];
}
diff --git a/src/Console/Upgrade.php b/src/Console/Upgrade.php
new file mode 100644
index 00000000..ffee6fea
--- /dev/null
+++ b/src/Console/Upgrade.php
@@ -0,0 +1,18 @@
+config = app(Config::class);
+ }
+
+ public function up(): void
+ {
+ if ($this->hasTable()) {
+ Schema::table($this->table(), function (Blueprint $table) {
+ $table->renameColumn('migration', 'action');
+
+ $table->unsignedInteger('batch')->change();
+ });
+ }
+ }
+
+ public function down(): void
+ {
+ if ($this->hasTable()) {
+ Schema::table($this->table(), function (Blueprint $table) {
+ $table->renameColumn('action', 'migration');
+
+ $table->integer('batch')->change();
+ });
+ }
+ }
+
+ protected function hasTable(): bool
+ {
+ return Schema::hasTable($this->table());
+ }
+
+ protected function table(): string
+ {
+ return $this->config->table();
+ }
+}
diff --git a/src/Events/ActionEnded.php b/src/Events/ActionEnded.php
new file mode 100644
index 00000000..2c855ef2
--- /dev/null
+++ b/src/Events/ActionEnded.php
@@ -0,0 +1,9 @@
+config->get('app.env', 'production');
+ }
+
+ public function connection(): ?string
+ {
+ return $this->config->get('actions.connection');
+ }
+
+ public function table(): string
+ {
+ return $this->config->get('actions.table');
+ }
+
+ public function path(?string $path = null): string
+ {
+ $directory = $this->config->get('actions.path', base_path('actions'));
+
+ return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . ltrim((string) $path, '\\/');
+ }
+
+ public function gitPath(): string
+ {
+ return base_path();
+ }
+}
diff --git a/src/Helpers/Git.php b/src/Helpers/Git.php
new file mode 100644
index 00000000..48663c10
--- /dev/null
+++ b/src/Helpers/Git.php
@@ -0,0 +1,43 @@
+hasGitDirectory($path)) {
+ return $this->exec('rev-parse --abbrev-ref HEAD', $this->resolvePath($path));
+ }
+
+ return null;
+ }
+
+ protected function exec(string $command, ?string $path = null): ?string
+ {
+ return exec(sprintf('git --git-dir "%s" %s', $path, $command));
+ }
+
+ protected function hasGitDirectory(?string $path = null): bool
+ {
+ if ($path = rtrim($this->resolvePath($path), '/\\')) {
+ return Directory::exists($path . DIRECTORY_SEPARATOR . '.git');
+ }
+
+ return false;
+ }
+
+ protected function resolvePath(?string $path = null): string
+ {
+ return realpath($path ?: $this->config->gitPath());
+ }
+}
diff --git a/src/Notifications/Basic.php b/src/Notifications/Basic.php
new file mode 100644
index 00000000..3d5c217c
--- /dev/null
+++ b/src/Notifications/Basic.php
@@ -0,0 +1,45 @@
+$string$style>" : $string;
+
+ $this->output->writeln($styled, $this->verbosity);
+ }
+
+ public function info(string $string): void
+ {
+ $this->line($string, 'info');
+ }
+
+ public function warning(string $string): void
+ {
+ $this->line($string, 'warn');
+ }
+
+ public function task(string $description, Closure $task): void
+ {
+ $this->info($description);
+
+ $start = microtime(true);
+
+ $task();
+
+ $run_time = number_format((microtime(true) - $start) * 1000, 2);
+
+ $this->info("Migrated: {$run_time}ms");
+ }
+
+ public function twoColumn(string $first, string $second): void
+ {
+ $this->info($first . ' .......... ' . $second);
+ }
+}
diff --git a/src/Notifications/Beautiful.php b/src/Notifications/Beautiful.php
new file mode 100644
index 00000000..9f8d2285
--- /dev/null
+++ b/src/Notifications/Beautiful.php
@@ -0,0 +1,47 @@
+components()->line($style, $string, $this->verbosity);
+ }
+
+ public function info(string $string): void
+ {
+ $this->components()->info($string, $this->verbosity);
+ }
+
+ public function warning(string $string): void
+ {
+ $this->components()->warn($string, $this->verbosity);
+ }
+
+ public function task(string $description, Closure $task): void
+ {
+ $this->components()->task($description, $task);
+ }
+
+ public function twoColumn(string $first, string $second): void
+ {
+ $this->components()->twoColumnDetail($first, $second, $this->verbosity);
+ }
+
+ protected function components(): Factory
+ {
+ if (! is_null($this->components)) {
+ return $this->components;
+ }
+
+ return $this->component = new Factory($this->output);
+ }
+}
diff --git a/src/Notifications/Notification.php b/src/Notifications/Notification.php
new file mode 100644
index 00000000..ed4c8896
--- /dev/null
+++ b/src/Notifications/Notification.php
@@ -0,0 +1,34 @@
+output = $output;
+
+ return $this;
+ }
+}
diff --git a/src/Processors/Fresh.php b/src/Processors/Fresh.php
new file mode 100644
index 00000000..bba52c52
--- /dev/null
+++ b/src/Processors/Fresh.php
@@ -0,0 +1,42 @@
+drop();
+ $this->create();
+ $this->migrate();
+ }
+
+ protected function drop(): void
+ {
+ if ($this->repository->repositoryExists()) {
+ $this->notification->task('Dropping all actions', fn () => $this->repository->deleteRepository());
+ }
+ }
+
+ protected function create(): void
+ {
+ $this->runCommand(Names::INSTALL, [
+ '--' . Options::CONNECTION => $this->options->connection,
+ '--' . Options::FORCE => $this->options->force,
+ ]);
+ }
+
+ protected function migrate(): void
+ {
+ $this->runCommand(Names::MIGRATE, [
+ '--' . Options::CONNECTION => $this->options->connection,
+ '--' . Options::PATH => $this->options->path,
+ '--' . Options::REALPATH => $this->options->realpath,
+ ]);
+ }
+}
diff --git a/src/Processors/Install.php b/src/Processors/Install.php
new file mode 100644
index 00000000..e9c76042
--- /dev/null
+++ b/src/Processors/Install.php
@@ -0,0 +1,41 @@
+exists()) {
+ $this->notification->warning('Actions repository already exists');
+
+ return;
+ }
+
+ $this->notification->task('Installing the action repository', function () {
+ $this->create();
+ $this->ensureDirectory();
+ });
+ }
+
+ protected function exists(): bool
+ {
+ return $this->repository->repositoryExists();
+ }
+
+ protected function create(): void
+ {
+ $this->repository->createRepository();
+ }
+
+ protected function ensureDirectory(): void
+ {
+ Directory::ensureDirectory(
+ $this->getActionsPath()
+ );
+ }
+}
diff --git a/src/Processors/Make.php b/src/Processors/Make.php
new file mode 100644
index 00000000..2f9e4883
--- /dev/null
+++ b/src/Processors/Make.php
@@ -0,0 +1,57 @@
+notification->task('Creating an action', fn () => $this->run());
+ }
+
+ protected function run(): void
+ {
+ $name = $this->getName();
+ $path = $this->getActionsPath($name);
+
+ $this->create($path);
+ }
+
+ protected function create(string $path): void
+ {
+ File::copy($this->stub, $path);
+ }
+
+ protected function getName(): string
+ {
+ $branch = $this->getBranchName();
+ $filename = $this->getFilename($branch);
+
+ return Path::dirname($branch) . DIRECTORY_SEPARATOR . $filename;
+ }
+
+ protected function getFilename(string $branch): string
+ {
+ return Str::of(Path::filename($branch))->prepend($this->getTime())->finish('.php')->toString();
+ }
+
+ protected function getBranchName(): string
+ {
+ return $this->options->name ?? $this->git->currentBranch() ?? $this->fallbackName;
+ }
+
+ protected function getTime(): string
+ {
+ return date('Y_m_d_His_');
+ }
+}
diff --git a/src/Processors/Migrate.php b/src/Processors/Migrate.php
new file mode 100644
index 00000000..56f95dbf
--- /dev/null
+++ b/src/Processors/Migrate.php
@@ -0,0 +1,77 @@
+ensureRepository();
+ $this->runActions();
+ }
+
+ protected function ensureRepository(): void
+ {
+ $this->artisan(Names::INSTALL, [
+ '--' . Options::CONNECTION => $this->options->connection,
+ '--' . Options::FORCE => true,
+ ]);
+ }
+
+ protected function runActions(): void
+ {
+ try {
+ if ($files = $this->getNewFiles()) {
+ $this->fireEvent(ActionStarted::class, 'up');
+
+ $this->runEach($files, $this->getBatch());
+
+ $this->fireEvent(ActionEnded::class, 'up');
+
+ return;
+ }
+
+ $this->fireEvent(NoPendingActions::class, 'up');
+ }
+ catch (Throwable $e) {
+ $this->fireEvent(ActionFailed::class, 'up');
+
+ throw $e;
+ }
+ }
+
+ protected function runEach(array $files, int $batch): void
+ {
+ foreach ($files as $file) {
+ $this->run($file, $batch);
+ }
+ }
+
+ protected function run(string $file, int $batch): void
+ {
+ $this->migrator->runUp($file, $batch, $this->options);
+ }
+
+ protected function getNewFiles(): array
+ {
+ $completed = $this->repository->getCompleted()->pluck('action')->toArray();
+
+ return $this->getFiles(fn (string $file) => ! Str::of($file)->replace('\\', '/')->contains($completed), $this->options->path);
+ }
+
+ protected function getBatch(): int
+ {
+ return $this->repository->getNextBatchNumber();
+ }
+}
diff --git a/src/Processors/Processor.php b/src/Processors/Processor.php
new file mode 100644
index 00000000..c93e2ef2
--- /dev/null
+++ b/src/Processors/Processor.php
@@ -0,0 +1,82 @@
+notification->setOutput($this->output);
+ $this->repository->setConnection($this->options->connection);
+ $this->migrator->setConnection($this->options->connection)->setOutput($this->output);
+ }
+
+ protected function getFiles(?Closure $filter = null, ?string $path = null): array
+ {
+ $path = $this->getActionsPath($path);
+
+ return $this->file->exists($path) ? [$path] : $this->file->allPaths($path, $filter, true);
+ }
+
+ protected function getActionsPath(?string $path = null): string
+ {
+ $path = $this->options->realpath ? $path : $this->config->path($path);
+
+ if (! is_dir($path) && ! Str::endsWith($path, '.php')) {
+ return $this->file->exists($path . '.php') ? $path . '.php' : $path;
+ }
+
+ return $path;
+ }
+
+ protected function runCommand(string $command, array $options = []): void
+ {
+ $this->artisan($command, array_filter($options));
+ }
+
+ protected function tableNotFound(): bool
+ {
+ if (! $this->repository->repositoryExists()) {
+ $this->notification->warning('Actions table not found');
+
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function fireEvent(string $event, string $method): void
+ {
+ $this->events->dispatch(new $event($method, $this->options->before));
+ }
+}
diff --git a/src/Processors/Refresh.php b/src/Processors/Refresh.php
new file mode 100644
index 00000000..0ed70b15
--- /dev/null
+++ b/src/Processors/Refresh.php
@@ -0,0 +1,40 @@
+options->connection;
+ $path = $this->options->path;
+ $realPath = $this->options->realpath;
+
+ $this->runReset($connection, $path, $realPath);
+ $this->runMigrate($connection, $path, $realPath);
+ }
+
+ protected function runReset(?string $connection, ?string $path, bool $realPath): void
+ {
+ $this->runCommand(Names::RESET, [
+ '--' . Options::CONNECTION => $connection,
+ '--' . Options::PATH => $path,
+ '--' . Options::REALPATH => $realPath,
+ '--' . Options::FORCE => true,
+ ]);
+ }
+
+ protected function runMigrate(?string $connection, ?string $path, bool $realPath): void
+ {
+ $this->runCommand(Names::MIGRATE, [
+ '--' . Options::CONNECTION => $connection,
+ '--' . Options::PATH => $path,
+ '--' . Options::REALPATH => $realPath,
+ ]);
+ }
+}
diff --git a/src/Processors/Reset.php b/src/Processors/Reset.php
new file mode 100644
index 00000000..e57ecf0b
--- /dev/null
+++ b/src/Processors/Reset.php
@@ -0,0 +1,37 @@
+rollback(
+ $this->options->connection,
+ $this->options->path,
+ $this->options->realpath,
+ $this->count()
+ );
+ }
+
+ protected function rollback(?string $connection, ?string $path, ?bool $realPath, int $step): void
+ {
+ $this->runCommand(Names::ROLLBACK, [
+ '--' . Options::CONNECTION => $connection,
+ '--' . Options::PATH => $path,
+ '--' . Options::REALPATH => $realPath,
+ '--' . Options::STEP => $step,
+ '--' . Options::FORCE => true,
+ ]);
+ }
+
+ protected function count(): int
+ {
+ return $this->repository->getLastBatchNumber();
+ }
+}
diff --git a/src/Processors/Rollback.php b/src/Processors/Rollback.php
new file mode 100644
index 00000000..9a3420fa
--- /dev/null
+++ b/src/Processors/Rollback.php
@@ -0,0 +1,78 @@
+tableNotFound() || $this->nothingToRollback()) {
+ $this->fireEvent(NoPendingActions::class, 'down');
+
+ return;
+ }
+
+ if ($actions = $this->getActions($this->options->step)) {
+ $this->fireEvent(ActionStarted::class, 'down');
+
+ $this->run($actions);
+
+ $this->fireEvent(ActionEnded::class, 'down');
+
+ return;
+ }
+
+ $this->fireEvent(NoPendingActions::class, 'down');
+ }
+
+ protected function run(array $actions): void
+ {
+ foreach ($actions as $row) {
+ $this->rollbackAction(
+ $this->resolveFilename($row->action)
+ );
+ }
+ }
+
+ protected function getActions(?int $step): array
+ {
+ return (int) $step > 0
+ ? $this->repository->getByStep($step)
+ : $this->repository->getLast();
+ }
+
+ protected function rollbackAction(string $action): void
+ {
+ $this->migrator->runDown(
+ $this->getActionsPath($action)
+ );
+ }
+
+ protected function nothingToRollback(): bool
+ {
+ if ($this->count() <= 0) {
+ $this->notification->warning('Nothing To Rollback');
+
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function count(): int
+ {
+ return $this->repository->getLastBatchNumber();
+ }
+
+ protected function resolveFilename(string $name): string
+ {
+ return Str::finish($name, '.php');
+ }
+}
diff --git a/src/Processors/Status.php b/src/Processors/Status.php
new file mode 100644
index 00000000..0f5abd84
--- /dev/null
+++ b/src/Processors/Status.php
@@ -0,0 +1,79 @@
+Action name>';
+
+ protected string $columnStatus = 'Batch / Status>';
+
+ protected string $statusRan = 'Ran>';
+
+ protected string $statusPending = 'Pending>';
+
+ public function handle(): void
+ {
+ if ($this->tableNotFound()) {
+ return;
+ }
+
+ [$files, $completed] = $this->getData();
+
+ if ($this->doesntEmpty($files, $completed)) {
+ $this->showCaption();
+ $this->showStatus($files, $completed);
+
+ return;
+ }
+
+ $this->notification->info('No actions found');
+ }
+
+ protected function showCaption(): void
+ {
+ $this->notification->twoColumn($this->columnName, $this->columnStatus);
+ }
+
+ protected function showStatus(array $actions, array $completed): void
+ {
+ foreach ($actions as $action) {
+ $status = $this->getStatusFor($completed, $action);
+
+ $this->notification->twoColumn($action, $status);
+ }
+ }
+
+ protected function getData(): array
+ {
+ $files = $this->getFiles();
+ $completed = $this->getCompleted();
+
+ return [$files, $completed];
+ }
+
+ protected function getStatusFor(array $completed, string $action): string
+ {
+ if ($batch = Arr::get($completed, $action)) {
+ return "[$batch] $this->statusRan";
+ }
+
+ return $this->statusPending;
+ }
+
+ protected function getCompleted(): array
+ {
+ return $this->repository->getCompleted()
+ ->pluck('batch', 'action')
+ ->toArray();
+ }
+
+ protected function doesntEmpty(array $actions, array $completed): bool
+ {
+ return ! empty($actions) && ! empty($completed);
+ }
+}
diff --git a/src/Processors/Upgrade.php b/src/Processors/Upgrade.php
new file mode 100644
index 00000000..67f04bf7
--- /dev/null
+++ b/src/Processors/Upgrade.php
@@ -0,0 +1,136 @@
+alreadyUpgraded()) {
+ $this->notification->info('Action upgrade already done');
+
+ return;
+ }
+
+ $this->run();
+ }
+
+ protected function run(): void
+ {
+ $this->moveFiles();
+ $this->moveConfig();
+ $this->clean();
+ }
+
+ protected function moveFiles(): void
+ {
+ foreach ($this->getOldFiles() as $filename) {
+ $this->notification->task($filename, fn () => $this->move($filename));
+ }
+ }
+
+ protected function move(string $filename): void
+ {
+ $content = $this->open($filename);
+
+ $content = $this->replaceNamespace($content);
+ $content = $this->replaceClassName($content);
+ $content = $this->replaceDeclareStrictType($content);
+ $content = $this->replaceWithInvoke($content);
+
+ $this->store($filename, $content);
+ $this->delete($filename);
+ }
+
+ protected function clean(): void
+ {
+ $this->notification->task('Delete old directory', fn () => Directory::ensureDelete(
+ database_path('actions')
+ ));
+ }
+
+ protected function open(string $path): string
+ {
+ return file_get_contents(base_path('database/actions/' . $path));
+ }
+
+ protected function store(string $path, string $content): void
+ {
+ file_put_contents($this->config->path($path), $content);
+ }
+
+ protected function delete(string $path): void
+ {
+ File::ensureDelete($this->config->path($path));
+ }
+
+ protected function replaceNamespace(string $content): string
+ {
+ return Str::of($content)->replace(
+ ['DragonCode\\LaravelActions\\Support\\Actionable', 'Actionable'],
+ ['DragonCode\\LaravelActions\\Action', 'Action']
+ )->toString();
+ }
+
+ protected function replaceClassName(string $content): string
+ {
+ return Str::of($content)
+ ->pregReplace('/^([final\s|class]+.+extends\sAction)$/', 'return new class () extends Action')
+ ->trim()
+ ->append(';')
+ ->append(PHP_EOL)
+ ->toString();
+ }
+
+ protected function replaceDeclareStrictType(string $content): string
+ {
+ return Str::of($content)
+ ->replace('(declare\s*\(\s*strict_types\s*=\s*[1|0]\);)', '')
+ ->replace("toString();
+ }
+
+ protected function replaceWithInvoke(string $content): string
+ {
+ return Str::of($content)
+ ->when(! Str::matchContains($content, '/public\s+function\s+down/'), function (Stringable $string) {
+ return $string->pregReplace('/(public\s+function\s+up)/', 'public function __invoke');
+ })->toString();
+ }
+
+ protected function moveConfig(): void
+ {
+ $this->notification->task('Moving config file', function () {
+ $this->artisan('vendor:publish', [
+ '--provider' => ServiceProvider::class,
+ '--force' => true,
+ ]);
+
+ $path = config_path('actions.php');
+
+ $table = config('database.actions', 'migration_actions');
+
+ $content = Str::replace(file_get_contents($path), "'table' => 'migration_actions'", "'table' => '$table'");
+
+ file_put_contents($path, $content);
+ });
+ }
+
+ protected function getOldFiles(): array
+ {
+ return $this->getFiles(path: database_path('actions'));
+ }
+
+ protected function alreadyUpgraded(): bool
+ {
+ return Directory::exists($this->config->path());
+ }
+}
diff --git a/src/Repositories/ActionRepository.php b/src/Repositories/ActionRepository.php
new file mode 100644
index 00000000..4f03c627
--- /dev/null
+++ b/src/Repositories/ActionRepository.php
@@ -0,0 +1,132 @@
+connection = $connection;
+
+ return $this;
+ }
+
+ public function getCompleted(): Collection
+ {
+ return $this->sortedTable()->get();
+ }
+
+ public function getByStep(int $steps): array
+ {
+ return $this->sortedTable(Order::DESC)
+ ->whereIn('batch', $this->getBatchNumbers($steps))
+ ->get()
+ ->all();
+ }
+
+ public function getLast(): array
+ {
+ return $this->sortedTable(Order::DESC)
+ ->where('batch', $this->getLastBatchNumber())
+ ->get()
+ ->all();
+ }
+
+ public function getNextBatchNumber(): int
+ {
+ return $this->getLastBatchNumber() + 1;
+ }
+
+ public function getLastBatchNumber(): int
+ {
+ return (int) $this->table()->max('batch');
+ }
+
+ public function log(string $action, int $batch): void
+ {
+ $this->table()->insert(compact('action', 'batch'));
+ }
+
+ public function delete(string $action): void
+ {
+ $this->table()->where(compact('action'))->delete();
+ }
+
+ public function createRepository(): void
+ {
+ $this->schema()->create($this->config->table(), function (Blueprint $table) {
+ $table->bigIncrements('id');
+
+ $table->string('action');
+
+ $table->unsignedInteger('batch');
+ });
+ }
+
+ public function repositoryExists(): bool
+ {
+ return $this->schema()->hasTable($this->config->table());
+ }
+
+ public function deleteRepository(): void
+ {
+ $this->schema()->dropIfExists($this->config->table());
+ }
+
+ /**
+ * @param int $steps
+ *
+ * @return array
+ */
+ protected function getBatchNumbers(int $steps): array
+ {
+ return $this->sortedTable(Order::DESC)
+ ->pluck('batch')
+ ->unique()
+ ->take($steps)
+ ->all();
+ }
+
+ protected function sortedTable(string $order = Order::ASC): Query
+ {
+ return $this->table()
+ ->orderBy('batch', $order)
+ ->orderBy('id', $order);
+ }
+
+ protected function schema(): Builder
+ {
+ return $this->getConnection()->getSchemaBuilder();
+ }
+
+ protected function table(): Query
+ {
+ return $this->getConnection()->table($this->config->table())->useWritePdo();
+ }
+
+ protected function getConnection(): ConnectionInterface
+ {
+ return $this->resolver->connection(
+ $this->connection ?: $this->config->connection()
+ );
+ }
+}
diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php
index ba93e4fa..49c9fad5 100644
--- a/src/ServiceProvider.php
+++ b/src/ServiceProvider.php
@@ -1,148 +1,80 @@
Command::MIGRATE,
- 'MigrateFresh' => Command::FRESH,
- 'MigrateInstall' => Command::INSTALL,
- 'MigrateMake' => Command::MAKE,
- 'MigrateRefresh' => Command::REFRESH,
- 'MigrateReset' => Command::RESET,
- 'MigrateRollback' => Command::ROLLBACK,
- 'MigrateStatus' => Command::STATUS,
- ];
-
- public function register(): void
- {
- $this->registerConfig();
- $this->registerRepository();
- $this->registerMigrator();
- $this->registerCreator();
- $this->registerCommands($this->commands);
- }
+ use About;
+ use Anonymous;
- public function provides(): array
+ public function boot(): void
{
- return array_merge([
- Action::MIGRATOR,
- Action::REPOSITORY,
- Action::CREATOR,
- ], array_values($this->commands));
- }
+ if ($this->app->runningInConsole()) {
+ $this->publishConfig();
- protected function registerRepository(): void
- {
- $this->app->singleton(Action::REPOSITORY, static function ($app) {
- return new DatabaseMigrationRepository($app['db'], $app['config']['database.actions']);
- });
- }
-
- protected function registerMigrator(): void
- {
- $this->app->singleton(Action::MIGRATOR, static function ($app) {
- return new Migrator($app[Action::REPOSITORY], $app['db'], $app['files'], $app['events']);
- });
- }
-
- protected function registerCreator(): void
- {
- $this->app->singleton(Action::CREATOR, static function ($app) {
- return new MigrationCreator($app['files'], __DIR__ . '/../resources/stubs');
- });
- }
-
- protected function registerCommands(array $commands): void
- {
- foreach (array_keys($commands) as $command) {
- $this->{"register{$command}Command"}();
+ $this->registerCommands();
+ $this->registerAbout();
+ $this->registerMigrations();
+ $this->registerNotifications();
}
-
- $this->commands(array_values($commands));
- }
-
- protected function registerMigrateCommand(): void
- {
- $this->app->singleton(Command::MIGRATE, static function ($app) {
- return new Migrate($app[Action::MIGRATOR], $app[Dispatcher::class]);
- });
- }
-
- protected function registerMigrateStatusCommand(): void
- {
- $this->app->singleton(Command::STATUS, static function ($app) {
- return new Status($app[Action::MIGRATOR]);
- });
}
- protected function registerMigrateInstallCommand(): void
- {
- $this->app->singleton(Command::INSTALL, static function ($app) {
- return new Install($app[Action::REPOSITORY]);
- });
- }
-
- protected function registerMigrateMakeCommand(): void
+ public function register(): void
{
- $this->app->singleton(Command::MAKE, function ($app) {
- return new Make(
- $app[Action::CREATOR],
- $app['composer']
- );
- });
+ $this->registerConfig();
}
- protected function registerMigrateRollbackCommand(): void
+ protected function registerCommands(): void
{
- $this->app->singleton(Command::ROLLBACK, function ($app) {
- return new Rollback($app[Action::MIGRATOR]);
- });
+ $this->commands([
+ Console\Fresh::class,
+ Console\Install::class,
+ Console\Make::class,
+ Console\Migrate::class,
+ Console\Refresh::class,
+ Console\Reset::class,
+ Console\Rollback::class,
+ Console\Status::class,
+ Console\Upgrade::class,
+ ]);
}
- protected function registerMigrateResetCommand(): void
+ protected function registerMigrations(): void
{
- $this->app->singleton(Command::RESET, function ($app) {
- return new Reset($app[Action::MIGRATOR]);
- });
+ $this->allowAnonymousMigrations()
+ ? $this->loadMigrationsFrom(__DIR__ . '/../database/migrations/anonymous')
+ : $this->loadMigrationsFrom(__DIR__ . '/../database/migrations/named');
}
- protected function registerMigrateRefreshCommand(): void
+ protected function registerNotifications(): void
{
- $this->app->singleton(Command::REFRESH, function () {
- return new Refresh();
- });
+ class_exists(Factory::class)
+ ? $this->app->bind(Notification::class, Beautiful::class)
+ : $this->app->bind(Notification::class, Basic::class);
}
- protected function registerMigrateFreshCommand(): void
+ protected function publishConfig(): void
{
- $this->app->singleton(Command::FRESH, function () {
- return new Fresh();
- });
+ $this->publishes([
+ __DIR__ . '/../config/actions.php' => $this->app->configPath('actions.php'),
+ ], 'config');
}
protected function registerConfig(): void
{
$this->mergeConfigFrom(
- __DIR__ . '/../config/database.php',
- 'database'
+ __DIR__ . '/../config/actions.php',
+ 'actions'
);
}
}
diff --git a/src/Services/Migrator.php b/src/Services/Migrator.php
new file mode 100644
index 00000000..2bca7b81
--- /dev/null
+++ b/src/Services/Migrator.php
@@ -0,0 +1,176 @@
+repository->setConnection($connection);
+
+ return $this;
+ }
+
+ public function setOutput(OutputStyle $output): self
+ {
+ $this->notification->setOutput($output);
+
+ return $this;
+ }
+
+ public function runUp(string $file, int $batch, Options $options): void
+ {
+ $action = $this->resolvePath($file);
+ $name = $this->resolveActionName($file);
+
+ if ($this->allowAction($action, $name, $options)) {
+ $this->hasAction($action, '__invoke')
+ ? $this->runAction($action, $name, '__invoke')
+ : $this->runAction($action, $name, 'up');
+
+ if ($this->allowLogging($action)) {
+ $this->log($name, $batch);
+ }
+ }
+ }
+
+ public function runDown(string $file): void
+ {
+ $action = $this->resolvePath($file);
+ $name = $this->resolveActionName($file);
+
+ if (! $this->hasAction($action, '__invoke') && $this->hasAction($action, 'down')) {
+ $this->runAction($action, $name, 'down');
+ }
+
+ $this->deleteLog($name);
+ }
+
+ protected function hasAction(Action $action, string $method): bool
+ {
+ return method_exists($action, $method);
+ }
+
+ protected function runAction(Action $action, string $name, string $method): void
+ {
+ $this->notification->task("Action: $name", function () use ($action, $method) {
+ if ($this->hasAction($action, $method)) {
+ try {
+ $this->runMethod($action, $method, $action->enabledTransactions(), $action->transactionAttempts());
+
+ $action->success();
+ }
+ catch (Throwable $e) {
+ $action->failed();
+
+ throw $e;
+ }
+ }
+ });
+ }
+
+ protected function runMethod(Action $action, string $method, bool $transactions, int $attempts): void
+ {
+ $callback = fn () => $this->laravel->call([$action, $method]);
+
+ $transactions ? DB::transaction($callback, $attempts) : $callback();
+ }
+
+ protected function log(string $name, int $batch): void
+ {
+ $this->repository->log($name, $batch);
+ }
+
+ protected function deleteLog(string $name): void
+ {
+ $this->repository->delete($name);
+ }
+
+ protected function allowAction(Action $action, string $name, Options $options): bool
+ {
+ if (! $this->allowEnvironment($action)) {
+ $this->notification->info("Action: $name was skipped on this environment");
+
+ return false;
+ }
+
+ if ($this->disallowBefore($action, $options)) {
+ $this->notification->info("Action: $name was skipped by 'before' option");
+
+ return false;
+ }
+
+ return true;
+ }
+
+ protected function allowEnvironment(Action $action): bool
+ {
+ $env = $this->config->environment();
+
+ return $action->allow()
+ && $this->onEnvironment($env, $action->onEnvironment())
+ && $this->exceptEnvironment($env, $action->exceptEnvironment());
+ }
+
+ protected function onEnvironment(?string $env, array $on): bool
+ {
+ return empty($on) || in_array($env, $on);
+ }
+
+ protected function exceptEnvironment(?string $env, array $except): bool
+ {
+ return empty($except) || ! in_array($env, $except);
+ }
+
+ protected function disallowBefore(Action $action, Options $options): bool
+ {
+ return $options->before && ! $action->hasBefore();
+ }
+
+ protected function allowLogging(Action $action): bool
+ {
+ return $action->isOnce();
+ }
+
+ protected function resolvePath(string $path): Action
+ {
+ if ($this->file->exists($path)) {
+ return require $path;
+ }
+
+ throw new FileNotFoundException($path);
+ }
+
+ protected function resolveActionName(string $path): string
+ {
+ return Str::of(realpath($path))
+ ->after(realpath($this->config->path()))
+ ->ltrim('\\/')
+ ->replace('\\', '/')
+ ->toString();
+ }
+}
diff --git a/src/Support/Git.php b/src/Support/Git.php
deleted file mode 100644
index bb4f0509..00000000
--- a/src/Support/Git.php
+++ /dev/null
@@ -1,49 +0,0 @@
-getGitPath($path)) {
- return $this->exec($path, 'rev-parse --abbrev-ref HEAD');
- }
-
- return null;
- }
-
- protected function exec(string $path, string $command): ?string
- {
- return exec(sprintf('git --git-dir %s %s', $path, $command));
- }
-
- protected function resolvePath(string $path): ?string
- {
- return realpath($path) ?: null;
- }
-
- protected function getGitPath(?string $path): ?string
- {
- if ($path = $this->resolvePath($path)) {
- if ($this->isGitDir($path)) {
- return $path;
- }
- }
-
- return null;
- }
-
- protected function isGitDir(?string $path): bool
- {
- if ($path = rtrim($path, '/\\')) {
- return Str::endsWith($path, '.git');
- }
-
- return false;
- }
-}
diff --git a/src/Support/Information.php b/src/Support/Information.php
deleted file mode 100644
index 4f6d7a39..00000000
--- a/src/Support/Information.php
+++ /dev/null
@@ -1,25 +0,0 @@
- 'Done:',
- 'Migrating:' => 'Running:',
- 'Migration not found' => 'Action not found',
- 'Migration table created successfully' => 'Action table created successfully',
- 'Migration table not found' => 'Actions table not found',
- 'No migrations found' => 'No actions found',
- 'Nothing to migrate' => 'Nothing to do',
- ];
-
- public function replace(string $value): string
- {
- return str_replace(
- array_keys($this->available),
- array_values($this->available),
- $value
- );
- }
-}
diff --git a/src/Support/MigrationCreator.php b/src/Support/MigrationCreator.php
deleted file mode 100644
index 02ad9a32..00000000
--- a/src/Support/MigrationCreator.php
+++ /dev/null
@@ -1,42 +0,0 @@
-customStubPath = $custom_stub_path;
- }
-
- public function create($name, $path, $table = null, $create = false)
- {
- $this->files->ensureDirectoryExists($path);
-
- return parent::create($name, $path, $table, $create);
- }
-
- public function stubPath()
- {
- return realpath($this->customStubPath);
- }
-
- protected function getStub($table, $create): string
- {
- $stub = $this->allowAnonymous() ? '/action-anonymous.stub' : '/action-named.stub';
-
- return $this->files->get(
- $this->stubPath() . $stub
- );
- }
-}
diff --git a/src/Support/Migrator.php b/src/Support/Migrator.php
deleted file mode 100644
index 6eefe326..00000000
--- a/src/Support/Migrator.php
+++ /dev/null
@@ -1,269 +0,0 @@
-resolver->getDefaultConnection();
-
- $this->setConnection($name);
-
- return tap($callback(), function () use ($prev) {
- $this->setConnection($prev);
- });
- }
-
- public function runPending(array $migrations, array $options = [])
- {
- $this->is_before = $options['before'] ?? false;
-
- return parent::runPending($migrations, $options);
- }
-
- /**
- * Run "up" a migration instance.
- *
- * @param string $file
- * @param int $batch
- * @param bool $pretend
- *
- * @throws Throwable
- */
- protected function runUp($file, $batch, $pretend)
- {
- // First we will resolve a "real" instance of the migration class from this
- // migration file name. Once we have the instances we can run the actual
- // command such as "up" or "down", or we can just simulate the action.
- if ($this->allowAnonymous()) {
- $migration = $this->resolvePath($file);
-
- $name = $this->getMigrationName($file);
- }
- else {
- $migration = $this->resolve(
- $name = $this->getMigrationName($file)
- );
- }
-
- if (! $this->allowEnvironment($migration)) {
- $this->note("Migrate: {$name} was skipped on this environment");
-
- return;
- }
-
- if ($this->disallowBefore($migration)) {
- $this->note("Migrate: {$name} was omitted because the 'before' parameter is enabled.");
-
- return;
- }
-
- if ($pretend) {
- $this->pretendToRun($migration, 'up');
-
- return;
- }
-
- $this->note("Migrating: {$name}");
-
- $startTime = microtime(true);
-
- $this->runMigration($migration, 'up');
-
- $runTime = number_format((microtime(true) - $startTime) * 1000, 2);
-
- // Once we have run a migrations class, we will log that it was run in this
- // repository so that we don't try to run it next time we do a migration
- // in the application. A migration repository keeps the migrate order.
- if ($this->allowLogging($migration)) {
- $this->repository->log($name, $batch);
- }
-
- $this->note("Migrated: {$name} ({$runTime}ms)");
- }
-
- /**
- * Run "down" a migration instance.
- *
- * @param string $file
- * @param object $migration
- * @param bool $pretend
- *
- * @throws Throwable
- */
- protected function runDown($file, $migration, $pretend)
- {
- if ($this->allowAnonymous()) {
- $instance = $this->resolvePath($file);
-
- $name = $this->getMigrationName($file);
- }
- else {
- $instance = $this->resolve(
- $name = $this->getMigrationName($file)
- );
- }
-
- if (! $this->allowEnvironment($instance)) {
- $this->note("Rolling back: {$name} was skipped on this environment");
-
- return;
- }
-
- parent::runDown($file, $migration, $pretend);
- }
-
- /**
- * Starts the execution of code, starting database transactions, if necessary.
- *
- * @param object $migration
- * @param string $method
- *
- * @throws Throwable
- */
- protected function runMigration($migration, $method)
- {
- $this->runMigrationHandle($migration, function ($migration) use ($method) {
- if ($this->enabledTransactions($migration)) {
- DB::transaction(function () use ($migration, $method) {
- parent::runMigration($migration, $method);
- }, $this->transactionAttempts($migration));
-
- return;
- }
-
- parent::runMigration($migration, $method);
- });
- }
-
- /**
- * Whether it is necessary to record information about the execution in the database.
- *
- * @param \DragonCode\Contracts\LaravelActions\Actionable|object $migration
- *
- * @return bool
- */
- protected function allowLogging(ActionableContract $migration): bool
- {
- return $migration->isOnce();
- }
-
- /**
- * Whether the action needs to be executed in the current environment.
- *
- * @param \DragonCode\Contracts\LaravelActions\Actionable|object $migration
- *
- * @return bool
- */
- protected function allowEnvironment(ActionableContract $migration): bool
- {
- $environment = config('app.env', 'production');
-
- $on = $migration->onEnvironment();
- $except = $migration->exceptEnvironment();
- $allow = $migration->allow();
-
- if (! $allow) {
- return false;
- }
-
- if (! empty($on) && ! in_array($environment, $on)) {
- return false;
- }
-
- return ! (! empty($except) && in_array($environment, $except));
- }
-
- /**
- * Whether it is necessary to call database transactions at runtime.
- *
- * @param \DragonCode\LaravelActions\Support\Actionable|object $migration
- *
- * @return bool
- */
- protected function enabledTransactions(ActionableContract $migration): bool
- {
- return $migration->enabledTransactions();
- }
-
- /**
- * The number of attempts to execute a request within a transaction before throwing an error.
- *
- * @param \DragonCode\LaravelActions\Support\Actionable|object $migration
- *
- * @return int
- */
- protected function transactionAttempts(ActionableContract $migration): int
- {
- $value = $migration->transactionAttempts();
-
- return (int) abs($value);
- }
-
- /**
- * Defines a possible "pre-launch" of the action.
- *
- * @param \DragonCode\Contracts\LaravelActions\Actionable|object $migration
- *
- * @return bool
- */
- protected function disallowBefore(ActionableContract $migration): bool
- {
- return $this->is_before && ! $migration->hasBefore();
- }
-
- /**
- * @param \DragonCode\Contracts\LaravelActions\Actionable|object $migration
- * @param callable $handle
- *
- * @throws Throwable
- *
- * @return void
- */
- protected function runMigrationHandle(ActionableContract $migration, callable $handle)
- {
- try {
- $handle($migration);
-
- $this->runSuccess($migration);
- }
- catch (Throwable $e) {
- $this->runFailed($migration);
-
- throw $e;
- }
- }
-
- /**
- * @param \DragonCode\Contracts\LaravelActions\Actionable|object $migration
- *
- * @return void
- */
- protected function runSuccess(ActionableContract $migration): void
- {
- $migration->success();
- }
-
- /**
- * @param \DragonCode\Contracts\LaravelActions\Actionable|object $migration
- *
- * @return void
- */
- protected function runFailed(ActionableContract $migration): void
- {
- $migration->failed();
- }
-}
diff --git a/src/Values/Options.php b/src/Values/Options.php
new file mode 100644
index 00000000..560e3ed4
--- /dev/null
+++ b/src/Values/Options.php
@@ -0,0 +1,40 @@
+replace('\\', '/')
+ ->replace('.php', '')
+ ->explode('/')
+ ->map(fn (string $path) => Str::snake($path))
+ ->implode(DIRECTORY_SEPARATOR)
+ ->toString();
+ }
+}
diff --git a/tests/Commands/CreatorTest.php b/tests/Commands/CreatorTest.php
deleted file mode 100644
index 0f86dfd1..00000000
--- a/tests/Commands/CreatorTest.php
+++ /dev/null
@@ -1,61 +0,0 @@
-targetDirectory($filename);
-
- $this->assertFileDoesNotExist($path);
-
- $this->artisan('make:migration:action', compact('name'))->run();
-
- $this->assertFileExists($path);
- }
-
- public function testDuplicateOnPrev()
- {
- if ($this->allowAnonymous()) {
- $this->assertTrue(true);
-
- return;
- }
-
- $this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage('A BarExample class already exists.');
-
- $name = 'BarExample';
-
- $this->artisan('make:migration:action', compact('name'))->run();
- $this->artisan('make:migration:action', compact('name'))->run();
- }
-
- public function testDuplicateOnLatest()
- {
- if ($this->disallowAnonymous()) {
- $this->assertTrue(true);
-
- return;
- }
-
- $name = 'BarExample';
-
- $time1 = date('Y_m_d_His');
- $this->artisan('make:migration:action', compact('name'))->run();
-
- $time2 = date('Y_m_d_His');
- $this->artisan('make:migration:action', compact('name'))->run();
-
- $this->assertFileExists($this->targetDirectory($time1 . '_bar_example.php'));
- $this->assertFileExists($this->targetDirectory($time2 . '_bar_example.php'));
- }
-}
diff --git a/tests/Commands/FreshTest.php b/tests/Commands/FreshTest.php
index fe1192bd..e8251a13 100644
--- a/tests/Commands/FreshTest.php
+++ b/tests/Commands/FreshTest.php
@@ -4,26 +4,29 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Tests\TestCase;
class FreshTest extends TestCase
{
- public function testFreshCommand()
+ public function testFreshCommand(): void
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
- $this->artisan('make:migration:action', ['name' => 'Fresh'])->run();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MAKE, ['name' => 'Fresh'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 1);
- $this->artisan('migrate:actions:fresh')->run();
+ $this->artisan(Names::FRESH)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 1);
$this->assertDatabaseMigrationHas($this->table, 'fresh');
}
diff --git a/tests/Commands/InstallTest.php b/tests/Commands/InstallTest.php
index 6153895f..352332f4 100644
--- a/tests/Commands/InstallTest.php
+++ b/tests/Commands/InstallTest.php
@@ -2,24 +2,26 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Tests\TestCase;
class InstallTest extends TestCase
{
- public function testRepositoryNotFound()
+ public function testCreate(): void
{
$this->assertDatabaseDoesntTable($this->table);
- $this->hasTermwind()
- ? $this->artisan('migrate:actions:status')
- : $this->artisan('migrate:actions:status')->expectsOutput('Actions table not found.');
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
+
+ $this->assertDatabaseHasTable($this->table);
}
- public function testRepository()
+ public function testAlreadyCreated(): void
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
}
diff --git a/tests/Commands/MakeTest.php b/tests/Commands/MakeTest.php
index 97577973..d996bd97 100644
--- a/tests/Commands/MakeTest.php
+++ b/tests/Commands/MakeTest.php
@@ -2,6 +2,7 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Tests\TestCase;
class MakeTest extends TestCase
@@ -10,35 +11,100 @@ public function testMakingFiles()
{
$name = 'MakeExample';
- $filename = date('Y_m_d_His') . '_make_example.php';
+ $path = $this->getActionsPath() . '/' . date('Y_m_d_His') . '_make_example.php';
- $path = database_path('actions/' . $filename);
+ $this->assertFileDoesNotExist($path);
+
+ $this->artisan(Names::MAKE, compact('name'))->assertExitCode(0);
+
+ $this->assertFileExists($path);
+
+ $this->assertEquals(
+ file_get_contents(__DIR__ . '/../fixtures/app/stubs/make_example.stub'),
+ file_get_contents($path)
+ );
+ }
+
+ public function testAutoName()
+ {
+ $path = $this->getActionsPath() . '/' . date('Y_m_d_His') . '_auto.php';
$this->assertFileDoesNotExist($path);
- $this->artisan('make:migration:action', compact('name'))->run();
+ $this->artisan(Names::MAKE)->assertExitCode(0);
$this->assertFileExists($path);
+ }
- $expected = $this->allowAnonymous()
- ? __DIR__ . '/../fixtures/app/anonymous/stubs/make_example.stub'
- : __DIR__ . '/../fixtures/app/named/stubs/make_example.stub';
+ public function testNestedRightSlashWithoutExtension()
+ {
+ $name = 'Foo/bar/QweRty';
+
+ $path = $this->getActionsPath() . '/foo/bar/' . date('Y_m_d_His') . '_qwe_rty.php';
+
+ $this->assertFileDoesNotExist($path);
+
+ $this->artisan(Names::MAKE, compact('name'))->assertExitCode(0);
- $this->assertEquals(file_get_contents($expected), file_get_contents($path));
+ $this->assertFileExists($path);
+
+ $this->assertEquals(
+ file_get_contents(__DIR__ . '/../fixtures/app/stubs/make_example.stub'),
+ file_get_contents($path)
+ );
}
- public function testAutoName()
+ public function testNestedRightSlashWithExtension()
{
- $filename = $this->allowAnonymous()
- ? date('Y_m_d_His') . '_auto.php'
- : date('Y_m_d_His') . '_auto_' . time() . '.php';
+ $name = 'Foo/bar/QweRty.php';
- $path = database_path('actions/' . $filename);
+ $path = $this->getActionsPath() . '/foo/bar/' . date('Y_m_d_His') . '_qwe_rty.php';
$this->assertFileDoesNotExist($path);
- $this->artisan('make:migration:action')->run();
+ $this->artisan(Names::MAKE, compact('name'))->assertExitCode(0);
$this->assertFileExists($path);
+
+ $this->assertEquals(
+ file_get_contents(__DIR__ . '/../fixtures/app/stubs/make_example.stub'),
+ file_get_contents($path)
+ );
+ }
+
+ public function testNestedLeftSlashWithoutExtension()
+ {
+ $name = 'Foo\\bar\\QweRty';
+
+ $path = $this->getActionsPath() . '/foo/bar/' . date('Y_m_d_His') . '_qwe_rty.php';
+
+ $this->assertFileDoesNotExist($path);
+
+ $this->artisan(Names::MAKE, compact('name'))->assertExitCode(0);
+
+ $this->assertFileExists($path);
+
+ $this->assertEquals(
+ file_get_contents(__DIR__ . '/../fixtures/app/stubs/make_example.stub'),
+ file_get_contents($path)
+ );
+ }
+
+ public function testNestedLeftSlashWithExtension()
+ {
+ $name = 'Foo\\bar\\QweRty.php';
+
+ $path = $this->getActionsPath() . '/foo/bar/' . date('Y_m_d_His') . '_qwe_rty.php';
+
+ $this->assertFileDoesNotExist($path);
+
+ $this->artisan(Names::MAKE, compact('name'))->assertExitCode(0);
+
+ $this->assertFileExists($path);
+
+ $this->assertEquals(
+ file_get_contents(__DIR__ . '/../fixtures/app/stubs/make_example.stub'),
+ file_get_contents($path)
+ );
}
}
diff --git a/tests/Commands/MigrateTest.php b/tests/Commands/MigrateTest.php
index 1e6b717c..2027859d 100644
--- a/tests/Commands/MigrateTest.php
+++ b/tests/Commands/MigrateTest.php
@@ -2,6 +2,7 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Exception;
use Illuminate\Support\Str;
use Tests\TestCase;
@@ -13,48 +14,68 @@ public function testMigrationCommand()
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
- $this->artisan('make:migration:action', ['name' => 'TestMigration'])->run();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MAKE, ['name' => 'TestMigration'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($this->table, 1);
$this->assertDatabaseMigrationHas($this->table, 'test_migration');
}
+ public function testSameName()
+ {
+ $this->assertDatabaseDoesntTable($this->table);
+
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
+
+ $this->assertDatabaseHasTable($this->table);
+ $this->assertDatabaseCount($this->table, 0);
+
+ $this->artisan(Names::MAKE, ['name' => 'TestMigration'])->assertExitCode(0);
+
+ sleep(2);
+
+ $this->artisan(Names::MAKE, ['name' => 'TestMigration'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+
+ $this->assertDatabaseCount($this->table, 2);
+ $this->assertDatabaseMigrationHas($this->table, 'test_migration');
+ }
+
public function testOnce()
{
$this->copyFiles();
$table = 'every_time';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, $table);
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, $table);
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, $table);
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 3);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, $table);
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 4);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, $table);
}
@@ -64,12 +85,12 @@ public function testSuccessTransaction()
$table = 'transactions';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, $table);
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 3);
$this->assertDatabaseCount($this->table, 1);
@@ -82,14 +103,14 @@ public function testFailedTransaction()
$table = 'transactions';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, $table);
try {
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
}
catch (Exception $e) {
$this->assertSame(Exception::class, get_class($e));
@@ -107,7 +128,7 @@ public function testSingleEnvironment()
$table = 'environment';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
@@ -116,19 +137,19 @@ public function testSingleEnvironment()
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_testing');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_production');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_testing');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 5);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_on_all');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_production');
$this->assertDatabaseMigrationHas($this->table, 'run_on_testing');
$this->assertDatabaseMigrationHas($this->table, 'run_except_production');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_testing');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 5);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_on_all');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_production');
$this->assertDatabaseMigrationHas($this->table, 'run_on_testing');
@@ -142,7 +163,7 @@ public function testManyEnvironments()
$table = 'environment';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
@@ -153,10 +174,10 @@ public function testManyEnvironments()
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_production');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_testing');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_many_environments');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 5);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_on_all');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_production');
$this->assertDatabaseMigrationHas($this->table, 'run_on_testing');
@@ -164,10 +185,10 @@ public function testManyEnvironments()
$this->assertDatabaseMigrationHas($this->table, 'run_except_production');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_testing');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_except_many_environments');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 5);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_on_all');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_production');
$this->assertDatabaseMigrationHas($this->table, 'run_on_testing');
@@ -183,22 +204,22 @@ public function testAllow()
$table = 'environment';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_allow');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_disallow');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 5);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_allow');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_disallow');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 5);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_allow');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_disallow');
}
@@ -209,15 +230,15 @@ public function testUpSuccess()
$table = 'success';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_success');
}
@@ -227,21 +248,21 @@ public function testUpSuccessOnFailed()
$table = 'success';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success_on_failed');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success_on_failed');
try {
$this->copySuccessFailureMethod();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
}
catch (Throwable $e) {
$this->assertInstanceOf(Exception::class, $e);
@@ -252,7 +273,7 @@ public function testUpSuccessOnFailed()
}
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success_on_failed');
}
@@ -262,15 +283,15 @@ public function testUpFailed()
$table = 'failed';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_failed');
}
@@ -280,21 +301,21 @@ public function testUpFailedOnException()
$table = 'failed';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed_failure');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed_failure');
try {
$this->copyFailedMethod();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
}
catch (Throwable $e) {
$this->assertInstanceOf(Exception::class, $e);
@@ -305,7 +326,7 @@ public function testUpFailedOnException()
}
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed_failure');
}
@@ -317,12 +338,12 @@ public function testPathAsFileWithExtension()
$path = 'sub_path/2021_12_15_205804_baz.php';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'baz');
- $this->artisan('migrate:actions', ['--path' => $path])->run();
+ $this->artisan(Names::MIGRATE, ['--path' => $path])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
$this->assertDatabaseCount($this->table, 1);
@@ -337,12 +358,12 @@ public function testPathAsFileWithoutExtension()
$path = 'sub_path/2021_12_15_205804_baz';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'baz');
- $this->artisan('migrate:actions', ['--path' => $path])->run();
+ $this->artisan(Names::MIGRATE, ['--path' => $path])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
$this->assertDatabaseCount($this->table, 1);
@@ -357,12 +378,12 @@ public function testPathAsDirectory()
$path = 'sub_path';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'baz');
- $this->artisan('migrate:actions', ['--path' => $path])->run();
+ $this->artisan(Names::MIGRATE, ['--path' => $path])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
$this->assertDatabaseCount($this->table, 1);
@@ -373,13 +394,11 @@ public function testMigrationNotFound()
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
- $this->hasTermwind()
- ? $this->artisan('migrate:actions:status')
- : $this->artisan('migrate:actions:status')->expectsOutput('No actions found');
+ $this->artisan(Names::STATUS)->assertExitCode(0);
}
public function testDisabledBefore()
@@ -388,22 +407,22 @@ public function testDisabledBefore()
$table = 'before';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationHas($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationHas($this->table, 'test_before_disabled');
}
@@ -414,22 +433,22 @@ public function testEnabledBefore()
$table = 'before';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions', ['--before' => true])->run();
+ $this->artisan(Names::MIGRATE, ['--before' => true])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 9);
+ $this->assertDatabaseCount($this->table, 10);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions', ['--before' => true])->run();
+ $this->artisan(Names::MIGRATE, ['--before' => true])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 9);
+ $this->assertDatabaseCount($this->table, 10);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
}
@@ -440,35 +459,63 @@ public function testMixedBefore()
$table = 'before';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions', ['--before' => true])->run();
+ $this->artisan(Names::MIGRATE, ['--before' => true])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 9);
+ $this->assertDatabaseCount($this->table, 10);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions', ['--before' => true])->run();
+ $this->artisan(Names::MIGRATE, ['--before' => true])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 9);
+ $this->assertDatabaseCount($this->table, 10);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationHas($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationHas($this->table, 'test_before_disabled');
}
+
+ public function testDI(): void
+ {
+ $this->copyDI();
+
+ $table = 'test';
+
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
+
+ $this->assertDatabaseCount($table, 0);
+ $this->assertDatabaseCount($this->table, 0);
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'invoke');
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'invoke_down');
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'up_down');
+ $this->assertDatabaseMigrationDoesntLike($table, 'up_down', column: 'value');
+ $this->assertDatabaseMigrationDoesntLike($table, 'invoke_down', column: 'value');
+ $this->assertDatabaseMigrationDoesntLike($table, 'invoke', column: 'value');
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+
+ $this->assertDatabaseCount($table, 3);
+ $this->assertDatabaseCount($this->table, 3);
+ $this->assertDatabaseMigrationHas($this->table, 'invoke');
+ $this->assertDatabaseMigrationHas($this->table, 'invoke_down');
+ $this->assertDatabaseMigrationHas($this->table, 'up_down');
+ $this->assertDatabaseMigrationHas($table, 'up_down', column: 'value');
+ $this->assertDatabaseMigrationHas($table, 'invoke_down', column: 'value');
+ $this->assertDatabaseMigrationHas($table, 'invoke', column: 'value');
+ }
}
diff --git a/tests/Commands/RefreshTest.php b/tests/Commands/RefreshTest.php
index 3586449c..f6ea10ff 100644
--- a/tests/Commands/RefreshTest.php
+++ b/tests/Commands/RefreshTest.php
@@ -2,6 +2,7 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Tests\TestCase;
class RefreshTest extends TestCase
@@ -10,18 +11,20 @@ public function testRefreshCommand()
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
- $this->artisan('make:migration:action', ['name' => 'Refresh'])->run();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MAKE, ['name' => 'Refresh'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 1);
- $this->artisan('migrate:actions:refresh')->run();
+ $this->artisan(Names::REFRESH)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 1);
$this->assertDatabaseMigrationHas($this->table, 'refresh');
}
diff --git a/tests/Commands/ResetTest.php b/tests/Commands/ResetTest.php
index be9d18f1..5be868cb 100644
--- a/tests/Commands/ResetTest.php
+++ b/tests/Commands/ResetTest.php
@@ -2,6 +2,7 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Tests\TestCase;
class ResetTest extends TestCase
@@ -10,19 +11,21 @@ public function testResetCommand()
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
- $this->artisan('make:migration:action', ['name' => 'Reset'])->run();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MAKE, ['name' => 'Reset'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 1);
$this->assertDatabaseMigrationHas($this->table, 'reset');
- $this->artisan('migrate:actions:reset')->run();
+ $this->artisan(Names::RESET)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'reset');
}
diff --git a/tests/Commands/RollbackTest.php b/tests/Commands/RollbackTest.php
index 5728f857..90c6b270 100644
--- a/tests/Commands/RollbackTest.php
+++ b/tests/Commands/RollbackTest.php
@@ -2,6 +2,7 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Exception;
use Illuminate\Support\Str;
use Tests\TestCase;
@@ -13,32 +14,37 @@ public function testRollbackCommand()
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
- $this->artisan('make:migration:action', ['name' => 'RollbackOne'])->run();
- $this->artisan('make:migration:action', ['name' => 'RollbackTwo'])->run();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MAKE, ['name' => 'RollbackOne'])->assertExitCode(0);
+ $this->artisan(Names::MAKE, ['name' => 'RollbackTwo'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 2);
$this->assertDatabaseMigrationHas($this->table, 'rollback_one');
$this->assertDatabaseMigrationHas($this->table, 'rollback_two');
$this->assertDatabaseMigrationDoesntLike($this->table, 'rollback_tree');
- $this->artisan('migrate:actions:rollback')->run();
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 2);
- $this->artisan('make:migration:action', ['name' => 'RollbackTree'])->run();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MAKE, ['name' => 'RollbackTree'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+ $this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 3);
$this->assertDatabaseMigrationHas($this->table, 'rollback_one');
@@ -52,7 +58,7 @@ public function testEnvironment()
$table = 'environment';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
@@ -60,17 +66,17 @@ public function testEnvironment()
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_production');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_testing');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_many_environments');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 5);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_on_all');
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_production');
$this->assertDatabaseMigrationHas($this->table, 'run_on_testing');
$this->assertDatabaseMigrationHas($this->table, 'run_on_many_environments');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
- $this->artisan('migrate:actions:rollback')->run();
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
$this->assertDatabaseCount($table, 10);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_on_all');
@@ -85,18 +91,18 @@ public function testDownSuccess()
$table = 'success';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_success');
- $this->artisan('migrate:actions:rollback')->run();
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
$this->assertDatabaseCount($table, 4);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success');
@@ -108,23 +114,27 @@ public function testDownSuccessOnFailed()
$table = 'success';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success_on_failed');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_success_on_failed');
try {
$this->copySuccessFailureMethod();
- $this->table()->insert(['migration' => '2021_12_23_165048_run_success_on_failed', 'batch' => 999]);
+ $this->table()->insert(['action' => '2021_12_23_165048_run_success_on_failed', 'batch' => 999]);
- $this->artisan('migrate:actions:rollback')->run();
+ $this->assertDatabaseCount($table, 2);
+ $this->assertDatabaseCount($this->table, 12);
+ $this->assertDatabaseMigrationHas($this->table, 'run_success_on_failed');
+
+ $this->artisan(Names::ROLLBACK)->assertExitCode(1);
}
catch (Throwable $e) {
$this->assertInstanceOf(Exception::class, $e);
@@ -135,7 +145,7 @@ public function testDownSuccessOnFailed()
}
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 11);
+ $this->assertDatabaseCount($this->table, 12);
$this->assertDatabaseMigrationHas($this->table, 'run_success_on_failed');
}
@@ -145,18 +155,18 @@ public function testDownFailed()
$table = 'failed';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'run_failed');
- $this->artisan('migrate:actions:rollback')->run();
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed');
@@ -168,23 +178,23 @@ public function testUpFailedOnException()
$table = 'failed';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed_failure');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationDoesntLike($this->table, 'run_failed_failure');
try {
$this->copyFailedMethod();
- $this->table()->insert(['migration' => '2021_12_23_184029_run_failed_failure', 'batch' => 999]);
+ $this->table()->insert(['action' => '2021_12_23_184029_run_failed_failure', 'batch' => 999]);
- $this->artisan('migrate:actions:rollback')->run();
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
}
catch (Throwable $e) {
$this->assertInstanceOf(Exception::class, $e);
@@ -195,7 +205,7 @@ public function testUpFailedOnException()
}
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 11);
+ $this->assertDatabaseCount($this->table, 12);
$this->assertDatabaseMigrationHas($this->table, 'run_failed_failure');
}
@@ -205,21 +215,21 @@ public function testDisabledBefore()
$table = 'before';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
- $this->assertDatabaseCount($this->table, 10);
+ $this->assertDatabaseCount($this->table, 11);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationHas($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
- $this->artisan('migrate:actions:rollback')->run();
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
$this->assertDatabaseCount($table, 4);
$this->assertDatabaseCount($this->table, 0);
@@ -233,25 +243,64 @@ public function testEnabledBefore()
$table = 'before';
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseCount($table, 0);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions', ['--before' => true])->run();
+ $this->artisan(Names::MIGRATE, ['--before' => true])->assertExitCode(0);
$this->assertDatabaseCount($table, 1);
- $this->assertDatabaseCount($this->table, 9);
+ $this->assertDatabaseCount($this->table, 10);
$this->assertDatabaseMigrationHas($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
- $this->artisan('migrate:actions', ['--before' => true])->run();
+ $this->artisan(Names::MIGRATE, ['--before' => true])->assertExitCode(0);
- $this->artisan('migrate:actions:rollback')->run();
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
$this->assertDatabaseCount($table, 2);
$this->assertDatabaseCount($this->table, 0);
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_enabled');
$this->assertDatabaseMigrationDoesntLike($this->table, 'test_before_disabled');
}
+
+ public function testDI(): void
+ {
+ $this->copyDI();
+
+ $table = 'test';
+
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
+
+ $this->assertDatabaseCount($table, 0);
+ $this->assertDatabaseCount($this->table, 0);
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'invoke');
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'invoke_down');
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'up_down');
+ $this->assertDatabaseMigrationDoesntLike($table, 'up_down', column: 'value');
+ $this->assertDatabaseMigrationDoesntLike($table, 'invoke_down', column: 'value');
+ $this->assertDatabaseMigrationDoesntLike($table, 'invoke', column: 'value');
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
+
+ $this->assertDatabaseCount($table, 3);
+ $this->assertDatabaseCount($this->table, 3);
+ $this->assertDatabaseMigrationHas($this->table, 'invoke');
+ $this->assertDatabaseMigrationHas($this->table, 'invoke_down');
+ $this->assertDatabaseMigrationHas($this->table, 'up_down');
+ $this->assertDatabaseMigrationHas($table, 'up_down', column: 'value');
+ $this->assertDatabaseMigrationHas($table, 'invoke_down', column: 'value');
+ $this->assertDatabaseMigrationHas($table, 'invoke', column: 'value');
+
+ $this->artisan(Names::ROLLBACK)->assertExitCode(0);
+
+ $this->assertDatabaseCount($table, 2);
+ $this->assertDatabaseCount($this->table, 0);
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'invoke');
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'invoke_down');
+ $this->assertDatabaseMigrationDoesntLike($this->table, 'up_down');
+ $this->assertDatabaseMigrationDoesntLike($table, 'up_down', column: 'value');
+ $this->assertDatabaseMigrationHas($table, 'invoke_down', column: 'value');
+ $this->assertDatabaseMigrationHas($table, 'invoke', column: 'value');
+ }
}
diff --git a/tests/Commands/StatusTest.php b/tests/Commands/StatusTest.php
index 4b788462..28c8fae1 100644
--- a/tests/Commands/StatusTest.php
+++ b/tests/Commands/StatusTest.php
@@ -2,29 +2,37 @@
namespace Tests\Commands;
+use DragonCode\LaravelActions\Constants\Names;
use Tests\TestCase;
class StatusTest extends TestCase
{
+ public function testNotFound(): void
+ {
+ $this->assertDatabaseDoesntTable($this->table);
+
+ $this->artisan(Names::STATUS)->assertExitCode(0);
+
+ $this->assertDatabaseDoesntTable($this->table);
+ }
+
public function testStatusCommand()
{
$this->assertDatabaseDoesntTable($this->table);
- $this->artisan('migrate:actions:install')->run();
+ $this->artisan(Names::INSTALL)->assertExitCode(0);
$this->assertDatabaseHasTable($this->table);
$this->assertDatabaseCount($this->table, 0);
- $this->is6x()
- ? $this->artisan('migrate:actions:status')->run()
- : $this->artisan('migrate:actions:status')->expectsTable([], [])->run();
+ $this->artisan(Names::STATUS)->expectsTable([], [])->assertExitCode(0);
- $this->artisan('make:migration:action', ['name' => 'Status'])->run();
- $this->artisan('migrate:actions')->run();
+ $this->artisan(Names::MAKE, ['name' => 'Status'])->assertExitCode(0);
+ $this->artisan(Names::MIGRATE)->assertExitCode(0);
$this->assertDatabaseCount($this->table, 1);
- $this->artisan('migrate:actions:status')->run();
+ $this->artisan(Names::STATUS)->assertExitCode(0);
$this->assertDatabaseMigrationHas($this->table, 'status');
}
diff --git a/tests/Concerns/Actionable.php b/tests/Concerns/Actionable.php
deleted file mode 100644
index e46ed374..00000000
--- a/tests/Concerns/Actionable.php
+++ /dev/null
@@ -1,13 +0,0 @@
-allowAnonymous()
- ? __DIR__ . '/../fixtures/app/anonymous/actions'
- : __DIR__ . '/../fixtures/app/named/actions';
- }
-}
diff --git a/tests/Concerns/AssertDatabase.php b/tests/Concerns/AssertDatabase.php
index 7d21b25d..8c435bc0 100644
--- a/tests/Concerns/AssertDatabase.php
+++ b/tests/Concerns/AssertDatabase.php
@@ -8,13 +8,6 @@
/** @mixin \Tests\TestCase */
trait AssertDatabase
{
- protected function assertDatabaseCount($table, int $count, $connection = null): void
- {
- $actual = DB::connection($connection)->table($table)->count();
-
- $this->assertEquals($count, $actual);
- }
-
protected function assertDatabaseHasTable(string $table): void
{
$this->assertTrue(
@@ -29,31 +22,31 @@ protected function assertDatabaseDoesntTable(string $table): void
);
}
- protected function assertDatabaseMigrationHas(string $table, $value, $connection = null): void
+ protected function assertDatabaseMigrationHas(string $table, $value, $connection = null, string $column = 'action'): void
{
- $this->assertDatabaseHasLike($table, 'migration', $value, $connection);
+ $this->assertDatabaseHasLike($table, $column, $value, $connection);
}
protected function assertDatabaseHasLike(string $table, string $column, $value, $connection = null): void
{
$exists = DB::connection($connection)
->table($table)
- ->whereRaw("{$column} like '%$value%'")
+ ->whereRaw("$column like '%$value%'")
->exists();
$this->assertTrue($exists);
}
- protected function assertDatabaseMigrationDoesntLike(string $table, $value, $connection = null): void
+ protected function assertDatabaseMigrationDoesntLike(string $table, $value, $connection = null, string $column = 'action'): void
{
- $this->assertDatabaseDoesntLike($table, 'migration', $value, $connection);
+ $this->assertDatabaseDoesntLike($table, $column, $value, $connection);
}
protected function assertDatabaseDoesntLike(string $table, string $column, $value, $connection = null): void
{
$exists = DB::connection($connection)
->table($table)
- ->whereRaw("{$column} like '%$value%'")
+ ->whereRaw("$column like '%$value%'")
->doesntExist();
$this->assertTrue($exists);
diff --git a/tests/Concerns/Database.php b/tests/Concerns/Database.php
index 50fa5fb0..24de59fb 100644
--- a/tests/Concerns/Database.php
+++ b/tests/Concerns/Database.php
@@ -4,7 +4,9 @@
trait Database
{
- protected $database = 'testing';
+ protected string $database = 'testing';
+
+ protected string $table = 'foo_actions';
protected function setDatabase($app): void
{
@@ -15,6 +17,9 @@ protected function setDatabase($app): void
'database' => ':memory:',
'prefix' => '',
]);
+
+ $app['config']->set('actions.connection', $this->database);
+ $app['config']->set('actions.table', $this->table);
}
protected function freshDatabase(): void
@@ -27,8 +32,8 @@ protected function freshDatabase(): void
protected function loadMigrations(): void
{
- $this->loadMigrationsFrom(
- __DIR__ . '/../fixtures/migrations'
- );
+ $this->allowAnonymousMigrations()
+ ? $this->loadMigrationsFrom(__DIR__ . '/../fixtures/migrations/anonymous')
+ : $this->loadMigrationsFrom(__DIR__ . '/../fixtures/migrations/named');
}
}
diff --git a/tests/Concerns/Files.php b/tests/Concerns/Files.php
index facabfbb..46d7b642 100644
--- a/tests/Concerns/Files.php
+++ b/tests/Concerns/Files.php
@@ -4,6 +4,7 @@
use Illuminate\Support\Facades\File;
+/** @mixin \Tests\TestCase */
trait Files
{
protected function freshFiles(): void
@@ -15,55 +16,63 @@ protected function freshFiles(): void
protected function copyFiles(): void
{
- $source = $this->allowAnonymous()
- ? __DIR__ . '/../fixtures/app/anonymous/actions'
- : __DIR__ . '/../fixtures/app/named/actions';
-
- File::copyDirectory($source, $this->targetDirectory());
+ File::copyDirectory(
+ __DIR__ . '/../fixtures/app/actions',
+ $this->targetDirectory()
+ );
}
- protected function copySuccessFailureMethod()
+ protected function copyDI(): void
{
- $source = $this->allowAnonymous()
- ? __DIR__ . '/../fixtures/app/anonymous/actions_failed/2021_12_23_165048_run_success_on_failed.php'
- : __DIR__ . '/../fixtures/app/named/actions_failed/2021_12_23_165048_run_success_on_failed.php';
-
- File::copy($source, $this->targetDirectory('2021_12_23_165048_run_success_on_failed.php'));
+ File::copyDirectory(
+ __DIR__ . '/../fixtures/app/di',
+ $this->targetDirectory()
+ );
}
- protected function copyFailedMethod()
+ protected function copySuccessFailureMethod(): void
{
- $source = $this->allowAnonymous()
- ? __DIR__ . '/../fixtures/app/anonymous/actions_failed/2021_12_23_184029_run_failed_failure.php'
- : __DIR__ . '/../fixtures/app/named/actions_failed/2021_12_23_184029_run_failed_failure.php';
+ File::copy(
+ __DIR__ . '/../fixtures/app/actions_failed/2021_12_23_165048_run_success_on_failed.php',
+ $this->targetDirectory('2021_12_23_165048_run_success_on_failed.php')
+ );
+ }
- File::copy($source, $this->targetDirectory('2021_12_23_184029_run_failed_failure.php'));
+ protected function copyFailedMethod(): void
+ {
+ File::copy(
+ __DIR__ . '/../fixtures/app/actions_failed/2021_12_23_184029_run_failed_failure.php',
+ $this->targetDirectory('2021_12_23_184029_run_failed_failure.php')
+ );
}
protected function copySuccessTransaction(): void
{
- $source = $this->allowAnonymous()
- ? __DIR__ . '/../fixtures/app/anonymous/stubs/2021_02_15_124237_test_success_transactions.stub'
- : __DIR__ . '/../fixtures/app/named/stubs/2021_02_15_124237_test_success_transactions.stub';
-
- File::copy($source, $this->targetDirectory('2021_02_15_124237_test_success_transactions.php'));
+ File::copy(
+ __DIR__ . '/../fixtures/app/stubs/2021_02_15_124237_test_success_transactions.stub',
+ $this->targetDirectory('2021_02_15_124237_test_success_transactions.php')
+ );
}
protected function copyFailedTransaction(): void
{
- $source = $this->allowAnonymous()
- ? __DIR__ . '/../fixtures/app/anonymous/stubs/2021_02_15_124852_test_failed_transactions.stub'
- : __DIR__ . '/../fixtures/app/named/stubs/2021_02_15_124852_test_failed_transactions.stub';
-
- File::copy($source, $this->targetDirectory('2021_02_15_124852_test_failed_transactions.php'));
+ File::copy(
+ __DIR__ . '/../fixtures/app/stubs/2021_02_15_124852_test_failed_transactions.stub',
+ $this->targetDirectory('2021_02_15_124852_test_failed_transactions.php')
+ );
}
protected function targetDirectory(?string $path = null): string
{
- $dir = database_path('actions');
+ $dir = $this->getActionsPath();
File::ensureDirectoryExists($dir);
return rtrim($dir, '/\\') . '/' . ltrim($path, '/\\');
}
+
+ protected function getActionsPath(): string
+ {
+ return $this->app['config']->get('actions.path');
+ }
}
diff --git a/tests/Concerns/Laraveable.php b/tests/Concerns/Laraveable.php
deleted file mode 100644
index c8e62047..00000000
--- a/tests/Concerns/Laraveable.php
+++ /dev/null
@@ -1,13 +0,0 @@
-set('database.actions', $this->table);
- }
-}
diff --git a/tests/Concerns/Some.php b/tests/Concerns/Some.php
new file mode 100644
index 00000000..5e88dc01
--- /dev/null
+++ b/tests/Concerns/Some.php
@@ -0,0 +1,13 @@
+assertNull(Git::currentBranch(__DIR__));
+ $this->assertNull($this->git()->currentBranch(__DIR__));
}
public function testCurrentBranch()
{
- $branch = Git::currentBranch(__DIR__ . '/../../.git');
+ $branch = $this->git()->currentBranch(__DIR__ . '/../../');
$this->assertIsString($branch);
}
+
+ protected function git(): Git
+ {
+ return $this->app->make(Git::class);
+ }
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 17584d94..4ec6e9a6 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -4,28 +4,21 @@
use DragonCode\LaravelActions\Concerns\Anonymous;
use DragonCode\LaravelActions\ServiceProvider;
-use Illuminate\Console\View\Components\Factory as Components;
use Illuminate\Database\Query\Builder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Orchestra\Testbench\TestCase as BaseTestCase;
-use Tests\Concerns\Actionable;
use Tests\Concerns\AssertDatabase;
use Tests\Concerns\Database;
use Tests\Concerns\Files;
-use Tests\Concerns\Laraveable;
-use Tests\Concerns\Settings;
abstract class TestCase extends BaseTestCase
{
- use Actionable;
- use Anonymous;
use AssertDatabase;
use Database;
use Files;
- use Laraveable;
use RefreshDatabase;
- use Settings;
+ use Anonymous;
protected function setUp(): void
{
@@ -44,7 +37,6 @@ protected function getEnvironmentSetUp($app)
{
parent::getEnvironmentSetUp($app);
- $this->setTable($app);
$this->setDatabase($app);
}
@@ -52,9 +44,4 @@ protected function table(): Builder
{
return DB::table($this->table);
}
-
- protected function hasTermwind(): bool
- {
- return class_exists(Components::class);
- }
}
diff --git a/tests/fixtures/app/named/actions/2020_12_07_153105_foo_bar.php b/tests/fixtures/app/actions/2020_12_07_153105_foo_bar.php
similarity index 82%
rename from tests/fixtures/app/named/actions/2020_12_07_153105_foo_bar.php
rename to tests/fixtures/app/actions/2020_12_07_153105_foo_bar.php
index 4539606f..f8cbd99e 100644
--- a/tests/fixtures/app/named/actions/2020_12_07_153105_foo_bar.php
+++ b/tests/fixtures/app/actions/2020_12_07_153105_foo_bar.php
@@ -1,11 +1,11 @@
table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->truncate();
- }
-
- protected function table(): Builder
- {
- return DB::table('test');
- }
-};
diff --git a/tests/fixtures/app/anonymous/actions/2021_01_02_020947_every_time.php b/tests/fixtures/app/anonymous/actions/2021_01_02_020947_every_time.php
deleted file mode 100644
index 3930ae75..00000000
--- a/tests/fixtures/app/anonymous/actions/2021_01_02_020947_every_time.php
+++ /dev/null
@@ -1,23 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('every_time');
- }
-};
diff --git a/tests/fixtures/app/anonymous/actions/2021_05_24_120003_run_on_all.php b/tests/fixtures/app/anonymous/actions/2021_05_24_120003_run_on_all.php
deleted file mode 100644
index 8a02fbc2..00000000
--- a/tests/fixtures/app/anonymous/actions/2021_05_24_120003_run_on_all.php
+++ /dev/null
@@ -1,28 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-};
diff --git a/tests/fixtures/app/anonymous/actions/2021_10_26_143247_run_allow.php b/tests/fixtures/app/anonymous/actions/2021_10_26_143247_run_allow.php
deleted file mode 100644
index 8a02fbc2..00000000
--- a/tests/fixtures/app/anonymous/actions/2021_10_26_143247_run_allow.php
+++ /dev/null
@@ -1,28 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-};
diff --git a/tests/fixtures/app/anonymous/actions/2021_12_23_165047_run_success.php b/tests/fixtures/app/anonymous/actions/2021_12_23_165047_run_success.php
deleted file mode 100644
index 95d8299b..00000000
--- a/tests/fixtures/app/anonymous/actions/2021_12_23_165047_run_success.php
+++ /dev/null
@@ -1,35 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function success(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('success');
- }
-};
diff --git a/tests/fixtures/app/anonymous/actions/2021_12_23_184029_run_failed.php b/tests/fixtures/app/anonymous/actions/2021_12_23_184029_run_failed.php
deleted file mode 100644
index f9fffa9f..00000000
--- a/tests/fixtures/app/anonymous/actions/2021_12_23_184029_run_failed.php
+++ /dev/null
@@ -1,29 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('success');
- }
-};
diff --git a/tests/fixtures/app/anonymous/actions/sub_path/2021_12_15_205804_baz.php b/tests/fixtures/app/anonymous/actions/sub_path/2021_12_15_205804_baz.php
deleted file mode 100644
index f10667b9..00000000
--- a/tests/fixtures/app/anonymous/actions/sub_path/2021_12_15_205804_baz.php
+++ /dev/null
@@ -1,26 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->truncate();
- }
-
- protected function table(): Builder
- {
- return DB::table('test');
- }
-};
diff --git a/tests/fixtures/app/anonymous/stubs/make_example.stub b/tests/fixtures/app/anonymous/stubs/make_example.stub
deleted file mode 100644
index 09847ca5..00000000
--- a/tests/fixtures/app/anonymous/stubs/make_example.stub
+++ /dev/null
@@ -1,15 +0,0 @@
-table()->insert([
+ 'value' => $some->get('invoke'),
+ ]);
+ }
+
+ protected function table(): Builder
+ {
+ return DB::table('test');
+ }
+};
diff --git a/tests/fixtures/app/di/2022_10_11_234251_invoke_down.php b/tests/fixtures/app/di/2022_10_11_234251_invoke_down.php
new file mode 100644
index 00000000..14b61b41
--- /dev/null
+++ b/tests/fixtures/app/di/2022_10_11_234251_invoke_down.php
@@ -0,0 +1,28 @@
+table()->insert([
+ 'value' => $some->get('invoke_down'),
+ ]);
+ }
+
+ public function down(Some $some): void
+ {
+ $this->table()
+ ->where('value', $some->get('invoke_down'))
+ ->delete();
+ }
+
+ protected function table(): Builder
+ {
+ return DB::table('test');
+ }
+};
diff --git a/tests/fixtures/app/di/2022_10_11_234312_up_down.php b/tests/fixtures/app/di/2022_10_11_234312_up_down.php
new file mode 100644
index 00000000..945adb6a
--- /dev/null
+++ b/tests/fixtures/app/di/2022_10_11_234312_up_down.php
@@ -0,0 +1,28 @@
+table()->insert([
+ 'value' => $some->get('up_down'),
+ ]);
+ }
+
+ public function down(Some $some): void
+ {
+ $this->table()
+ ->where('value', $some->get('up_down'))
+ ->delete();
+ }
+
+ protected function table(): Builder
+ {
+ return DB::table('test');
+ }
+};
diff --git a/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_many_environments.php b/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_many_environments.php
deleted file mode 100644
index 9adfddf9..00000000
--- a/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_many_environments.php
+++ /dev/null
@@ -1,30 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_production.php b/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_production.php
deleted file mode 100644
index 78bc81d2..00000000
--- a/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_production.php
+++ /dev/null
@@ -1,30 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_testing.php b/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_testing.php
deleted file mode 100644
index 53838fc8..00000000
--- a/tests/fixtures/app/named/actions/2021_05_24_120003_run_on_testing.php
+++ /dev/null
@@ -1,30 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2021_06_07_132849_run_except_production.php b/tests/fixtures/app/named/actions/2021_06_07_132849_run_except_production.php
deleted file mode 100644
index e59d8093..00000000
--- a/tests/fixtures/app/named/actions/2021_06_07_132849_run_except_production.php
+++ /dev/null
@@ -1,30 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2021_06_07_132917_run_except_testing.php b/tests/fixtures/app/named/actions/2021_06_07_132917_run_except_testing.php
deleted file mode 100644
index 36f4a9dc..00000000
--- a/tests/fixtures/app/named/actions/2021_06_07_132917_run_except_testing.php
+++ /dev/null
@@ -1,30 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2021_06_07_134045_run_except_many_environments.php b/tests/fixtures/app/named/actions/2021_06_07_134045_run_except_many_environments.php
deleted file mode 100644
index bb4a8094..00000000
--- a/tests/fixtures/app/named/actions/2021_06_07_134045_run_except_many_environments.php
+++ /dev/null
@@ -1,32 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2021_10_26_143304_run_disallow.php b/tests/fixtures/app/named/actions/2021_10_26_143304_run_disallow.php
deleted file mode 100644
index 50e1daff..00000000
--- a/tests/fixtures/app/named/actions/2021_10_26_143304_run_disallow.php
+++ /dev/null
@@ -1,33 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function allow(): bool
- {
- return false;
- }
-
- protected function table(): Builder
- {
- return DB::table('environment');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2022_08_17_135147_test_before_enabled.php b/tests/fixtures/app/named/actions/2022_08_17_135147_test_before_enabled.php
deleted file mode 100644
index 41a64b9f..00000000
--- a/tests/fixtures/app/named/actions/2022_08_17_135147_test_before_enabled.php
+++ /dev/null
@@ -1,30 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('before');
- }
-}
diff --git a/tests/fixtures/app/named/actions/2022_08_17_135153_test_before_disabled.php b/tests/fixtures/app/named/actions/2022_08_17_135153_test_before_disabled.php
deleted file mode 100644
index cd16a417..00000000
--- a/tests/fixtures/app/named/actions/2022_08_17_135153_test_before_disabled.php
+++ /dev/null
@@ -1,30 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- public function down(): void
- {
- $this->table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('before');
- }
-}
diff --git a/tests/fixtures/app/named/actions_failed/2021_12_23_165048_run_success_on_failed.php b/tests/fixtures/app/named/actions_failed/2021_12_23_165048_run_success_on_failed.php
deleted file mode 100644
index dd5ef362..00000000
--- a/tests/fixtures/app/named/actions_failed/2021_12_23_165048_run_success_on_failed.php
+++ /dev/null
@@ -1,31 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('success');
- }
-}
diff --git a/tests/fixtures/app/named/actions_failed/2021_12_23_184029_run_failed_failure.php b/tests/fixtures/app/named/actions_failed/2021_12_23_184029_run_failed_failure.php
deleted file mode 100644
index 75c09925..00000000
--- a/tests/fixtures/app/named/actions_failed/2021_12_23_184029_run_failed_failure.php
+++ /dev/null
@@ -1,31 +0,0 @@
-table()->insert([
- 'value' => Uuid::uuid4(),
- ]);
- }
-
- protected function table(): Builder
- {
- return DB::table('failed');
- }
-}
diff --git a/tests/fixtures/app/named/stubs/2021_02_15_124237_test_success_transactions.stub b/tests/fixtures/app/named/stubs/2021_02_15_124237_test_success_transactions.stub
deleted file mode 100644
index 515e6f1d..00000000
--- a/tests/fixtures/app/named/stubs/2021_02_15_124237_test_success_transactions.stub
+++ /dev/null
@@ -1,29 +0,0 @@
-table()->insert([
- $this->value(),
- $this->value(),
- $this->value(),
- ]);
- }
-
- protected function table()
- {
- return DB::table('transactions');
- }
-
- protected function value(): array
- {
- return ['value' => Uuid::uuid4()];
- }
-}
diff --git a/tests/fixtures/app/named/stubs/2021_02_15_124852_test_failed_transactions.stub b/tests/fixtures/app/named/stubs/2021_02_15_124852_test_failed_transactions.stub
deleted file mode 100644
index afec5ac7..00000000
--- a/tests/fixtures/app/named/stubs/2021_02_15_124852_test_failed_transactions.stub
+++ /dev/null
@@ -1,31 +0,0 @@
-table()->insert([
- $this->value(),
- $this->value(),
- $this->value(),
- ]);
-
- throw new Exception('Random message');
- }
-
- protected function table()
- {
- return DB::table('transactions');
- }
-
- protected function value(): array
- {
- return ['value' => Uuid::uuid4()];
- }
-}
diff --git a/tests/fixtures/app/named/stubs/make_example.stub b/tests/fixtures/app/named/stubs/make_example.stub
deleted file mode 100644
index 2a53c390..00000000
--- a/tests/fixtures/app/named/stubs/make_example.stub
+++ /dev/null
@@ -1,16 +0,0 @@
-uuid('value')->unique();
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('test');
+ }
+};
diff --git a/tests/fixtures/migrations/anonymous/2021_01_02_022431_create_every_time_table.php b/tests/fixtures/migrations/anonymous/2021_01_02_022431_create_every_time_table.php
new file mode 100644
index 00000000..d9522b02
--- /dev/null
+++ b/tests/fixtures/migrations/anonymous/2021_01_02_022431_create_every_time_table.php
@@ -0,0 +1,20 @@
+uuid('value');
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('every_time');
+ }
+};
diff --git a/tests/fixtures/migrations/anonymous/2021_02_15_124419_create_transactions_table.php b/tests/fixtures/migrations/anonymous/2021_02_15_124419_create_transactions_table.php
new file mode 100644
index 00000000..833e4846
--- /dev/null
+++ b/tests/fixtures/migrations/anonymous/2021_02_15_124419_create_transactions_table.php
@@ -0,0 +1,20 @@
+uuid('value');
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('transactions');
+ }
+};
diff --git a/tests/fixtures/migrations/anonymous/2021_05_24_122027_create_environment_table.php b/tests/fixtures/migrations/anonymous/2021_05_24_122027_create_environment_table.php
new file mode 100644
index 00000000..254a9b8b
--- /dev/null
+++ b/tests/fixtures/migrations/anonymous/2021_05_24_122027_create_environment_table.php
@@ -0,0 +1,20 @@
+uuid('value');
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('environment');
+ }
+};
diff --git a/tests/fixtures/migrations/anonymous/2021_12_23_165218_create_success_table.php b/tests/fixtures/migrations/anonymous/2021_12_23_165218_create_success_table.php
new file mode 100644
index 00000000..a96f2b24
--- /dev/null
+++ b/tests/fixtures/migrations/anonymous/2021_12_23_165218_create_success_table.php
@@ -0,0 +1,20 @@
+string('value');
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('success');
+ }
+};
diff --git a/tests/fixtures/migrations/anonymous/2021_12_23_184434_create_failed_table.php b/tests/fixtures/migrations/anonymous/2021_12_23_184434_create_failed_table.php
new file mode 100644
index 00000000..493529ef
--- /dev/null
+++ b/tests/fixtures/migrations/anonymous/2021_12_23_184434_create_failed_table.php
@@ -0,0 +1,20 @@
+string('value');
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('failed');
+ }
+};
diff --git a/tests/fixtures/migrations/anonymous/2022_08_17_150549_create_before_table.php b/tests/fixtures/migrations/anonymous/2022_08_17_150549_create_before_table.php
new file mode 100644
index 00000000..0010b64b
--- /dev/null
+++ b/tests/fixtures/migrations/anonymous/2022_08_17_150549_create_before_table.php
@@ -0,0 +1,20 @@
+string('value');
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('before');
+ }
+};
diff --git a/tests/fixtures/migrations/2020_12_07_164624_create_test_table.php b/tests/fixtures/migrations/named/2020_12_07_164624_create_test_table.php
similarity index 100%
rename from tests/fixtures/migrations/2020_12_07_164624_create_test_table.php
rename to tests/fixtures/migrations/named/2020_12_07_164624_create_test_table.php
diff --git a/tests/fixtures/migrations/2021_01_02_022431_create_every_time_table.php b/tests/fixtures/migrations/named/2021_01_02_022431_create_every_time_table.php
similarity index 100%
rename from tests/fixtures/migrations/2021_01_02_022431_create_every_time_table.php
rename to tests/fixtures/migrations/named/2021_01_02_022431_create_every_time_table.php
diff --git a/tests/fixtures/migrations/2021_02_15_124419_create_transactions_table.php b/tests/fixtures/migrations/named/2021_02_15_124419_create_transactions_table.php
similarity index 100%
rename from tests/fixtures/migrations/2021_02_15_124419_create_transactions_table.php
rename to tests/fixtures/migrations/named/2021_02_15_124419_create_transactions_table.php
diff --git a/tests/fixtures/migrations/2021_05_24_122027_create_environment_table.php b/tests/fixtures/migrations/named/2021_05_24_122027_create_environment_table.php
similarity index 100%
rename from tests/fixtures/migrations/2021_05_24_122027_create_environment_table.php
rename to tests/fixtures/migrations/named/2021_05_24_122027_create_environment_table.php
diff --git a/tests/fixtures/migrations/2021_12_23_165218_create_success_table.php b/tests/fixtures/migrations/named/2021_12_23_165218_create_success_table.php
similarity index 100%
rename from tests/fixtures/migrations/2021_12_23_165218_create_success_table.php
rename to tests/fixtures/migrations/named/2021_12_23_165218_create_success_table.php
diff --git a/tests/fixtures/migrations/2021_12_23_184434_create_failed_table.php b/tests/fixtures/migrations/named/2021_12_23_184434_create_failed_table.php
similarity index 100%
rename from tests/fixtures/migrations/2021_12_23_184434_create_failed_table.php
rename to tests/fixtures/migrations/named/2021_12_23_184434_create_failed_table.php
diff --git a/tests/fixtures/migrations/2022_08_17_150549_create_before_table.php b/tests/fixtures/migrations/named/2022_08_17_150549_create_before_table.php
similarity index 100%
rename from tests/fixtures/migrations/2022_08_17_150549_create_before_table.php
rename to tests/fixtures/migrations/named/2022_08_17_150549_create_before_table.php