@@ -228,7 +228,13 @@ public function markMigrated(int $version, string $path): bool
228228 /** @var class-string<\Phinx\Migration\MigrationInterface> $className */
229229 $ className = $ this ->getMigrationClassName ($ migrationFile );
230230 require_once $ migrationFile ;
231- $ Migration = new $ className ('default ' , $ version );
231+
232+ // BaseMigration uses different constructor signature than Phinx AbstractMigration
233+ if (is_subclass_of ($ className , BaseMigration::class)) {
234+ $ Migration = new $ className ($ version );
235+ } else {
236+ $ Migration = new $ className ('default ' , $ version );
237+ }
232238
233239 $ time = date ('Y-m-d H:i:s ' , time ());
234240
@@ -360,6 +366,118 @@ public function setInput(InputInterface $input)
360366 return $ this ;
361367 }
362368
369+ /**
370+ * Gets an array of the database migrations, indexed by migration name (aka creation time) and sorted in ascending
371+ * order
372+ *
373+ * Overrides parent to handle both Phinx AbstractMigration and CakePHP BaseMigration constructors
374+ *
375+ * @param string $environment Environment
376+ * @throws \InvalidArgumentException
377+ * @return \Phinx\Migration\MigrationInterface[]
378+ */
379+ public function getMigrations (string $ environment ): array
380+ {
381+ if ($ this ->migrations === null ) {
382+ $ phpFiles = $ this ->getMigrationFiles ();
383+
384+ if ($ this ->getOutput ()->getVerbosity () >= OutputInterface::VERBOSITY_DEBUG ) {
385+ $ this ->getOutput ()->writeln ('Migration file ' );
386+ $ this ->getOutput ()->writeln (
387+ array_map (
388+ function ($ phpFile ) {
389+ return " <info> {$ phpFile }</info> " ;
390+ },
391+ $ phpFiles ,
392+ ),
393+ );
394+ }
395+
396+ // filter the files to only get the ones that match our naming scheme
397+ $ fileNames = [];
398+ /** @var \Phinx\Migration\MigrationInterface[] $versions */
399+ $ versions = [];
400+
401+ foreach ($ phpFiles as $ filePath ) {
402+ if (\Phinx \Util \Util::isValidMigrationFileName (basename ($ filePath ))) {
403+ if ($ this ->getOutput ()->getVerbosity () >= OutputInterface::VERBOSITY_DEBUG ) {
404+ $ this ->getOutput ()->writeln ("Valid migration file <info> {$ filePath }</info>. " );
405+ }
406+
407+ $ version = \Phinx \Util \Util::getVersionFromFileName (basename ($ filePath ));
408+
409+ if (isset ($ versions [$ version ])) {
410+ throw new InvalidArgumentException (sprintf ('Duplicate migration - "%s" has the same version as "%s" ' , $ filePath , $ versions [$ version ]->getVersion ()));
411+ }
412+
413+ $ config = $ this ->getConfig ();
414+ $ namespace = $ config instanceof \Phinx \Config \NamespaceAwareInterface ? $ config ->getMigrationNamespaceByPath (dirname ($ filePath )) : null ;
415+
416+ // convert the filename to a class name
417+ $ class = ($ namespace === null ? '' : $ namespace . '\\' ) . \Phinx \Util \Util::mapFileNameToClassName (basename ($ filePath ));
418+
419+ if (isset ($ fileNames [$ class ])) {
420+ throw new InvalidArgumentException (sprintf (
421+ 'Migration "%s" has the same name as "%s" ' ,
422+ basename ($ filePath ),
423+ $ fileNames [$ class ],
424+ ));
425+ }
426+
427+ $ fileNames [$ class ] = basename ($ filePath );
428+
429+ if ($ this ->getOutput ()->getVerbosity () >= OutputInterface::VERBOSITY_DEBUG ) {
430+ $ this ->getOutput ()->writeln ("Loading class <info> $ class</info> from <info> $ filePath</info>. " );
431+ }
432+
433+ // load the migration file
434+ $ orig_display_errors_setting = ini_get ('display_errors ' );
435+ ini_set ('display_errors ' , 'On ' );
436+ /** @noinspection PhpIncludeInspection */
437+ require_once $ filePath ;
438+ ini_set ('display_errors ' , $ orig_display_errors_setting );
439+ if (!class_exists ($ class )) {
440+ throw new InvalidArgumentException (sprintf (
441+ 'Could not find class "%s" in file "%s" ' ,
442+ $ class ,
443+ $ filePath ,
444+ ));
445+ }
446+
447+ if ($ this ->getOutput ()->getVerbosity () >= OutputInterface::VERBOSITY_DEBUG ) {
448+ $ this ->getOutput ()->writeln ("Running <info> $ class</info>. " );
449+ }
450+
451+ // instantiate it - BaseMigration uses different constructor than Phinx AbstractMigration
452+ if (is_subclass_of ($ class , BaseMigration::class)) {
453+ $ migration = new $ class ($ version );
454+ } else {
455+ $ migration = new $ class ($ environment , $ version , $ this ->getInput (), $ this ->getOutput ());
456+ }
457+
458+ if (!($ migration instanceof \Phinx \Migration \MigrationInterface)) {
459+ throw new InvalidArgumentException (sprintf (
460+ 'The class "%s" in file "%s" must implement \Phinx\Migration\MigrationInterface ' ,
461+ $ class ,
462+ $ filePath ,
463+ ));
464+ }
465+
466+ $ versions [$ version ] = $ migration ;
467+ } else {
468+ if ($ this ->getOutput ()->getVerbosity () >= OutputInterface::VERBOSITY_DEBUG ) {
469+ $ this ->getOutput ()->writeln ("Invalid migration file <error> {$ filePath }</error>. " );
470+ }
471+ }
472+ }
473+
474+ ksort ($ versions );
475+ $ this ->setMigrations ($ versions );
476+ }
477+
478+ return $ this ->migrations ;
479+ }
480+
363481 /**
364482 * Gets an array of database seeders.
365483 *
0 commit comments