diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ab6c3a763b07..78bb54749b3e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: true matrix: - php: [7.2, 7.3, 7.4] + php: [7.3, 7.4] stability: [prefer-lowest, prefer-stable] name: PHP ${{ matrix.php }} - ${{ matrix.stability }} diff --git a/bin/release.sh b/bin/release.sh index 589bc45e0e18..889e09d202dd 100755 --- a/bin/release.sh +++ b/bin/release.sh @@ -10,7 +10,7 @@ then exit 1 fi -RELEASE_BRANCH="7.x" +RELEASE_BRANCH="master" CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) VERSION=$1 diff --git a/bin/split.sh b/bin/split.sh index 18a8fd695306..70630bac1e31 100755 --- a/bin/split.sh +++ b/bin/split.sh @@ -3,7 +3,7 @@ set -e set -x -CURRENT_BRANCH="7.x" +CURRENT_BRANCH="master" function split() { diff --git a/composer.json b/composer.json index 587e28d3fb89..1292e459bdda 100644 --- a/composer.json +++ b/composer.json @@ -15,12 +15,12 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", "doctrine/inflector": "^1.1", - "dragonmantank/cron-expression": "^2.0", + "dragonmantank/cron-expression": "^3.0", "egulias/email-validator": "^2.1.10", "league/commonmark": "^1.3", "league/flysystem": "^1.0.8", @@ -29,17 +29,17 @@ "opis/closure": "^3.1", "psr/container": "^1.0", "psr/simple-cache": "^1.0", - "ramsey/uuid": "^3.7|^4.0", + "ramsey/uuid": "^4.0", "swiftmailer/swiftmailer": "^6.0", - "symfony/console": "^5.0", - "symfony/error-handler": "^5.0", - "symfony/finder": "^5.0", - "symfony/http-foundation": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/mime": "^5.0", - "symfony/process": "^5.0", - "symfony/routing": "^5.0", - "symfony/var-dumper": "^5.0", + "symfony/console": "^5.1", + "symfony/error-handler": "^5.1", + "symfony/finder": "^5.1", + "symfony/http-foundation": "^5.1", + "symfony/http-kernel": "^5.1", + "symfony/mime": "^5.1", + "symfony/process": "^5.1", + "symfony/routing": "^5.1", + "symfony/var-dumper": "^5.1", "tijsverkoyen/css-to-inline-styles": "^2.2.2", "vlucas/phpdotenv": "^4.0", "voku/portable-ascii": "^1.4.8" @@ -82,12 +82,11 @@ "guzzlehttp/guzzle": "^6.3.1|^7.0", "league/flysystem-cached-adapter": "^1.0", "mockery/mockery": "^1.3.1", - "moontoast/math": "^1.1", - "orchestra/testbench-core": "^5.0", + "orchestra/testbench-core": "^6.0", "pda/pheanstalk": "^4.0", "phpunit/phpunit": "^8.4|^9.0", "predis/predis": "^1.1.1", - "symfony/cache": "^5.0" + "symfony/cache": "^5.1" }, "conflict": { "tightenco/collect": "<5.5.33" @@ -111,7 +110,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { @@ -130,13 +129,12 @@ "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", "mockery/mockery": "Required to use mocking (^1.3.1).", - "moontoast/math": "Required to use ordered UUIDs (^1.1).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", "phpunit/phpunit": "Required to use assertions and run tests (^8.4|^9.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.1).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." }, diff --git a/src/Illuminate/Auth/composer.json b/src/Illuminate/Auth/composer.json index 82316dd1008f..909b5da120dd 100644 --- a/src/Illuminate/Auth/composer.json +++ b/src/Illuminate/Auth/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/http": "^7.0", - "illuminate/queue": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/http": "^8.0", + "illuminate/queue": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -27,13 +27,13 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "illuminate/console": "Required to use the auth:clear-resets command (^7.0).", - "illuminate/queue": "Required to fire login / logout events (^7.0).", - "illuminate/session": "Required to use the session based guard (^7.0)." + "illuminate/console": "Required to use the auth:clear-resets command (^8.0).", + "illuminate/queue": "Required to fire login / logout events (^8.0).", + "illuminate/session": "Required to use the session based guard (^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Broadcasting/composer.json b/src/Illuminate/Broadcasting/composer.json index 6abaeb3c21a5..cb6a2a950edc 100644 --- a/src/Illuminate/Broadcasting/composer.json +++ b/src/Illuminate/Broadcasting/composer.json @@ -14,13 +14,13 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", "psr/log": "^1.0", - "illuminate/bus": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/queue": "^7.0", - "illuminate/support": "^7.0" + "illuminate/bus": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/queue": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -29,7 +29,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Bus/composer.json b/src/Illuminate/Bus/composer.json index 61b5b93df682..bd67f8d5791f 100644 --- a/src/Illuminate/Bus/composer.json +++ b/src/Illuminate/Bus/composer.json @@ -14,10 +14,10 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/pipeline": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/pipeline": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Cache/composer.json b/src/Illuminate/Cache/composer.json index a3565dca0c9a..b578dd8f0a58 100755 --- a/src/Illuminate/Cache/composer.json +++ b/src/Illuminate/Cache/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -25,15 +25,15 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { "ext-memcached": "Required to use the memcache cache driver.", - "illuminate/database": "Required to use the database cache driver (^7.0).", - "illuminate/filesystem": "Required to use the file cache driver (^7.0).", - "illuminate/redis": "Required to use the redis cache driver (^7.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.0)." + "illuminate/database": "Required to use the database cache driver (^8.0).", + "illuminate/filesystem": "Required to use the file cache driver (^8.0).", + "illuminate/redis": "Required to use the redis cache driver (^8.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.1)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Config/composer.json b/src/Illuminate/Config/composer.json index a76331305c87..28c6b25e3d00 100755 --- a/src/Illuminate/Config/composer.json +++ b/src/Illuminate/Config/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Console/composer.json b/src/Illuminate/Console/composer.json index 6cb334fb6b87..e431a064f89d 100755 --- a/src/Illuminate/Console/composer.json +++ b/src/Illuminate/Console/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0", - "symfony/console": "^5.0", - "symfony/process": "^5.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "symfony/console": "^5.1", + "symfony/process": "^5.1" }, "autoload": { "psr-4": { @@ -27,16 +27,16 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "dragonmantank/cron-expression": "Required to use scheduler (^2.0).", + "dragonmantank/cron-expression": "Required to use scheduler (^3.0).", "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.3.1|^7.0).", - "illuminate/bus": "Required to use the scheduled job dispatcher (^7.0)", - "illuminate/container": "Required to use the scheduler (^7.0)", - "illuminate/filesystem": "Required to use the generator command (^7.0)", - "illuminate/queue": "Required to use closures for scheduled jobs (^7.0)" + "illuminate/bus": "Required to use the scheduled job dispatcher (^8.0)", + "illuminate/container": "Required to use the scheduler (^8.0)", + "illuminate/filesystem": "Required to use the generator command (^8.0)", + "illuminate/queue": "Required to use closures for scheduled jobs (^8.0)" }, "config": { "sort-packages": true diff --git a/src/Illuminate/Container/composer.json b/src/Illuminate/Container/composer.json index ddc03cfd0e1c..666d93aa791c 100755 --- a/src/Illuminate/Container/composer.json +++ b/src/Illuminate/Container/composer.json @@ -14,8 +14,8 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", + "php": "^7.3", + "illuminate/contracts": "^8.0", "psr/container": "^1.0" }, "autoload": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Contracts/Database/Eloquent/Castable.php b/src/Illuminate/Contracts/Database/Eloquent/Castable.php index 8656646f14da..911b1cf86af2 100644 --- a/src/Illuminate/Contracts/Database/Eloquent/Castable.php +++ b/src/Illuminate/Contracts/Database/Eloquent/Castable.php @@ -7,7 +7,9 @@ interface Castable /** * Get the name of the caster class to use when casting from / to this cast target. * + * @param array $arguments + * @return string * @return string|\Illuminate\Contracts\Database\Eloquent\CastsAttributes|\Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes */ - public static function castUsing(); + public static function castUsing(array $arguments); } diff --git a/src/Illuminate/Contracts/composer.json b/src/Illuminate/Contracts/composer.json index 4424cf6baaf6..3eda3b0ba1d7 100644 --- a/src/Illuminate/Contracts/composer.json +++ b/src/Illuminate/Contracts/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "psr/container": "^1.0", "psr/simple-cache": "^1.0" }, @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Cookie/composer.json b/src/Illuminate/Cookie/composer.json index 03bb50bc7768..0916f7aea3e0 100755 --- a/src/Illuminate/Cookie/composer.json +++ b/src/Illuminate/Cookie/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0", - "symfony/http-foundation": "^5.0", - "symfony/http-kernel": "^5.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "symfony/http-foundation": "^5.1", + "symfony/http-kernel": "^5.1" }, "autoload": { "psr-4": { @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Database/Console/DumpCommand.php b/src/Illuminate/Database/Console/DumpCommand.php new file mode 100644 index 000000000000..7662823443e6 --- /dev/null +++ b/src/Illuminate/Database/Console/DumpCommand.php @@ -0,0 +1,80 @@ +schemaState( + $connection = $connections->connection($database = $this->input->getOption('database')) + )->dump($path = $this->path($connection)); + + $dispatcher->dispatch(new SchemaDumped($connection, $path)); + + $this->info('Database schema dumped successfully.'); + + if ($this->option('prune')) { + (new Filesystem)->deleteDirectory( + database_path('migrations'), $preserve = false + ); + + $this->info('Migrations pruned successfully.'); + } + } + + /** + * Create a schema state instance for the given connection. + * + * @param \Illuminate\Database\Connection $connection + * @return mixed + */ + protected function schemaState(Connection $connection) + { + return $connection->getSchemaState() + ->handleOutputUsing(function ($type, $buffer) { + $this->output->write($buffer); + }); + } + + /** + * Get the path that the dump should be written to. + * + * @param \Illuminate\Database\Connection $connection + */ + protected function path(Connection $connection) + { + return tap($this->option('path') ?: database_path('schema/'.$connection->getName().'-schema.sql'), function ($path) { + (new Filesystem)->ensureDirectoryExists(dirname($path)); + }); + } +} diff --git a/src/Illuminate/Database/Console/Migrations/MigrateCommand.php b/src/Illuminate/Database/Console/Migrations/MigrateCommand.php index 688b67da8bfd..dcc8ac045886 100755 --- a/src/Illuminate/Database/Console/Migrations/MigrateCommand.php +++ b/src/Illuminate/Database/Console/Migrations/MigrateCommand.php @@ -3,7 +3,11 @@ namespace Illuminate\Database\Console\Migrations; use Illuminate\Console\ConfirmableTrait; +use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Database\Events\SchemaLoaded; use Illuminate\Database\Migrations\Migrator; +use Illuminate\Database\SQLiteConnection; +use Illuminate\Database\SqlServerConnection; class MigrateCommand extends BaseCommand { @@ -18,6 +22,7 @@ class MigrateCommand extends BaseCommand {--force : Force the operation to run when in production} {--path=* : The path(s) to the migrations files to be executed} {--realpath : Indicate any provided migration file paths are pre-resolved absolute paths} + {--schema-path= : The path to a schema dump file} {--pretend : Dump the SQL queries that would be run} {--seed : Indicates if the seed task should be re-run} {--step : Force the migrations to be run so they can be rolled back individually}'; @@ -36,17 +41,26 @@ class MigrateCommand extends BaseCommand */ protected $migrator; + /** + * The event dispatcher instance. + * + * @var \Illuminate\Contracts\Events\Dispatcher + */ + protected $dispatcher; + /** * Create a new migration command instance. * * @param \Illuminate\Database\Migrations\Migrator $migrator + * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher * @return void */ - public function __construct(Migrator $migrator) + public function __construct(Migrator $migrator, Dispatcher $dispatcher) { parent::__construct(); $this->migrator = $migrator; + $this->dispatcher = $dispatcher; } /** @@ -95,5 +109,63 @@ protected function prepareDatabase() '--database' => $this->option('database'), ])); } + + if (! $this->migrator->hasRunAnyMigrations() && ! $this->option('pretend')) { + $this->loadSchemaState(); + } + } + + /** + * Load the schema state to seed the initial database schema structure. + * + * @return void + */ + protected function loadSchemaState() + { + $connection = $this->migrator->resolveConnection($this->option('database')); + + // First, we will make sure that the connection supports schema loading and that + // the schema file exists before we proceed any further. If not, we will just + // continue with the standard migration operation as normal without errors. + if ($connection instanceof SQLiteConnection || + $connection instanceof SqlServerConnection || + ! file_exists($path = $this->schemaPath($connection))) { + return; + } + + $this->line('Loading stored database schema: '.$path); + + $startTime = microtime(true); + + // Since the schema file will create the "migrations" table and reload it to its + // proper state, we need to delete it here so we don't get an error that this + // table already exists when the stored database schema file gets executed. + $this->migrator->deleteRepository(); + + $connection->getSchemaState()->handleOutputUsing(function ($type, $buffer) { + $this->output->write($buffer); + })->load($path); + + $runTime = number_format((microtime(true) - $startTime) * 1000, 2); + + // Finally, we will fire an event that this schema has been loaded so developers + // can perform any post schema load tasks that are necessary in listeners for + // this event, which may seed the database tables with some necessary data. + $this->dispatcher->dispatch( + new SchemaLoaded($connection, $path) + ); + + $this->line('Loaded stored database schema. ('.$runTime.'ms)'); + } + + /** + * Get the path to the stored schema for the given connection. + * + * @param \Illuminate\Database\Connection $connection + * @return string + */ + protected function schemaPath($connection) + { + return $this->option('schema-path') ?: database_path('schema/'.$connection->getName().'-schema.sql'); } } diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index b01069f4f5a6..f4c8709142d3 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -1074,7 +1074,7 @@ protected function resolveCasterClass($key) } if (is_subclass_of($castType, Castable::class)) { - $castType = $castType::castUsing(); + $castType = $castType::castUsing($arguments); } if (is_object($castType)) { diff --git a/src/Illuminate/Database/Events/SchemaDumped.php b/src/Illuminate/Database/Events/SchemaDumped.php new file mode 100644 index 000000000000..1cbbfff96ec6 --- /dev/null +++ b/src/Illuminate/Database/Events/SchemaDumped.php @@ -0,0 +1,41 @@ +connection = $connection; + $this->connectionName = $connection->getName(); + $this->path = $path; + } +} diff --git a/src/Illuminate/Database/Events/SchemaLoaded.php b/src/Illuminate/Database/Events/SchemaLoaded.php new file mode 100644 index 000000000000..061a079a9611 --- /dev/null +++ b/src/Illuminate/Database/Events/SchemaLoaded.php @@ -0,0 +1,41 @@ +connection = $connection; + $this->connectionName = $connection->getName(); + $this->path = $path; + } +} diff --git a/src/Illuminate/Database/MigrationServiceProvider.php b/src/Illuminate/Database/MigrationServiceProvider.php index 3ccc4517eafd..779e19fdc120 100755 --- a/src/Illuminate/Database/MigrationServiceProvider.php +++ b/src/Illuminate/Database/MigrationServiceProvider.php @@ -2,6 +2,7 @@ namespace Illuminate\Database; +use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Support\DeferrableProvider; use Illuminate\Database\Console\Migrations\FreshCommand; use Illuminate\Database\Console\Migrations\InstallCommand; @@ -116,7 +117,7 @@ protected function registerCommands(array $commands) protected function registerMigrateCommand() { $this->app->singleton('command.migrate', function ($app) { - return new MigrateCommand($app['migrator']); + return new MigrateCommand($app['migrator'], $app[Dispatcher::class]); }); } diff --git a/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php b/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php index 1ace1a6ff7e3..ed42756b1b2f 100755 --- a/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php +++ b/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php @@ -169,6 +169,18 @@ public function repositoryExists() return $schema->hasTable($this->table); } + /** + * Delete the migration repository data store. + * + * @return void + */ + public function deleteRepository() + { + $schema = $this->getConnection()->getSchemaBuilder(); + + $schema->drop($this->table); + } + /** * Get a query builder for the migration table. * diff --git a/src/Illuminate/Database/Migrations/MigrationCreator.php b/src/Illuminate/Database/Migrations/MigrationCreator.php index fca9ed81b8d9..a79039a7a20b 100755 --- a/src/Illuminate/Database/Migrations/MigrationCreator.php +++ b/src/Illuminate/Database/Migrations/MigrationCreator.php @@ -63,9 +63,12 @@ public function create($name, $path, $table = null, $create = false) // various place-holders, save the file, and run the post create event. $stub = $this->getStub($table, $create); + $path = $this->getPath($name, $path); + + $this->files->ensureDirectoryExists(dirname($path)); + $this->files->put( - $path = $this->getPath($name, $path), - $this->populateStub($name, $stub, $table) + $path, $this->populateStub($name, $stub, $table) ); // Next, we will fire any hooks that are supposed to fire after a migration is diff --git a/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php b/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php index 410326a9bd68..9d5a134409f0 100755 --- a/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php +++ b/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php @@ -71,6 +71,13 @@ public function createRepository(); */ public function repositoryExists(); + /** + * Delete the migration repository data store. + * + * @return void + */ + public function deleteRepository(); + /** * Set the information source to gather data. * diff --git a/src/Illuminate/Database/Migrations/Migrator.php b/src/Illuminate/Database/Migrations/Migrator.php index d334e0b56310..093e41e78a43 100755 --- a/src/Illuminate/Database/Migrations/Migrator.php +++ b/src/Illuminate/Database/Migrations/Migrator.php @@ -199,14 +199,14 @@ protected function runUp($file, $batch, $pretend) $this->runMigration($migration, 'up'); - $runTime = round(microtime(true) - $startTime, 2); + $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. $this->repository->log($name, $batch); - $this->note("Migrated: {$name} ({$runTime} seconds)"); + $this->note("Migrated: {$name} ({$runTime}ms)"); } /** @@ -362,14 +362,14 @@ protected function runDown($file, $migration, $pretend) $this->runMigration($instance, 'down'); - $runTime = round(microtime(true) - $startTime, 2); + $runTime = number_format((microtime(true) - $startTime) * 1000, 2); // Once we have successfully run the migration "down" we will remove it from // the migration repository so it will be considered to have not been run // by the application then will be able to fire by any later operation. $this->repository->delete($migration); - $this->note("Rolled back: {$name} ({$runTime} seconds)"); + $this->note("Rolled back: {$name} ({$runTime}ms)"); } /** @@ -608,6 +608,26 @@ public function repositoryExists() return $this->repository->repositoryExists(); } + /** + * Determine if any migrations have been run. + * + * @return bool + */ + public function hasRunAnyMigrations() + { + return $this->repositoryExists() && count($this->repository->getRan()) > 0; + } + + /** + * Delete the migration repository data store. + * + * @return void + */ + public function deleteRepository() + { + return $this->repository->deleteRepository(); + } + /** * Get the file system instance. * diff --git a/src/Illuminate/Database/MySqlConnection.php b/src/Illuminate/Database/MySqlConnection.php index 94b5b57d87e0..d2dcc191e6b2 100755 --- a/src/Illuminate/Database/MySqlConnection.php +++ b/src/Illuminate/Database/MySqlConnection.php @@ -7,6 +7,8 @@ use Illuminate\Database\Query\Processors\MySqlProcessor; use Illuminate\Database\Schema\Grammars\MySqlGrammar as SchemaGrammar; use Illuminate\Database\Schema\MySqlBuilder; +use Illuminate\Database\Schema\MySqlSchemaState; +use Illuminate\Filesystem\Filesystem; class MySqlConnection extends Connection { @@ -44,6 +46,18 @@ protected function getDefaultSchemaGrammar() return $this->withTablePrefix(new SchemaGrammar); } + /** + * Get the schema state for the connection. + * + * @param \Illuminate\Filesystem\Filesystem|null $files + * @param callable|null $processFactory + * @return \Illuminate\Database\Schema\MySqlSchemaState + */ + public function getSchemaState(Filesystem $files = null, callable $processFactory = null) + { + return new MySqlSchemaState($this, $files, $processFactory); + } + /** * Get the default post processor instance. * diff --git a/src/Illuminate/Database/PostgresConnection.php b/src/Illuminate/Database/PostgresConnection.php index 5555df1a2e32..a7a833d0b039 100755 --- a/src/Illuminate/Database/PostgresConnection.php +++ b/src/Illuminate/Database/PostgresConnection.php @@ -7,6 +7,7 @@ use Illuminate\Database\Query\Processors\PostgresProcessor; use Illuminate\Database\Schema\Grammars\PostgresGrammar as SchemaGrammar; use Illuminate\Database\Schema\PostgresBuilder; +use Illuminate\Database\Schema\PostgresSchemaState; class PostgresConnection extends Connection { @@ -44,6 +45,18 @@ protected function getDefaultSchemaGrammar() return $this->withTablePrefix(new SchemaGrammar); } + /** + * Get the schema state for the connection. + * + * @param \Illuminate\Filesystem\Filesystem|null $files + * @param callable|null $processFactory + * @return \Illuminate\Database\Schema\PostgresSchemaState + */ + public function getSchemaState(Filesystem $files = null, callable $processFactory = null) + { + return new PostgresSchemaState($this, $files, $processFactory); + } + /** * Get the default post processor instance. * diff --git a/src/Illuminate/Database/SQLiteConnection.php b/src/Illuminate/Database/SQLiteConnection.php index 4990fdd299a1..06d7fbf73ad1 100755 --- a/src/Illuminate/Database/SQLiteConnection.php +++ b/src/Illuminate/Database/SQLiteConnection.php @@ -7,6 +7,8 @@ use Illuminate\Database\Query\Processors\SQLiteProcessor; use Illuminate\Database\Schema\Grammars\SQLiteGrammar as SchemaGrammar; use Illuminate\Database\Schema\SQLiteBuilder; +use Illuminate\Filesystem\Filesystem; +use RuntimeException; class SQLiteConnection extends Connection { @@ -68,6 +70,19 @@ protected function getDefaultSchemaGrammar() return $this->withTablePrefix(new SchemaGrammar); } + /** + * Get the schema state for the connection. + * + * @param \Illuminate\Filesystem\Filesystem|null $files + * @param callable|null $processFactory + * + * @throws \RuntimeException + */ + public function getSchemaState(Filesystem $files = null, callable $processFactory = null) + { + throw new RuntimeException('Schema dumping is not supported when using SQLite.'); + } + /** * Get the default post processor instance. * diff --git a/src/Illuminate/Database/Schema/MySqlSchemaState.php b/src/Illuminate/Database/Schema/MySqlSchemaState.php new file mode 100644 index 000000000000..6fe886cf5ad6 --- /dev/null +++ b/src/Illuminate/Database/Schema/MySqlSchemaState.php @@ -0,0 +1,99 @@ +makeProcess( + $this->baseDumpCommand().' --routines --result-file=$LARAVEL_LOAD_PATH --no-data' + )->mustRun($this->output, array_merge($this->baseVariables($this->connection->getConfig()), [ + 'LARAVEL_LOAD_PATH' => $path, + ])); + + $this->removeAutoIncrementingState($path); + + $this->appendMigrationData($path); + } + + /** + * Remove the auto-incrementing state from the given schema dump. + * + * @param string $path + * @return void + */ + protected function removeAutoIncrementingState(string $path) + { + $this->files->put($path, preg_replace( + '/\s+AUTO_INCREMENT=[0-9]+/iu', + '', + $this->files->get($path) + )); + } + + /** + * Append the migration data to the schema dump. + * + * @param string $path + * @return void + */ + protected function appendMigrationData(string $path) + { + with($process = $this->makeProcess( + $this->baseDumpCommand().' migrations --no-create-info --skip-extended-insert --skip-routines --compact' + ))->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [ + // + ])); + + $this->files->append($path, $process->getOutput()); + } + + /** + * Load the given schema file into the database. + * + * @param string $path + * @return void + */ + public function load($path) + { + $process = $this->makeProcess('mysql --host=$LARAVEL_LOAD_HOST --port=$LARAVEL_LOAD_PORT --user=$LARAVEL_LOAD_USER --password=$LARAVEL_LOAD_PASSWORD --database=$LARAVEL_LOAD_DATABASE < $LARAVEL_LOAD_PATH'); + + $process->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [ + 'LARAVEL_LOAD_PATH' => $path, + ])); + } + + /** + * Get the base dump command arguments for MySQL as a string. + * + * @return string + */ + protected function baseDumpCommand() + { + return 'mysqldump --set-gtid-purged=OFF --skip-add-drop-table --skip-add-locks --skip-comments --skip-set-charset --tz-utc --host=$LARAVEL_LOAD_HOST --port=$LARAVEL_LOAD_PORT --user=$LARAVEL_LOAD_USER --password=$LARAVEL_LOAD_PASSWORD $LARAVEL_LOAD_DATABASE'; + } + + /** + * Get the base variables for a dump / load command. + * + * @param array $config + * @return array + */ + protected function baseVariables(array $config) + { + return [ + 'LARAVEL_LOAD_HOST' => $config['host'], + 'LARAVEL_LOAD_PORT' => $config['port'], + 'LARAVEL_LOAD_USER' => $config['username'], + 'LARAVEL_LOAD_PASSWORD' => $config['password'], + 'LARAVEL_LOAD_DATABASE' => $config['database'], + ]; + } +} diff --git a/src/Illuminate/Database/Schema/PostgresSchemaState.php b/src/Illuminate/Database/Schema/PostgresSchemaState.php new file mode 100644 index 000000000000..d7f1d46ae7d4 --- /dev/null +++ b/src/Illuminate/Database/Schema/PostgresSchemaState.php @@ -0,0 +1,87 @@ +makeProcess( + $this->baseDumpCommand().' --no-owner --file=$LARAVEL_LOAD_PATH --schema-only' + )->mustRun($this->output, array_merge($this->baseVariables($this->connection->getConfig()), [ + 'LARAVEL_LOAD_PATH' => $path, + ])); + + $this->appendMigrationData($path); + } + + /** + * Append the migration data to the schema dump. + * + * @param string $path + * @return void + */ + protected function appendMigrationData(string $path) + { + with($process = $this->makeProcess( + $this->baseDumpCommand().' --table=migrations --data-only --inserts' + ))->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [ + // + ])); + + $migrations = collect(preg_split("/\r\n|\n|\r/", $process->getOutput()))->filter(function ($line) { + return preg_match('/^\s*(--|SELECT\s|SET\s)/iu', $line) === 0 && + strlen($line) > 0; + })->all(); + + $this->files->append($path, implode(PHP_EOL, $migrations).PHP_EOL); + } + + /** + * Load the given schema file into the database. + * + * @param string $path + * @return void + */ + public function load($path) + { + $process = $this->makeProcess('PGPASSWORD=$LARAVEL_LOAD_PASSWORD psql --file=$LARAVEL_LOAD_PATH --host=$LARAVEL_LOAD_HOST --port=$LARAVEL_LOAD_PORT --username=$LARAVEL_LOAD_USER --dbname=$LARAVEL_LOAD_DATABASE'); + + $process->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [ + 'LARAVEL_LOAD_PATH' => $path, + ])); + } + + /** + * Get the base dump command arguments for MySQL as a string. + * + * @return string + */ + protected function baseDumpCommand() + { + return 'PGPASSWORD=$LARAVEL_LOAD_PASSWORD pg_dump --host=$LARAVEL_LOAD_HOST --port=$LARAVEL_LOAD_PORT --username=$LARAVEL_LOAD_USER $LARAVEL_LOAD_DATABASE'; + } + + /** + * Get the base variables for a dump / load command. + * + * @param array $config + * @return array + */ + protected function baseVariables(array $config) + { + return [ + 'LARAVEL_LOAD_HOST' => $config['host'], + 'LARAVEL_LOAD_PORT' => $config['port'], + 'LARAVEL_LOAD_USER' => $config['username'], + 'LARAVEL_LOAD_PASSWORD' => $config['password'], + 'LARAVEL_LOAD_DATABASE' => $config['database'], + ]; + } +} diff --git a/src/Illuminate/Database/Schema/SchemaState.php b/src/Illuminate/Database/Schema/SchemaState.php new file mode 100644 index 000000000000..072ffb8cbe23 --- /dev/null +++ b/src/Illuminate/Database/Schema/SchemaState.php @@ -0,0 +1,101 @@ +connection = $connection; + + $this->files = $files ?: new Filesystem; + + $this->processFactory = $processFactory ?: function (...$arguments) { + return Process::fromShellCommandline(...$arguments); + }; + + $this->handleOutputUsing(function () { + // + }); + } + + /** + * Dump the database's schema into a file. + * + * @param string $path + * @return void + */ + abstract public function dump($path); + + /** + * Load the given schema file into the database. + * + * @param string $path + * @return void + */ + abstract public function load($path); + + /** + * Create a new process instance. + * + * @param array $arguments + * @return \Symfony\Component\Process\Process + */ + public function makeProcess(...$arguments) + { + return call_user_func($this->processFactory, ...$arguments); + } + + /** + * Specify the callback that should be used to handle process output. + * + * @param callable $output + * @return $this + */ + public function handleOutputUsing(callable $output) + { + $this->output = $output; + + return $this; + } +} diff --git a/src/Illuminate/Database/Seeder.php b/src/Illuminate/Database/Seeder.php index 2facfd7de225..e5ab87d959d5 100755 --- a/src/Illuminate/Database/Seeder.php +++ b/src/Illuminate/Database/Seeder.php @@ -47,10 +47,10 @@ public function call($class, $silent = false) $seeder->__invoke(); - $runTime = round(microtime(true) - $startTime, 2); + $runTime = number_format((microtime(true) - $startTime) * 1000, 2); if ($silent === false && isset($this->command)) { - $this->command->getOutput()->writeln("Seeded: {$name} ({$runTime} seconds)"); + $this->command->getOutput()->writeln("Seeded: {$name} ({$runTime}ms)"); } } diff --git a/src/Illuminate/Database/SqlServerConnection.php b/src/Illuminate/Database/SqlServerConnection.php index c5f0c19cff8b..fdfca9114de1 100755 --- a/src/Illuminate/Database/SqlServerConnection.php +++ b/src/Illuminate/Database/SqlServerConnection.php @@ -8,6 +8,8 @@ use Illuminate\Database\Query\Processors\SqlServerProcessor; use Illuminate\Database\Schema\Grammars\SqlServerGrammar as SchemaGrammar; use Illuminate\Database\Schema\SqlServerBuilder; +use Illuminate\Filesystem\Filesystem; +use RuntimeException; use Throwable; class SqlServerConnection extends Connection @@ -86,6 +88,19 @@ protected function getDefaultSchemaGrammar() return $this->withTablePrefix(new SchemaGrammar); } + /** + * Get the schema state for the connection. + * + * @param \Illuminate\Filesystem\Filesystem|null $files + * @param callable|null $processFactory + * + * @throws \RuntimeException + */ + public function getSchemaState(Filesystem $files = null, callable $processFactory = null) + { + throw new RuntimeException('Schema dumping is not supported when using SQL Server.'); + } + /** * Get the default post processor instance. * diff --git a/src/Illuminate/Database/composer.json b/src/Illuminate/Database/composer.json index cad46df9d7a7..423e82e56486 100644 --- a/src/Illuminate/Database/composer.json +++ b/src/Illuminate/Database/composer.json @@ -15,12 +15,12 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0", - "symfony/console": "^5.0" + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "symfony/console": "^5.1" }, "autoload": { "psr-4": { @@ -29,17 +29,17 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", "fzaninotto/faker": "Required to use the eloquent factory builder (^1.9.1).", - "illuminate/console": "Required to use the database commands (^7.0).", - "illuminate/events": "Required to use the observers with Eloquent (^7.0).", - "illuminate/filesystem": "Required to use the migrations (^7.0).", - "illuminate/pagination": "Required to paginate the result set (^7.0).", - "symfony/finder": "Required to use Eloquent model factories (^5.0)." + "illuminate/console": "Required to use the database commands (^8.0).", + "illuminate/events": "Required to use the observers with Eloquent (^8.0).", + "illuminate/filesystem": "Required to use the migrations (^8.0).", + "illuminate/pagination": "Required to paginate the result set (^8.0).", + "symfony/finder": "Required to use Eloquent model factories (^5.1)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Encryption/composer.json b/src/Illuminate/Encryption/composer.json index 7a3598d820a9..daeae948b240 100644 --- a/src/Illuminate/Encryption/composer.json +++ b/src/Illuminate/Encryption/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Events/composer.json b/src/Illuminate/Events/composer.json index 03225a9743b7..65d01dbf1823 100755 --- a/src/Illuminate/Events/composer.json +++ b/src/Illuminate/Events/composer.json @@ -14,10 +14,10 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Filesystem/composer.json b/src/Illuminate/Filesystem/composer.json index 674a2fdaf7df..a87a7123835c 100644 --- a/src/Illuminate/Filesystem/composer.json +++ b/src/Illuminate/Filesystem/composer.json @@ -14,10 +14,10 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0", - "symfony/finder": "^5.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "symfony/finder": "^5.1" }, "autoload": { "psr-4": { @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 9426e36eee3b..20c5c8618a04 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -33,7 +33,7 @@ class Application extends Container implements ApplicationContract, CachesConfig * * @var string */ - const VERSION = '7.5.2'; + const VERSION = '8.x-dev'; /** * The base path for the Laravel installation. diff --git a/src/Illuminate/Foundation/Console/DownCommand.php b/src/Illuminate/Foundation/Console/DownCommand.php index af2f6eb95bee..010f95eff2f9 100644 --- a/src/Illuminate/Foundation/Console/DownCommand.php +++ b/src/Illuminate/Foundation/Console/DownCommand.php @@ -37,7 +37,7 @@ public function handle() if (file_exists(storage_path('framework/down'))) { $this->comment('Application is already down.'); - return true; + return 0; } file_put_contents(storage_path('framework/down'), diff --git a/src/Illuminate/Foundation/Console/UpCommand.php b/src/Illuminate/Foundation/Console/UpCommand.php index 9f659920833e..ba02040511f8 100644 --- a/src/Illuminate/Foundation/Console/UpCommand.php +++ b/src/Illuminate/Foundation/Console/UpCommand.php @@ -32,7 +32,7 @@ public function handle() if (! file_exists(storage_path('framework/down'))) { $this->comment('Application is already up.'); - return true; + return 0; } unlink(storage_path('framework/down')); diff --git a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php index a26d29cf40e2..1340f9614e3b 100755 --- a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php @@ -9,6 +9,7 @@ use Illuminate\Console\Scheduling\ScheduleFinishCommand; use Illuminate\Console\Scheduling\ScheduleRunCommand; use Illuminate\Contracts\Support\DeferrableProvider; +use Illuminate\Database\Console\DumpCommand; use Illuminate\Database\Console\Factories\FactoryMakeCommand; use Illuminate\Database\Console\Seeds\SeedCommand; use Illuminate\Database\Console\Seeds\SeederMakeCommand; @@ -102,6 +103,7 @@ class ArtisanServiceProvider extends ServiceProvider implements DeferrableProvid 'RouteCache' => 'command.route.cache', 'RouteClear' => 'command.route.clear', 'RouteList' => 'command.route.list', + 'SchemaDump' => 'command.schema.dump', 'Seed' => 'command.seed', 'ScheduleFinish' => ScheduleFinishCommand::class, 'ScheduleRun' => ScheduleRunCommand::class, @@ -812,6 +814,18 @@ protected function registerRouteListCommand() }); } + /** + * Register the command. + * + * @return void + */ + protected function registerSchemaDumpCommand() + { + $this->app->singleton('command.schema.dump', function () { + return new DumpCommand; + }); + } + /** * Register the command. * diff --git a/src/Illuminate/Hashing/composer.json b/src/Illuminate/Hashing/composer.json index 4c5269341984..370e4897ae79 100755 --- a/src/Illuminate/Hashing/composer.json +++ b/src/Illuminate/Hashing/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Http/composer.json b/src/Illuminate/Http/composer.json index 6f6184bd0e4e..7e0fe48197e2 100755 --- a/src/Illuminate/Http/composer.json +++ b/src/Illuminate/Http/composer.json @@ -14,13 +14,13 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/session": "^7.0", - "illuminate/support": "^7.0", - "symfony/http-foundation": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/mime": "^5.0" + "illuminate/session": "^8.0", + "illuminate/support": "^8.0", + "symfony/http-foundation": "^5.1", + "symfony/http-kernel": "^5.1", + "symfony/mime": "^5.1" }, "autoload": { "psr-4": { @@ -33,7 +33,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Log/composer.json b/src/Illuminate/Log/composer.json index 6f4548c84120..822cb950275f 100755 --- a/src/Illuminate/Log/composer.json +++ b/src/Illuminate/Log/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0", + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", "monolog/monolog": "^2.0" }, "autoload": { @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Mail/PendingMail.php b/src/Illuminate/Mail/PendingMail.php index 42a9f009a166..d9ac1130c482 100644 --- a/src/Illuminate/Mail/PendingMail.php +++ b/src/Illuminate/Mail/PendingMail.php @@ -122,18 +122,6 @@ public function send(MailableContract $mailable) return $this->mailer->send($this->fill($mailable)); } - /** - * Send a mailable message immediately. - * - * @param \Illuminate\Contracts\Mail\Mailable $mailable - * @return mixed - * @deprecated Use send() instead. - */ - public function sendNow(MailableContract $mailable) - { - return $this->mailer->send($this->fill($mailable)); - } - /** * Push the given mailable onto the queue. * diff --git a/src/Illuminate/Mail/composer.json b/src/Illuminate/Mail/composer.json index 706a8c039bcf..76078e910a9c 100755 --- a/src/Illuminate/Mail/composer.json +++ b/src/Illuminate/Mail/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", "league/commonmark": "^1.3", "psr/log": "^1.0", "swiftmailer/swiftmailer": "^6.0", @@ -31,7 +31,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Notifications/composer.json b/src/Illuminate/Notifications/composer.json index b99e6c816a3e..4530263571bd 100644 --- a/src/Illuminate/Notifications/composer.json +++ b/src/Illuminate/Notifications/composer.json @@ -14,15 +14,15 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/broadcasting": "^7.0", - "illuminate/bus": "^7.0", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/filesystem": "^7.0", - "illuminate/mail": "^7.0", - "illuminate/queue": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/broadcasting": "^8.0", + "illuminate/bus": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/mail": "^8.0", + "illuminate/queue": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -31,11 +31,11 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "illuminate/database": "Required to use the database transport (^7.0)." + "illuminate/database": "Required to use the database transport (^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Pagination/composer.json b/src/Illuminate/Pagination/composer.json index b780c348fb5f..e34b3844a8f5 100755 --- a/src/Illuminate/Pagination/composer.json +++ b/src/Illuminate/Pagination/composer.json @@ -14,10 +14,10 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Pipeline/composer.json b/src/Illuminate/Pipeline/composer.json index d2f323d931af..cda7e7b96ea1 100644 --- a/src/Illuminate/Pipeline/composer.json +++ b/src/Illuminate/Pipeline/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Queue/composer.json b/src/Illuminate/Queue/composer.json index b870f4f50d4a..d7a83375391b 100644 --- a/src/Illuminate/Queue/composer.json +++ b/src/Illuminate/Queue/composer.json @@ -14,18 +14,18 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/console": "^7.0", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/database": "^7.0", - "illuminate/filesystem": "^7.0", - "illuminate/pipeline": "^7.0", - "illuminate/support": "^7.0", + "illuminate/console": "^8.0", + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/database": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/pipeline": "^8.0", + "illuminate/support": "^8.0", "opis/closure": "^3.1", - "ramsey/uuid": "^3.7|^4.0", - "symfony/process": "^5.0" + "ramsey/uuid": "^4.0", + "symfony/process": "^5.1" }, "autoload": { "psr-4": { @@ -34,14 +34,14 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { "ext-pcntl": "Required to use all features of the queue worker.", "ext-posix": "Required to use all features of the queue worker.", "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.0).", - "illuminate/redis": "Required to use the Redis queue driver (^7.0).", + "illuminate/redis": "Required to use the Redis queue driver (^8.0).", "pda/pheanstalk": "Required to use the Beanstalk queue driver (^4.0)." }, "config": { diff --git a/src/Illuminate/Redis/composer.json b/src/Illuminate/Redis/composer.json index 100cc4a65d9f..9c405d81656e 100755 --- a/src/Illuminate/Redis/composer.json +++ b/src/Illuminate/Redis/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -29,7 +29,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Routing/composer.json b/src/Illuminate/Routing/composer.json index 22ba74235148..4a25625312db 100644 --- a/src/Illuminate/Routing/composer.json +++ b/src/Illuminate/Routing/composer.json @@ -14,17 +14,17 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/http": "^7.0", - "illuminate/pipeline": "^7.0", - "illuminate/session": "^7.0", - "illuminate/support": "^7.0", - "symfony/http-foundation": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/routing": "^5.0" + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/http": "^8.0", + "illuminate/pipeline": "^8.0", + "illuminate/session": "^8.0", + "illuminate/support": "^8.0", + "symfony/http-foundation": "^5.1", + "symfony/http-kernel": "^5.1", + "symfony/routing": "^5.1" }, "autoload": { "psr-4": { @@ -33,11 +33,11 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "illuminate/console": "Required to use the make commands (^7.0).", + "illuminate/console": "Required to use the make commands (^8.0).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." }, diff --git a/src/Illuminate/Session/composer.json b/src/Illuminate/Session/composer.json index 56597c288c5c..7d4d1016d2fe 100755 --- a/src/Illuminate/Session/composer.json +++ b/src/Illuminate/Session/composer.json @@ -14,13 +14,13 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/contracts": "^7.0", - "illuminate/filesystem": "^7.0", - "illuminate/support": "^7.0", - "symfony/finder": "^5.0", - "symfony/http-foundation": "^5.0" + "illuminate/contracts": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/support": "^8.0", + "symfony/finder": "^5.1", + "symfony/http-foundation": "^5.1" }, "autoload": { "psr-4": { @@ -29,11 +29,11 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "illuminate/console": "Required to use the session:table command (^7.0)." + "illuminate/console": "Required to use the session:table command (^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Support/Arr.php b/src/Illuminate/Support/Arr.php index e14ae83acb5c..99c670b447fc 100755 --- a/src/Illuminate/Support/Arr.php +++ b/src/Illuminate/Support/Arr.php @@ -144,6 +144,10 @@ public static function except($array, $keys) */ public static function exists($array, $key) { + if ($array instanceof Enumerable) { + return $array->has($key); + } + if ($array instanceof ArrayAccess) { return $array->offsetExists($key); } @@ -256,9 +260,13 @@ public static function forget(&$array, $keys) // clean up before each pass $array = &$original; - - while (count($parts) > 1) { - $part = array_shift($parts); + + foreach ($parts as $i => $part) { + if (count($parts) === 1) { + break; + } + + unset($parts[$i]); if (isset($array[$part]) && is_array($array[$part])) { $array = &$array[$part]; diff --git a/src/Illuminate/Support/Collection.php b/src/Illuminate/Support/Collection.php index 32373cdc86f0..fd0a7f96c8e8 100644 --- a/src/Illuminate/Support/Collection.php +++ b/src/Illuminate/Support/Collection.php @@ -412,7 +412,7 @@ public function forget($keys) */ public function get($key, $default = null) { - if ($this->offsetExists($key)) { + if (array_key_exists($key, $this->items)) { return $this->items[$key]; } @@ -501,7 +501,7 @@ public function has($key) $keys = is_array($key) ? $key : func_get_args(); foreach ($keys as $value) { - if (! $this->offsetExists($value)) { + if (! array_key_exists($value, $this->items)) { return false; } } @@ -1293,7 +1293,7 @@ public function toBase() */ public function offsetExists($key) { - return array_key_exists($key, $this->items); + return isset($this->items[$key]); } /** diff --git a/src/Illuminate/Support/Manager.php b/src/Illuminate/Support/Manager.php index 8b20f6a25e58..8361be239f7f 100755 --- a/src/Illuminate/Support/Manager.php +++ b/src/Illuminate/Support/Manager.php @@ -15,15 +15,6 @@ abstract class Manager */ protected $container; - /** - * The container instance. - * - * @var \Illuminate\Contracts\Container\Container - * - * @deprecated Use the $container property instead. - */ - protected $app; - /** * The configuration repository instance. * diff --git a/src/Illuminate/Support/Testing/Fakes/PendingMailFake.php b/src/Illuminate/Support/Testing/Fakes/PendingMailFake.php index 64452e634517..31100a431e74 100644 --- a/src/Illuminate/Support/Testing/Fakes/PendingMailFake.php +++ b/src/Illuminate/Support/Testing/Fakes/PendingMailFake.php @@ -29,18 +29,6 @@ public function send(Mailable $mailable) return $this->mailer->send($this->fill($mailable)); } - /** - * Send a mailable message immediately. - * - * @param \Illuminate\Contracts\Mail\Mailable $mailable; - * @return mixed - * @deprecated Use send() instead. - */ - public function sendNow(Mailable $mailable) - { - return $this->send($mailable); - } - /** * Push the given mailable onto the queue. * diff --git a/src/Illuminate/Support/composer.json b/src/Illuminate/Support/composer.json index 33322adc9a30..2adac0992c71 100644 --- a/src/Illuminate/Support/composer.json +++ b/src/Illuminate/Support/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", "ext-mbstring": "*", "doctrine/inflector": "^1.1", - "illuminate/contracts": "^7.0", + "illuminate/contracts": "^8.0", "nesbot/carbon": "^2.17", "voku/portable-ascii": "^1.4.8" }, @@ -35,15 +35,14 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "illuminate/filesystem": "Required to use the composer class (^7.0).", - "moontoast/math": "Required to use ordered UUIDs (^1.1).", - "ramsey/uuid": "Required to use Str::uuid() (^3.7|^4.0).", - "symfony/process": "Required to use the composer class (^5.0).", - "symfony/var-dumper": "Required to use the dd function (^5.0).", + "illuminate/filesystem": "Required to use the composer class (^8.0).", + "ramsey/uuid": "Required to use Str::uuid() (^4.0).", + "symfony/process": "Required to use the composer class (^5.1).", + "symfony/var-dumper": "Required to use the dd function (^5.1).", "vlucas/phpdotenv": "Required to use the Env class and env helper (^4.0)." }, "config": { diff --git a/src/Illuminate/Testing/composer.json b/src/Illuminate/Testing/composer.json index 2e3131d9526e..e77a8a4c545c 100644 --- a/src/Illuminate/Testing/composer.json +++ b/src/Illuminate/Testing/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^7.2.5", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0" + "php": "^7.3", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -25,13 +25,13 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "illuminate/console": "Required to assert console commands (^7.0).", - "illuminate/database": "Required to assert databases (^7.0).", - "illuminate/http": "Required to assert responses (^7.0).", + "illuminate/console": "Required to assert console commands (^8.0).", + "illuminate/database": "Required to assert databases (^8.0).", + "illuminate/http": "Required to assert responses (^8.0).", "mockery/mockery": "Required to use mocking (^1.3.1).", "phpunit/phpunit": "Required to use assertions and run tests (^8.4|^9.0)." }, diff --git a/src/Illuminate/Translation/composer.json b/src/Illuminate/Translation/composer.json index 454892e49393..cf7172422386 100755 --- a/src/Illuminate/Translation/composer.json +++ b/src/Illuminate/Translation/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/contracts": "^7.0", - "illuminate/filesystem": "^7.0", - "illuminate/support": "^7.0" + "illuminate/contracts": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/src/Illuminate/Validation/composer.json b/src/Illuminate/Validation/composer.json index 344311ce437b..08250cffffc2 100755 --- a/src/Illuminate/Validation/composer.json +++ b/src/Illuminate/Validation/composer.json @@ -14,15 +14,15 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", "egulias/email-validator": "^2.1.10", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/support": "^7.0", - "illuminate/translation": "^7.0", - "symfony/http-foundation": "^5.0", - "symfony/mime": "^5.0" + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/support": "^8.0", + "illuminate/translation": "^8.0", + "symfony/http-foundation": "^5.1", + "symfony/mime": "^5.1" }, "autoload": { "psr-4": { @@ -31,11 +31,11 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "suggest": { - "illuminate/database": "Required to use the database presence verifier (^7.0)." + "illuminate/database": "Required to use the database presence verifier (^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/View/composer.json b/src/Illuminate/View/composer.json index 88141f76b56b..790c5533b35a 100644 --- a/src/Illuminate/View/composer.json +++ b/src/Illuminate/View/composer.json @@ -14,13 +14,13 @@ } ], "require": { - "php": "^7.2.5", + "php": "^7.3", "ext-json": "*", - "illuminate/container": "^7.0", - "illuminate/contracts": "^7.0", - "illuminate/events": "^7.0", - "illuminate/filesystem": "^7.0", - "illuminate/support": "^7.0" + "illuminate/container": "^8.0", + "illuminate/contracts": "^8.0", + "illuminate/events": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/support": "^8.0" }, "autoload": { "psr-4": { @@ -29,7 +29,7 @@ }, "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "config": { diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index db79acb1dcdd..612cbd415ce5 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -532,10 +532,6 @@ public function testFromDateTime() public function testFromDateTimeMilliseconds() { - if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) { - $this->markTestSkipped('Due to https://bugs.php.net/bug.php?id=75577, proper "v" format support can only works since PHP 7.3.'); - } - $model = $this->getMockBuilder('Illuminate\Tests\Database\EloquentDateModelStub')->setMethods(['getDateFormat'])->getMock(); $model->expects($this->any())->method('getDateFormat')->willReturn('Y-m-d H:s.vi'); $model->setRawAttributes([ diff --git a/tests/Database/DatabaseMigrationCreatorTest.php b/tests/Database/DatabaseMigrationCreatorTest.php index 47acf9ffbeb0..ff5b0c128882 100755 --- a/tests/Database/DatabaseMigrationCreatorTest.php +++ b/tests/Database/DatabaseMigrationCreatorTest.php @@ -22,6 +22,7 @@ public function testBasicCreateMethodStoresMigrationFile() $creator->expects($this->any())->method('getDatePrefix')->willReturn('foo'); $creator->getFilesystem()->shouldReceive('exists')->once()->with('stubs/migration.stub')->andReturn(false); $creator->getFilesystem()->shouldReceive('get')->once()->with($creator->stubPath().'/migration.stub')->andReturn('DummyClass'); + $creator->getFilesystem()->shouldReceive('ensureDirectoryExists')->once()->with('foo'); $creator->getFilesystem()->shouldReceive('put')->once()->with('foo/foo_create_bar.php', 'CreateBar'); $creator->getFilesystem()->shouldReceive('glob')->once()->with('foo/*.php')->andReturn(['foo/foo_create_bar.php']); $creator->getFilesystem()->shouldReceive('requireOnce')->once()->with('foo/foo_create_bar.php'); @@ -42,6 +43,7 @@ public function testBasicCreateMethodCallsPostCreateHooks() $creator->expects($this->any())->method('getDatePrefix')->willReturn('foo'); $creator->getFilesystem()->shouldReceive('exists')->once()->with('stubs/migration.update.stub')->andReturn(false); $creator->getFilesystem()->shouldReceive('get')->once()->with($creator->stubPath().'/migration.update.stub')->andReturn('DummyClass DummyTable'); + $creator->getFilesystem()->shouldReceive('ensureDirectoryExists')->once()->with('foo'); $creator->getFilesystem()->shouldReceive('put')->once()->with('foo/foo_create_bar.php', 'CreateBar baz'); $creator->getFilesystem()->shouldReceive('glob')->once()->with('foo/*.php')->andReturn(['foo/foo_create_bar.php']); $creator->getFilesystem()->shouldReceive('requireOnce')->once()->with('foo/foo_create_bar.php'); @@ -59,6 +61,7 @@ public function testTableUpdateMigrationStoresMigrationFile() $creator->expects($this->any())->method('getDatePrefix')->willReturn('foo'); $creator->getFilesystem()->shouldReceive('exists')->once()->with('stubs/migration.update.stub')->andReturn(false); $creator->getFilesystem()->shouldReceive('get')->once()->with($creator->stubPath().'/migration.update.stub')->andReturn('DummyClass DummyTable'); + $creator->getFilesystem()->shouldReceive('ensureDirectoryExists')->once()->with('foo'); $creator->getFilesystem()->shouldReceive('put')->once()->with('foo/foo_create_bar.php', 'CreateBar baz'); $creator->getFilesystem()->shouldReceive('glob')->once()->with('foo/*.php')->andReturn(['foo/foo_create_bar.php']); $creator->getFilesystem()->shouldReceive('requireOnce')->once()->with('foo/foo_create_bar.php'); @@ -72,6 +75,7 @@ public function testTableCreationMigrationStoresMigrationFile() $creator->expects($this->any())->method('getDatePrefix')->willReturn('foo'); $creator->getFilesystem()->shouldReceive('exists')->once()->with('stubs/migration.create.stub')->andReturn(false); $creator->getFilesystem()->shouldReceive('get')->once()->with($creator->stubPath().'/migration.create.stub')->andReturn('DummyClass DummyTable'); + $creator->getFilesystem()->shouldReceive('ensureDirectoryExists')->once()->with('foo'); $creator->getFilesystem()->shouldReceive('put')->once()->with('foo/foo_create_bar.php', 'CreateBar baz'); $creator->getFilesystem()->shouldReceive('glob')->once()->with('foo/*.php')->andReturn(['foo/foo_create_bar.php']); $creator->getFilesystem()->shouldReceive('requireOnce')->once()->with('foo/foo_create_bar.php'); diff --git a/tests/Database/DatabaseMigrationMigrateCommandTest.php b/tests/Database/DatabaseMigrationMigrateCommandTest.php index 7fd0c6020cb4..53436cccb2c3 100755 --- a/tests/Database/DatabaseMigrationMigrateCommandTest.php +++ b/tests/Database/DatabaseMigrationMigrateCommandTest.php @@ -2,7 +2,9 @@ namespace Illuminate\Tests\Database; +use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Database\Console\Migrations\MigrateCommand; +use Illuminate\Database\Events\SchemaLoaded; use Illuminate\Database\Migrations\Migrator; use Illuminate\Foundation\Application; use Mockery as m; @@ -19,11 +21,12 @@ protected function tearDown(): void public function testBasicMigrationsCallMigratorWithProperArguments() { - $command = new MigrateCommand($migrator = m::mock(Migrator::class)); + $command = new MigrateCommand($migrator = m::mock(Migrator::class), $dispatcher = m::mock(Dispatcher::class)); $app = new ApplicationDatabaseMigrationStub(['path.database' => __DIR__]); $app->useDatabasePath(__DIR__); $command->setLaravel($app); $migrator->shouldReceive('paths')->once()->andReturn([]); + $migrator->shouldReceive('hasRunAnyMigrations')->andReturn(true); $migrator->shouldReceive('usingConnection')->once()->andReturnUsing(function ($name, $callback) { return $callback(); }); @@ -35,14 +38,41 @@ public function testBasicMigrationsCallMigratorWithProperArguments() $this->runCommand($command); } + public function testMigrationsCanBeRunWithStoredSchema() + { + $command = new MigrateCommand($migrator = m::mock(Migrator::class), $dispatcher = m::mock(Dispatcher::class)); + $app = new ApplicationDatabaseMigrationStub(['path.database' => __DIR__]); + $app->useDatabasePath(__DIR__); + $command->setLaravel($app); + $migrator->shouldReceive('paths')->once()->andReturn([]); + $migrator->shouldReceive('hasRunAnyMigrations')->andReturn(false); + $migrator->shouldReceive('resolveConnection')->andReturn($connection = m::mock(stdClass::class)); + $connection->shouldReceive('getName')->andReturn('mysql'); + $migrator->shouldReceive('usingConnection')->once()->andReturnUsing(function ($name, $callback) { + return $callback(); + }); + $migrator->shouldReceive('deleteRepository')->once(); + $connection->shouldReceive('getSchemaState')->andReturn($schemaState = m::mock(stdClass::class)); + $schemaState->shouldReceive('handleOutputUsing')->andReturnSelf(); + $schemaState->shouldReceive('load')->once()->with(__DIR__.'/stubs/schema.sql'); + $dispatcher->shouldReceive('dispatch')->once()->with(m::type(SchemaLoaded::class)); + $migrator->shouldReceive('setOutput')->once()->andReturn($migrator); + $migrator->shouldReceive('run')->once()->with([__DIR__.DIRECTORY_SEPARATOR.'migrations'], ['pretend' => false, 'step' => false]); + $migrator->shouldReceive('getNotes')->andReturn([]); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + + $this->runCommand($command, ['--schema-path' => __DIR__.'/stubs/schema.sql']); + } + public function testMigrationRepositoryCreatedWhenNecessary() { - $params = [$migrator = m::mock(Migrator::class)]; + $params = [$migrator = m::mock(Migrator::class), $dispatcher = m::mock(Dispatcher::class)]; $command = $this->getMockBuilder(MigrateCommand::class)->setMethods(['call'])->setConstructorArgs($params)->getMock(); $app = new ApplicationDatabaseMigrationStub(['path.database' => __DIR__]); $app->useDatabasePath(__DIR__); $command->setLaravel($app); $migrator->shouldReceive('paths')->once()->andReturn([]); + $migrator->shouldReceive('hasRunAnyMigrations')->andReturn(true); $migrator->shouldReceive('usingConnection')->once()->andReturnUsing(function ($name, $callback) { return $callback(); }); @@ -56,11 +86,12 @@ public function testMigrationRepositoryCreatedWhenNecessary() public function testTheCommandMayBePretended() { - $command = new MigrateCommand($migrator = m::mock(Migrator::class)); + $command = new MigrateCommand($migrator = m::mock(Migrator::class), $dispatcher = m::mock(Dispatcher::class)); $app = new ApplicationDatabaseMigrationStub(['path.database' => __DIR__]); $app->useDatabasePath(__DIR__); $command->setLaravel($app); $migrator->shouldReceive('paths')->once()->andReturn([]); + $migrator->shouldReceive('hasRunAnyMigrations')->andReturn(true); $migrator->shouldReceive('usingConnection')->once()->andReturnUsing(function ($name, $callback) { return $callback(); }); @@ -73,11 +104,12 @@ public function testTheCommandMayBePretended() public function testTheDatabaseMayBeSet() { - $command = new MigrateCommand($migrator = m::mock(Migrator::class)); + $command = new MigrateCommand($migrator = m::mock(Migrator::class), $dispatcher = m::mock(Dispatcher::class)); $app = new ApplicationDatabaseMigrationStub(['path.database' => __DIR__]); $app->useDatabasePath(__DIR__); $command->setLaravel($app); $migrator->shouldReceive('paths')->once()->andReturn([]); + $migrator->shouldReceive('hasRunAnyMigrations')->andReturn(true); $migrator->shouldReceive('usingConnection')->once()->andReturnUsing(function ($name, $callback) { return $callback(); }); @@ -90,11 +122,12 @@ public function testTheDatabaseMayBeSet() public function testStepMayBeSet() { - $command = new MigrateCommand($migrator = m::mock(Migrator::class)); + $command = new MigrateCommand($migrator = m::mock(Migrator::class), $dispatcher = m::mock(Dispatcher::class)); $app = new ApplicationDatabaseMigrationStub(['path.database' => __DIR__]); $app->useDatabasePath(__DIR__); $command->setLaravel($app); $migrator->shouldReceive('paths')->once()->andReturn([]); + $migrator->shouldReceive('hasRunAnyMigrations')->andReturn(true); $migrator->shouldReceive('usingConnection')->once()->andReturnUsing(function ($name, $callback) { return $callback(); }); diff --git a/tests/Database/stubs/schema.sql b/tests/Database/stubs/schema.sql new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/Integration/Database/DatabaseEloquentModelCustomCastingTest.php b/tests/Integration/Database/DatabaseEloquentModelCustomCastingTest.php index 5df983887fd8..79bdea4d22aa 100644 --- a/tests/Integration/Database/DatabaseEloquentModelCustomCastingTest.php +++ b/tests/Integration/Database/DatabaseEloquentModelCustomCastingTest.php @@ -250,15 +250,36 @@ public function __construct(string $name) $this->name = $name; } - public static function castUsing() + public static function castUsing(array $arguments) { - return ValueObjectCaster::class; + return new class(...$arguments) implements CastsAttributes { + private $argument; + + public function __construct($argument = null) + { + $this->argument = $argument; + } + + public function get($model, $key, $value, $attributes) + { + if ($this->argument) { + return $this->argument; + } + + return unserialize($value); + } + + public function set($model, $key, $value, $attributes) + { + return serialize($value); + } + }; } } class ValueObjectWithCasterInstance extends ValueObject { - public static function castUsing() + public static function castUsing(array $arguments) { return new ValueObjectCaster(); } diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index 5aaa0a921ed5..bab922c9eef7 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -327,10 +327,31 @@ public function testOffsetAccess() public function testArrayAccessOffsetExists() { - $c = new Collection(['foo', 'bar']); + $c = new Collection(['foo', 'bar', null]); $this->assertTrue($c->offsetExists(0)); $this->assertTrue($c->offsetExists(1)); - $this->assertFalse($c->offsetExists(1000)); + $this->assertFalse($c->offsetExists(2)); + } + + public function testBehavesLikeAnArrayWithArrayAccess() + { + // indexed array + $input = ['foo', null]; + $c = new Collection($input); + $this->assertEquals(isset($input[0]), isset($c[0])); // existing value + $this->assertEquals(isset($input[1]), isset($c[1])); // existing but null value + $this->assertEquals(isset($input[1000]), isset($c[1000])); // non-existing value + $this->assertEquals($input[0], $c[0]); + $this->assertEquals($input[1], $c[1]); + + // associative array + $input = ['k1' => 'foo', 'k2' => null]; + $c = new Collection($input); + $this->assertEquals(isset($input['k1']), isset($c['k1'])); // existing value + $this->assertEquals(isset($input['k2']), isset($c['k2'])); // existing but null value + $this->assertEquals(isset($input['k3']), isset($c['k3'])); // non-existing value + $this->assertEquals($input['k1'], $c['k1']); + $this->assertEquals($input['k2'], $c['k2']); } public function testArrayAccessOffsetGet()