diff --git a/src/AntiMattr/MongoDB/Migrations/Configuration/Configuration.php b/src/AntiMattr/MongoDB/Migrations/Configuration/Configuration.php index 0f4533c..581cedb 100644 --- a/src/AntiMattr/MongoDB/Migrations/Configuration/Configuration.php +++ b/src/AntiMattr/MongoDB/Migrations/Configuration/Configuration.php @@ -1,4 +1,5 @@ */ -class Configuration +class Configuration implements ConfigurationInterface { + const MIGRATION_DIRECTION_UP = 'up'; + const MIGRATION_DIRECTION_DOWN = 'down'; + + const DEFAULT_PREFIX = 'app'; + /** * @var \Doctrine\MongoDB\Collection */ @@ -39,11 +47,6 @@ class Configuration */ private $database; - /** - * @var \Doctrine\MongoDB\Connection - */ - private $migrationsDatabase; - /** * The migration database name to track versions in. * @@ -93,6 +96,15 @@ class Configuration */ private $name; + + /** + * With this value will be marked all migrations in database. This mark will allow to group migrations by their + * origin. + * + * @var string + */ + protected $prefix; + /** * @var \AntiMattr\MongoDB\Migrations\Version[] */ @@ -128,15 +140,16 @@ public function __construct(Connection $connection, OutputWriter $outputWriter = * * @return string The formatted version */ - public static function formatVersion($version) + public static function formatVersion($version): string { - return sprintf('%s-%s-%s %s:%s:%s', - substr($version, 0, 4), - substr($version, 4, 2), - substr($version, 6, 2), - substr($version, 8, 2), - substr($version, 10, 2), - substr($version, 12, 2) + return \sprintf( + '%s-%s-%s %s:%s:%s', + \substr($version, 0, 4), + \substr($version, 4, 2), + \substr($version, 6, 2), + \substr($version, 8, 2), + \substr($version, 10, 2), + \substr($version, 12, 2) ); } @@ -145,7 +158,7 @@ public static function formatVersion($version) * * @return array */ - public function getAvailableVersions() + public function getAvailableVersions(): array { $availableVersions = []; foreach ($this->migrations as $migration) { @@ -156,9 +169,9 @@ public function getAvailableVersions() } /** - * @return \Doctrine\MongoDB\Collection + * @return \Doctrine\MongoDB\Collection|null */ - public function getCollection() + public function getCollection(): ?Collection { if (isset($this->collection)) { return $this->collection; @@ -170,15 +183,15 @@ public function getCollection() } /** - * @return \Doctrine\MongoDB\Connection + * @return \Doctrine\MongoDB\Connection|null */ - public function getConnection() + public function getConnection(): ?Connection { return $this->connection; } /** - * @return \Doctrine\MongoDB\Database + * @return \Doctrine\MongoDB\Database|null */ public function getDatabase(): ?Database { @@ -196,15 +209,17 @@ public function getDatabase(): ?Database * * @return Version[] $migrations */ - public function getMigrations() + public function getMigrations(): array { return $this->migrations; } /** - * @param string $databaseName + * @param string|null $databaseName + * + * @return ConfigurationInterface */ - public function setMigrationsDatabaseName($databaseName) + public function setMigrationsDatabaseName(?string $databaseName): ConfigurationInterface { $this->migrationsDatabaseName = $databaseName; @@ -212,17 +227,19 @@ public function setMigrationsDatabaseName($databaseName) } /** - * @return string + * @return string|null */ - public function getMigrationsDatabaseName() + public function getMigrationsDatabaseName(): ?string { return $this->migrationsDatabaseName; } /** - * @param string $collectionName + * @param string|null $collectionName + * + * @return ConfigurationInterface */ - public function setMigrationsCollectionName($collectionName) + public function setMigrationsCollectionName(?string $collectionName): ConfigurationInterface { $this->migrationsCollectionName = $collectionName; @@ -230,17 +247,19 @@ public function setMigrationsCollectionName($collectionName) } /** - * @return string + * @return string|null */ - public function getMigrationsCollectionName() + public function getMigrationsCollectionName(): ?string { return $this->migrationsCollectionName; } /** * @param string $migrationsDirectory + * + * @return ConfigurationInterface */ - public function setMigrationsDirectory($migrationsDirectory) + public function setMigrationsDirectory(string $migrationsDirectory): ConfigurationInterface { $this->migrationsDirectory = $migrationsDirectory; @@ -248,9 +267,9 @@ public function setMigrationsDirectory($migrationsDirectory) } /** - * @return string + * @return string|null */ - public function getMigrationsDirectory() + public function getMigrationsDirectory(): ?string { return $this->migrationsDirectory; } @@ -258,9 +277,11 @@ public function getMigrationsDirectory() /** * Set the migrations namespace. * - * @param string $migrationsNamespace The migrations namespace + * @param string|null $migrationsNamespace The migrations namespace + * + * @return ConfigurationInterface */ - public function setMigrationsNamespace($migrationsNamespace) + public function setMigrationsNamespace(?string $migrationsNamespace): ConfigurationInterface { $this->migrationsNamespace = $migrationsNamespace; @@ -268,17 +289,19 @@ public function setMigrationsNamespace($migrationsNamespace) } /** - * @return string $migrationsNamespace + * @return string|null */ - public function getMigrationsNamespace() + public function getMigrationsNamespace(): ?string { return $this->migrationsNamespace; } /** * @param string $scriptsDirectory + * + * @return ConfigurationInterface */ - public function setMigrationsScriptDirectory($scriptsDirectory) + public function setMigrationsScriptDirectory(string $scriptsDirectory): ConfigurationInterface { $this->migrationsScriptDirectory = $scriptsDirectory; @@ -286,17 +309,19 @@ public function setMigrationsScriptDirectory($scriptsDirectory) } /** - * @return string + * @return string|null */ - public function getMigrationsScriptDirectory() + public function getMigrationsScriptDirectory(): ?string { return $this->migrationsScriptDirectory; } /** - * @param string $file + * @param string|null $file + * + * @return self */ - public function setFile($file) + public function setFile(?string $file): ConfigurationInterface { $this->file = $file; @@ -316,11 +341,11 @@ public function getFile(): ?string * * @return \AntiMattr\MongoDB\Migrations\Version[] */ - public function getMigratedVersions() + public function getMigratedVersions(): array { $this->createMigrationCollection(); - $cursor = $this->getCollection()->find(); + $cursor = $this->getCollection()->find(['prefix' => $this->prefix]); $versions = []; foreach ($cursor as $record) { $versions[] = $record['v']; @@ -336,16 +361,15 @@ public function getMigratedVersions() * * @return int * - * @throws AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version does not exist - * @throws DomainException If more than one version exists + * @throws \AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version + * does not exist + * @throws \DomainException If more than one version exists */ - public function getMigratedTimestamp($version): int + public function getMigratedTimestamp(string $version): int { $this->createMigrationCollection(); - $cursor = $this->getCollection()->find( - ['v' => $version] - ); + $cursor = $this->getCollection()->find(['v' => $version, 'prefix' => $this->prefix]); if (!$cursor->count()) { throw new UnknownVersionException($version); @@ -370,15 +394,17 @@ public function getMigratedTimestamp($version): int * * @return array */ - public function getUnavailableMigratedVersions() + public function getUnavailableMigratedVersions(): array { - return array_diff($this->getMigratedVersions(), $this->getAvailableVersions()); + return \array_diff($this->getMigratedVersions(), $this->getAvailableVersions()); } /** - * @param string $name + * @param string|null $name + * + * @return self */ - public function setName($name) + public function setName(?string $name): ConfigurationInterface { $this->name = $name; @@ -386,9 +412,9 @@ public function setName($name) } /** - * @return string $name + * @return string */ - public function getName() + public function getName(): string { return ($this->name) ?: 'Database Migrations'; } @@ -396,19 +422,19 @@ public function getName() /** * @return int */ - public function getNumberOfAvailableMigrations() + public function getNumberOfAvailableMigrations(): int { - return count($this->migrations); + return \count($this->migrations); } /** * @return int */ - public function getNumberOfExecutedMigrations() + public function getNumberOfExecutedMigrations(): int { $this->createMigrationCollection(); - $cursor = $this->getCollection()->find(); + $cursor = $this->getCollection()->find(['prefix' => $this->prefix]); return $cursor->count(); } @@ -416,7 +442,7 @@ public function getNumberOfExecutedMigrations() /** * @return \AntiMattr\MongoDB\Migrations\OutputWriter */ - public function getOutputWriter() + public function getOutputWriter(): OutputWriter { return $this->outputWriter; } @@ -426,27 +452,27 @@ public function getOutputWriter() * class. * * @param string $version The version of the migration in the format YYYYMMDDHHMMSS - * @param string $class The migration class to execute for the version + * @param string $class The migration class to execute for the version * * @return Version * - * @throws AntiMattr\MongoDB\Migrations\Exception\DuplicateVersionException + * @throws \AntiMattr\MongoDB\Migrations\Exception\DuplicateVersionException */ - public function registerMigration($version, $class) + public function registerMigration(string $version, string $class): Version { - $version = (string) $version; - $class = (string) $class; + $version = (string)$version; + $class = (string)$class; if (isset($this->migrations[$version])) { - $message = sprintf( + $message = \sprintf( 'Migration version %s already registered with class %s', $version, - get_class($this->migrations[$version]) + \get_class($this->migrations[$version]) ); throw new DuplicateVersionException($message); } - $version = new Version($this, $version, $class); + $version = new Version($this, null === $this->prefix ? self::DEFAULT_PREFIX: $this->prefix, $version, $class); $this->migrations[$version->getVersion()] = $version; - ksort($this->migrations); + \ksort($this->migrations); return $version; } @@ -460,7 +486,7 @@ public function registerMigration($version, $class) * * @return Version[] */ - public function registerMigrations(array $migrations) + public function registerMigrations(array $migrations): array { $versions = []; foreach ($migrations as $version => $class) { @@ -479,17 +505,17 @@ public function registerMigrations(array $migrations) * * @return Version[] The array of migrations registered */ - public function registerMigrationsFromDirectory($path) + public function registerMigrationsFromDirectory(string $path): array { - $path = realpath($path); - $path = rtrim($path, '/'); - $files = glob($path . '/Version*.php'); + $path = \realpath($path); + $path = \rtrim($path, '/'); + $files = \glob($path . '/Version*.php'); $versions = []; - if ($files) { + if (!empty($files)) { foreach ($files as $file) { require_once $file; - $info = pathinfo($file); - $version = substr($info['filename'], 7); + $info = \pathinfo($file); + $version = \substr($info['filename'], 7); $class = $this->migrationsNamespace . '\\' . $info['filename']; $versions[] = $this->registerMigration($version, $class); } @@ -505,9 +531,10 @@ public function registerMigrationsFromDirectory($path) * * @return \AntiMattr\MongoDB\Migrations\Version * - * @throws AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version does not exist + * @throws \AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version + * does not exist */ - public function getVersion($version) + public function getVersion(string $version): Version { if (!isset($this->migrations[$version])) { throw new UnknownVersionException($version); @@ -523,7 +550,7 @@ public function getVersion($version) * * @return bool */ - public function hasVersion($version) + public function hasVersion(string $version): bool { return isset($this->migrations[$version]); } @@ -535,11 +562,11 @@ public function hasVersion($version) * * @return bool */ - public function hasVersionMigrated(Version $version) + public function hasVersionMigrated(Version $version): bool { $this->createMigrationCollection(); - $record = $this->getCollection()->findOne(['v' => $version->getVersion()]); + $record = $this->getCollection()->findOne(['v' => $version->getVersion(), 'prefix' => $this->prefix]); return null !== $record; } @@ -547,7 +574,7 @@ public function hasVersionMigrated(Version $version) /** * @return string */ - public function getCurrentVersion() + public function getCurrentVersion(): string { $this->createMigrationCollection(); @@ -559,11 +586,9 @@ public function getCurrentVersion() } $cursor = $this->getCollection() - ->find( - ['v' => ['$in' => $migratedVersions]] - ) - ->sort(['v' => -1]) - ->limit(1); + ->find(['v' => ['$in' => $migratedVersions], 'prefix' => $this->prefix]) + ->sort(['v' => -1]) + ->limit(1); if (0 === $cursor->count()) { return '0'; @@ -579,12 +604,12 @@ public function getCurrentVersion() * * @return string The version string in the format YYYYMMDDHHMMSS */ - public function getLatestVersion() + public function getLatestVersion(): string { - $versions = array_keys($this->migrations); - $latest = end($versions); + $versions = \array_keys($this->migrations); + $latest = \end($versions); - return false !== $latest ? (string) $latest : '0'; + return false !== $latest ? (string)$latest : '0'; } /** @@ -592,13 +617,13 @@ public function getLatestVersion() * * @return bool Whether or not the collection was created */ - public function createMigrationCollection() + public function createMigrationCollection(): bool { $this->validate(); - if (true !== $this->migrationCollectionCreated) { + if (!$this->migrationCollectionCreated) { $collection = $this->getCollection(); - $collection->ensureIndex(['v' => -1], ['name' => 'version', 'unique' => true]); + $collection->ensureIndex(['v' => -1, 'prefix' => -1], ['name' => 'version', 'unique' => true]); $this->migrationCollectionCreated = true; } @@ -610,17 +635,17 @@ public function createMigrationCollection() * and target version number. * * @param string $direction The direction we are migrating - * @param string $to The version to migrate to + * @param string $to The version to migrate to * * @return Version[] $migrations The array of migrations we can execute */ - public function getMigrationsToExecute($direction, $to) + public function getMigrationsToExecute(string $direction, string $to): array { - if ('down' === $direction) { - if (count($this->migrations)) { - $allVersions = array_reverse(array_keys($this->migrations)); - $classes = array_reverse(array_values($this->migrations)); - $allVersions = array_combine($allVersions, $classes); + if (self::MIGRATION_DIRECTION_DOWN === $direction) { + if (\count($this->migrations)) { + $allVersions = \array_reverse(\array_keys($this->migrations)); + $classes = \array_reverse(\array_values($this->migrations)); + $allVersions = \array_combine($allVersions, $classes); } else { $allVersions = []; } @@ -638,72 +663,62 @@ public function getMigrationsToExecute($direction, $to) return $versions; } - /** - * Check if we should execute a migration for a given direction and target - * migration version. - * - * @param string $direction The direction we are migrating - * @param Version $version The Version instance to check - * @param string $to The version we are migrating to - * @param array $migrated Migrated versions array - * - * @return bool - */ - private function shouldExecuteMigration($direction, Version $version, $to, $migrated) - { - if ('down' === $direction) { - if (!in_array($version->getVersion(), $migrated)) { - return false; - } - - return $version->getVersion() > $to; - } - - if ('up' === $direction) { - if (in_array($version->getVersion(), $migrated)) { - return false; - } - - return $version->getVersion() <= $to; - } - } - /** * Validation that this instance has all the required properties configured. * - * @throws AntiMattr\MongoDB\Migrations\Exception\ConfigurationValidationException + * @throws \AntiMattr\MongoDB\Migrations\Exception\ConfigurationValidationException */ - public function validate() + public function validate(): void { - if (!$this->migrationsDatabaseName) { + if (empty($this->migrationsDatabaseName)) { $message = 'Migrations Database Name must be configured in order to use AntiMattr migrations.'; throw new ConfigurationValidationException($message); } - if (!$this->migrationsNamespace) { + if (empty($this->migrationsNamespace)) { $message = 'Migrations namespace must be configured in order to use AntiMattr migrations.'; throw new ConfigurationValidationException($message); } - if (!$this->migrationsDirectory) { + if (empty($this->migrationsDirectory)) { $message = 'Migrations directory must be configured in order to use AntiMattr migrations.'; throw new ConfigurationValidationException($message); } } + /** + * @return string + */ + public function getPrefix(): string + { + return $this->prefix; + } + + /** + * @param string $prefix + * + * @return ConfigurationInterface + */ + public function setPrefix(string $prefix): ConfigurationInterface + { + $this->prefix = $prefix; + + return $this; + } + /** * @return array */ - public function getDetailsMap() + public function getDetailsMap(): array { // Executed migration count $executedMigrations = $this->getMigratedVersions(); - $numExecutedMigrations = count($executedMigrations); + $numExecutedMigrations = \count($executedMigrations); // Available migration count $availableMigrations = $this->getAvailableVersions(); - $numAvailableMigrations = count($availableMigrations); + $numAvailableMigrations = \count($availableMigrations); // Executed Unavailable migration count - $numExecutedUnavailableMigrations = count($this->getUnavailableMigratedVersions()); + $numExecutedUnavailableMigrations = \count($this->getUnavailableMigratedVersions()); // New migration count $numNewMigrations = $numAvailableMigrations - ($numExecutedMigrations - $numExecutedUnavailableMigrations); @@ -723,4 +738,37 @@ public function getDetailsMap() 'num_new_migrations' => $numNewMigrations, ]; } + + /** + * Check if we should execute a migration for a given direction and target + * migration version. + * + * @param string $direction The direction we are migrating + * @param Version $version The Version instance to check + * @param string $to The version we are migrating to + * @param array $migrated Migrated versions array + * + * @return bool + */ + private function shouldExecuteMigration(string $direction, Version $version, string $to, array $migrated): bool + { + switch ($direction) { + case self::MIGRATION_DIRECTION_DOWN: + if (!\in_array($version->getVersion(), $migrated)) { + return false; + } + + return $version->getVersion() > $to; + + case self::MIGRATION_DIRECTION_UP: + if (\in_array($version->getVersion(), $migrated)) { + return false; + } + + return $version->getVersion() <= $to; + + default: + throw new \LogicException("Specified direction {$direction} is not supported."); + } + } } diff --git a/src/AntiMattr/MongoDB/Migrations/Configuration/ConfigurationBuilder.php b/src/AntiMattr/MongoDB/Migrations/Configuration/ConfigurationBuilder.php index bdf5463..b188590 100644 --- a/src/AntiMattr/MongoDB/Migrations/Configuration/ConfigurationBuilder.php +++ b/src/AntiMattr/MongoDB/Migrations/Configuration/ConfigurationBuilder.php @@ -1,6 +1,5 @@ */ -class ConfigurationBuilder +class ConfigurationBuilder implements ConfigurationBuilderInterface { /** * @var \Doctrine\MongoDB\Connection @@ -56,9 +57,9 @@ private function __construct() } /** - * @return ConfigurationBuilder + * @return ConfigurationBuilderInterface */ - public static function create(): ConfigurationBuilder + public static function create(): ConfigurationBuilderInterface { return new static(); } @@ -66,9 +67,9 @@ public static function create(): ConfigurationBuilder /** * @param Connection $connection * - * @return ConfigurationBuilder + * @return self */ - public function setConnection(Connection $connection): ConfigurationBuilder + public function setConnection(Connection $connection): ConfigurationBuilderInterface { $this->connection = $connection; @@ -78,9 +79,9 @@ public function setConnection(Connection $connection): ConfigurationBuilder /** * @param OutputWriter $outputWriter * - * @return ConfigurationBuilder + * @return self */ - public function setOutputWriter(OutputWriter $outputWriter): ConfigurationBuilder + public function setOutputWriter(OutputWriter $outputWriter): ConfigurationBuilderInterface { $this->outputWriter = $outputWriter; @@ -90,9 +91,9 @@ public function setOutputWriter(OutputWriter $outputWriter): ConfigurationBuilde /** * @param string|null $configFile * - * @return ConfigurationBuilder + * @return self */ - public function setOnDiskConfiguration(?string $configFile = null): ConfigurationBuilder + public function setOnDiskConfiguration(?string $configFile = null): ConfigurationBuilderInterface { $this->configFile = $configFile; @@ -135,18 +136,17 @@ public function setOnDiskConfiguration(?string $configFile = null): Configuratio } /** - * @return Configuration + * @return ConfigurationInterface */ - public function build(): Configuration + public function build(): ConfigurationInterface { - $config = new Configuration($this->connection, $this->outputWriter); + $config = $this->createConfigurationInstance($this->connection, $this->outputWriter); $config->setName($this->configParams['name']) - ->setFile($this->configFile) - ->setMigrationsDatabaseName($this->configParams['database']) - ->setMigrationsCollectionName($this->configParams['collection_name']) - ->setMigrationsNamespace($this->configParams['migrations_namespace']) - ; + ->setFile($this->configFile) + ->setMigrationsDatabaseName($this->configParams['database']) + ->setMigrationsCollectionName($this->configParams['collection_name']) + ->setMigrationsNamespace($this->configParams['migrations_namespace']); if (!empty($this->configParams['migrations_directory'])) { $migrationsDirectory = $this->getDirectoryRelativeToFile( @@ -155,7 +155,7 @@ public function build(): Configuration ); $config->setMigrationsDirectory($migrationsDirectory) - ->registerMigrationsFromDirectory($migrationsDirectory); + ->registerMigrationsFromDirectory($migrationsDirectory); } if (!empty($this->configParams['migrations_script_directory'])) { @@ -188,27 +188,27 @@ private function loadXmlFile(string $configFile): array $configArr = []; if (isset($xml->name)) { - $configArr['name'] = (string) $xml->name; + $configArr['name'] = (string)$xml->name; } if (isset($xml->database['name'])) { - $configArr['database'] = (string) $xml->database['name']; + $configArr['database'] = (string)$xml->database['name']; } if (isset($xml->collection['name'])) { - $configArr['collection_name'] = (string) $xml->collection['name']; + $configArr['collection_name'] = (string)$xml->collection['name']; } if (isset($xml->{'migrations-namespace'})) { - $configArr['migrations_namespace'] = (string) $xml->{'migrations-namespace'}; + $configArr['migrations_namespace'] = (string)$xml->{'migrations-namespace'}; } if (isset($xml->{'migrations-directory'})) { - $configArr['migrations_directory'] = (string) $xml->{'migrations-directory'}; + $configArr['migrations_directory'] = (string)$xml->{'migrations-directory'}; } if (isset($xml->{'migrations-script-directory'})) { - $configArr['migrations_script_directory'] = (string) $xml->{'migrations-script-directory'}; + $configArr['migrations_script_directory'] = (string)$xml->{'migrations-script-directory'}; } if (isset($xml->migrations->migration)) { @@ -245,4 +245,19 @@ protected function getDirectoryRelativeToFile(string $configFile, ?string $direc return $directory; } + + /** + * Create configuration instance + * + * @param Connection $connection + * @param OutputWriter $outputWriter + * + * @return ConfigurationInterface + */ + protected function createConfigurationInstance( + Connection $connection, + OutputWriter $outputWriter + ): ConfigurationInterface { + return new Configuration($connection, $outputWriter); + } } diff --git a/src/AntiMattr/MongoDB/Migrations/Configuration/Interfaces/ConfigurationBuilderInterface.php b/src/AntiMattr/MongoDB/Migrations/Configuration/Interfaces/ConfigurationBuilderInterface.php new file mode 100644 index 0000000..582c587 --- /dev/null +++ b/src/AntiMattr/MongoDB/Migrations/Configuration/Interfaces/ConfigurationBuilderInterface.php @@ -0,0 +1,48 @@ + + */ +interface ConfigurationBuilderInterface +{ + + /** + * @return ConfigurationBuilderInterface + */ + public static function create(): ConfigurationBuilderInterface; + + /** + * @param Connection $connection + * + * @return self + */ + public function setConnection(Connection $connection): self; + + /** + * @param OutputWriter $outputWriter + * + * @return self + */ + public function setOutputWriter(OutputWriter $outputWriter): self; + + /** + * @param string|null $configFile + * + * @return self + */ + public function setOnDiskConfiguration(?string $configFile = null): self; + + /** + * @return ConfigurationInterface + */ + public function build(): ConfigurationInterface; +} diff --git a/src/AntiMattr/MongoDB/Migrations/Configuration/Interfaces/ConfigurationInterface.php b/src/AntiMattr/MongoDB/Migrations/Configuration/Interfaces/ConfigurationInterface.php new file mode 100644 index 0000000..ea9fa24 --- /dev/null +++ b/src/AntiMattr/MongoDB/Migrations/Configuration/Interfaces/ConfigurationInterface.php @@ -0,0 +1,306 @@ + + */ +interface ConfigurationInterface +{ + + /** + * Returns a timestamp version as a formatted date. + * + * @param string $version + * + * @return string The formatted version + */ + public static function formatVersion($version): string; + + /** + * Returns an array of available migration version numbers. + * + * @return array + */ + public function getAvailableVersions(): array; + + /** + * @return \Doctrine\MongoDB\Collection|null + */ + public function getCollection(): ?Collection; + + /** + * @return \Doctrine\MongoDB\Connection|null + */ + public function getConnection(): ?Connection; + + /** + * @return \Doctrine\MongoDB\Database|null + */ + public function getDatabase(): ?Database; + + /** + * Get the array of registered migration versions. + * + * @return Version[] $migrations + */ + public function getMigrations(): array; + + /** + * @param string|null $databaseName + * + * @return ConfigurationInterface + */ + public function setMigrationsDatabaseName(?string $databaseName): ConfigurationInterface; + + /** + * @return string|null + */ + public function getMigrationsDatabaseName(): ?string; + + /** + * @param string|null $collectionName + * + * @return ConfigurationInterface + */ + public function setMigrationsCollectionName(?string $collectionName): ConfigurationInterface; + + /** + * @return string|null + */ + public function getMigrationsCollectionName(): ?string; + + /** + * @param string $migrationsDirectory + * + * @return ConfigurationInterface + */ + public function setMigrationsDirectory(string $migrationsDirectory): ConfigurationInterface; + + /** + * @return string|null + */ + public function getMigrationsDirectory(): ?string; + + /** + * Set the migrations namespace. + * + * @param string|null $migrationsNamespace The migrations namespace + * + * @return ConfigurationInterface + */ + public function setMigrationsNamespace(?string $migrationsNamespace): ConfigurationInterface; + + /** + * @return string|null + */ + public function getMigrationsNamespace(): ?string; + + /** + * @param string $scriptsDirectory + * + * @return self + */ + public function setMigrationsScriptDirectory(string $scriptsDirectory): ConfigurationInterface; + + /** + * @return string|null + */ + public function getMigrationsScriptDirectory(): ?string; + + /** + * @param string|null $file + * + * @return self + */ + public function setFile(?string $file): ConfigurationInterface; + + /** + * @return string|null + */ + public function getFile(): ?string; + + /** + * Returns all migrated versions from the versions collection, in an array. + * + * @return \AntiMattr\MongoDB\Migrations\Version[] + */ + public function getMigratedVersions(): array; + + /** + * Returns the time a migration occurred. + * + * @param string $version + * + * @return int + * + * @throws \AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version + * does not exist + * @throws \DomainException If more than one version exists + */ + public function getMigratedTimestamp(string $version): int; + + /** + * Return all migrated versions from versions collection that have migration files deleted. + * + * @return array + */ + public function getUnavailableMigratedVersions(): array; + + /** + * @param string|null $name + * + * @return self + */ + public function setName(?string $name): ConfigurationInterface; + + /** + * @return string $name + */ + public function getName(): string; + + /** + * @return int + */ + public function getNumberOfAvailableMigrations(): int; + + /** + * @return int + */ + public function getNumberOfExecutedMigrations(): int; + + /** + * @return \AntiMattr\MongoDB\Migrations\OutputWriter + */ + public function getOutputWriter(): OutputWriter; + + /** + * Register a single migration version to be executed by a AbstractMigration + * class. + * + * @param string $version The version of the migration in the format YYYYMMDDHHMMSS + * @param string $class The migration class to execute for the version + * + * @return Version + * + * @throws \AntiMattr\MongoDB\Migrations\Exception\DuplicateVersionException + */ + public function registerMigration(string $version, string $class): Version; + + /** + * Register an array of migrations. Each key of the array is the version and + * the value is the migration class name. + * + * + * @param array $migrations + * + * @return Version[] + */ + public function registerMigrations(array $migrations): array; + + /** + * Register migrations from a given directory. Recursively finds all files + * with the pattern VersionYYYYMMDDHHMMSS.php as the filename and registers + * them as migrations. + * + * @param string $path The root directory to where some migration classes live + * + * @return Version[] The array of migrations registered + */ + public function registerMigrationsFromDirectory(string $path): array; + + /** + * Returns the Version instance for a given version in the format YYYYMMDDHHMMSS. + * + * @param string $version The version string in the format YYYYMMDDHHMMSS + * + * @return \AntiMattr\MongoDB\Migrations\Version + * + * @throws \AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version + * does not exist + */ + public function getVersion(string $version): Version; + + /** + * Check if a version exists. + * + * @param string $version + * + * @return bool + */ + public function hasVersion(string $version): bool; + + /** + * Check if a version has been migrated or not yet. + * + * @param \AntiMattr\MongoDB\Migrations\Version $version + * + * @return bool + */ + public function hasVersionMigrated(Version $version): bool; + + /** + * @return string + */ + public function getCurrentVersion(): string; + + /** + * Returns the latest available migration version. + * + * @return string The version string in the format YYYYMMDDHHMMSS + */ + public function getLatestVersion(): string; + + /** + * Create the migration collection to track migrations with. + * + * @return bool Whether or not the collection was created + */ + public function createMigrationCollection(): bool; + + /** + * Returns the array of migrations to executed based on the given direction + * and target version number. + * + * @param string $direction The direction we are migrating + * @param string $to The version to migrate to + * + * @return Version[] $migrations The array of migrations we can execute + */ + public function getMigrationsToExecute(string $direction, string $to): array; + + /** + * Validation that this instance has all the required properties configured. + * + * @throws \AntiMattr\MongoDB\Migrations\Exception\ConfigurationValidationException + */ + public function validate(): void; + + /** + * @return string + */ + public function getPrefix(): string; + + /** + * @param string $prefix + * + * @return ConfigurationInterface + */ + public function setPrefix(string $prefix): ConfigurationInterface; + + + /** + * @return array + */ + public function getDetailsMap(): array; +} diff --git a/src/AntiMattr/MongoDB/Migrations/Migration.php b/src/AntiMattr/MongoDB/Migrations/Migration.php index bbc3687..6161a75 100644 --- a/src/AntiMattr/MongoDB/Migrations/Migration.php +++ b/src/AntiMattr/MongoDB/Migrations/Migration.php @@ -48,8 +48,8 @@ public function __construct(Configuration $configuration) * * @param string $to The version to migrate to * - * @throws AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException - * @throws AntiMattr\MongoDB\Migrations\Exception\NoMigrationsToExecuteException + * @throws \AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException + * @throws \AntiMattr\MongoDB\Migrations\Exception\NoMigrationsToExecuteException */ public function migrate($to = null) { diff --git a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/AbstractCommand.php b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/AbstractCommand.php index 03823f1..b603708 100644 --- a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/AbstractCommand.php +++ b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/AbstractCommand.php @@ -1,4 +1,5 @@ addOption( - 'configuration', null, InputOption::VALUE_OPTIONAL, 'The path to a migrations configuration file.' + 'configuration', + null, + InputOption::VALUE_OPTIONAL, + 'The path to a migrations configuration file.' ); $this->addOption( - 'db-configuration', null, InputOption::VALUE_OPTIONAL, 'The path to a database connection configuration file.' + 'db-configuration', + null, + InputOption::VALUE_OPTIONAL, + 'The path to a database connection configuration file.' ); } /** * @param \AntiMattr\MongoDB\Migrations\Configuration\Configuration $configuration * @param \Symfony\Component\Console\Output\OutputInterface $output + * + * @return void */ - protected function outputHeader(Configuration $configuration, OutputInterface $output) + protected function outputHeader(Configuration $configuration, OutputInterface $output): void { $name = $configuration->getName(); - $name = $name ? $name : 'AntiMattr Database Migrations'; - $name = str_repeat(' ', 20) . $name . str_repeat(' ', 20); - $output->writeln('' . str_repeat(' ', strlen($name)) . ''); + $name = !empty($name) ? $name : 'AntiMattr Database Migrations'; + $name = \str_repeat(' ', 20) . $name . \str_repeat(' ', 20); + $output->writeln('' . \str_repeat(' ', \strlen($name)) . ''); $output->writeln('' . $name . ''); - $output->writeln('' . str_repeat(' ', strlen($name)) . ''); + $output->writeln('' . \str_repeat(' ', \strlen($name)) . ''); $output->writeln(''); } /** * @param \AntiMattr\MongoDB\Migrations\Configuration\Configuration + * + * @return void */ - public function setMigrationConfiguration(Configuration $config) + public function setMigrationConfiguration(ConfigurationInterface $config): void { $this->configuration = $config; } @@ -72,24 +87,24 @@ public function setMigrationConfiguration(Configuration $config) * * @return \AntiMattr\MongoDB\Migrations\Configuration\Configuration */ - protected function getMigrationConfiguration( - InputInterface $input, - OutputInterface $output - ): Configuration { - if (!$this->configuration) { + protected function getMigrationConfiguration(InputInterface $input, OutputInterface $output): ConfigurationInterface + { + if (empty($this->configuration)) { $conn = $this->getDatabaseConnection($input); - $outputWriter = new OutputWriter(function($message) use ($output) { - return $output->writeln($message); - }); + $outputWriter = new OutputWriter( + function ($message) use ($output) { + return $output->writeln($message); + } + ); $migrationsConfigFile = $input->getOption('configuration'); - $this->configuration = ConfigurationBuilder::create() - ->setConnection($conn) - ->setOutputWriter($outputWriter) - ->setOnDiskConfiguration($migrationsConfigFile) - ->build(); + $this->configuration = $this->getConfigurationBuilder() + ->setConnection($conn) + ->setOutputWriter($outputWriter) + ->setOnDiskConfiguration($migrationsConfigFile) + ->build(); } return $this->configuration; @@ -105,8 +120,8 @@ protected function getDatabaseConnection(InputInterface $input): Connection // Default to document manager helper set if ($this->getApplication()->getHelperSet()->has('dm')) { return $this->getHelper('dm') - ->getDocumentManager() - ->getConnection(); + ->getDocumentManager() + ->getConnection(); } // PHP array file @@ -118,13 +133,13 @@ protected function getDatabaseConnection(InputInterface $input): Connection ); } - if (!file_exists($dbConfiguration)) { + if (!\file_exists($dbConfiguration)) { throw new \InvalidArgumentException('The specified connection file is not a valid file.'); } $dbConfigArr = include $dbConfiguration; - if (!is_array($dbConfigArr)) { + if (!\is_array($dbConfigArr)) { throw new \InvalidArgumentException( 'The connection file has to return an array with database configuration parameters.' ); @@ -138,7 +153,7 @@ protected function getDatabaseConnection(InputInterface $input): Connection * * @return \Doctrine\MongoDB\Connection */ - protected function createConnection($params) + protected function createConnection($params): Connection { $credentials = ''; if (isset($params['password'])) { @@ -153,7 +168,7 @@ protected function createConnection($params) $database = '/' . $params['dbname']; } - $server = sprintf( + $server = \sprintf( 'mongodb://%s%s:%s%s', $credentials, (isset($params['host']) ? $params['host'] : 'localhost'), @@ -168,4 +183,14 @@ protected function createConnection($params) return new Connection($server, $options); } + + /** + * Create instance of configuration builder for command. + * + * @return ConfigurationBuilderInterface + */ + protected function getConfigurationBuilder(): ConfigurationBuilderInterface + { + return ConfigurationBuilder::create(); + } } diff --git a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/BCFixCommand.php b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/BCFixCommand.php new file mode 100644 index 0000000..27fe349 --- /dev/null +++ b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/BCFixCommand.php @@ -0,0 +1,57 @@ + + */ +class BCFixCommand extends AbstractCommand +{ + public const NAME = 'mongodb:migrations:bc-fix'; + + protected function configure(): void + { + $this + ->setName($this->getName()) + ->setDescription('Add to existing migrations with missing prefix default app prefix.'); + + parent::configure(); + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface + * @param \Symfony\Component\Console\Output\OutputInterface + * + * @throws \InvalidArgumentException + */ + public function execute(InputInterface $input, OutputInterface $output): void + { + $configuration = $this->getMigrationConfiguration($input, $output); + $collection = $configuration->getCollection(); + $collection->findAndUpdate( + ['prefix' => ['$exists' => false]], + ['$set' => ['prefix' => Configuration::DEFAULT_PREFIX]] + ); + $collection->deleteIndex(['v' => -1]); + $collection->ensureIndex(['v' => -1, 'prefix' => -1], ['name' => 'version', 'unique' => true]); + } + + public function getName() + { + return self::NAME; + } +} diff --git a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/ExecuteCommand.php b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/ExecuteCommand.php index a4bdb75..bac7f39 100644 --- a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/ExecuteCommand.php +++ b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/ExecuteCommand.php @@ -11,7 +11,6 @@ namespace AntiMattr\MongoDB\Migrations\Tools\Console\Command; -use AntiMattr\MongoDB\Migrations\Migration; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -25,7 +24,7 @@ class ExecuteCommand extends AbstractCommand { const NAME = 'mongodb:migrations:execute'; - protected function configure() + protected function configure(): void { $this ->setName($this->getName()) diff --git a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/GenerateCommand.php b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/GenerateCommand.php index 67d423b..c4c6175 100644 --- a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/GenerateCommand.php +++ b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/GenerateCommand.php @@ -58,7 +58,7 @@ public function down(Database $db) } '; - protected function configure() + protected function configure(): void { $this ->setName($this->getName()) @@ -101,7 +101,7 @@ public function execute(InputInterface $input, OutputInterface $output) * * @return string $path * - * @throws InvalidArgumentException + * @throws \InvalidArgumentException */ protected function generateMigration(Configuration $configuration, InputInterface $input, $version, $up = null, $down = null) { diff --git a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/MigrateCommand.php b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/MigrateCommand.php index 6c13c3d..26d3bed 100644 --- a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/MigrateCommand.php +++ b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/MigrateCommand.php @@ -25,7 +25,7 @@ class MigrateCommand extends AbstractCommand { const NAME = 'mongodb:migrations:migrate'; - protected function configure() + protected function configure(): void { $this ->setName($this->getName()) @@ -45,7 +45,7 @@ protected function configure() %command.full_name% --no-interaction EOT - ); + ); parent::configure(); } @@ -63,14 +63,15 @@ public function execute(InputInterface $input, OutputInterface $output) $this->outputHeader($configuration, $output); - $noInteraction = !$input->isInteractive(); + $isInteractive = $input->isInteractive(); $executedVersions = $configuration->getMigratedVersions(); $availableVersions = $configuration->getAvailableVersions(); $executedUnavailableVersions = array_diff($executedVersions, $availableVersions); - if ($executedUnavailableVersions) { - $output->writeln(sprintf('WARNING! You have %s previously executed migrations in the database that are not registered migrations.', count($executedUnavailableVersions))); + if (!empty($executedUnavailableVersions)) { + $output->writeln(sprintf('WARNING! You have %s previously executed migrations in the database that are not registered migrations.', + count($executedUnavailableVersions))); foreach ($executedUnavailableVersions as $executedUnavailableVersion) { $output->writeln( sprintf( @@ -81,7 +82,7 @@ public function execute(InputInterface $input, OutputInterface $output) ); } - if (!$noInteraction) { + if ($isInteractive) { $question = new ConfirmationQuestion( 'Are you sure you wish to continue? (y/[n]) ', false @@ -100,7 +101,7 @@ public function execute(InputInterface $input, OutputInterface $output) } // warn the user if no dry run and interaction is on - if (!$noInteraction) { + if ($isInteractive) { $question = new ConfirmationQuestion( 'WARNING! You are about to execute a database migration that could result in data lost. Are you sure you wish to continue? (y/[n]) ', false @@ -118,6 +119,8 @@ public function execute(InputInterface $input, OutputInterface $output) } $migration->migrate($version); + + return 0; } protected function createMigration(Configuration $configuration) diff --git a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/StatusCommand.php b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/StatusCommand.php index 6118764..a7204ec 100644 --- a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/StatusCommand.php +++ b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/StatusCommand.php @@ -11,7 +11,6 @@ namespace AntiMattr\MongoDB\Migrations\Tools\Console\Command; -use AntiMattr\MongoDB\Migrations\Migration; use AntiMattr\MongoDB\Migrations\Configuration\Configuration; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -25,7 +24,7 @@ class StatusCommand extends AbstractCommand { const NAME = 'mongodb:migrations:status'; - protected function configure() + protected function configure(): void { $this ->setName($this->getName()) diff --git a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/VersionCommand.php b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/VersionCommand.php index 50c77d7..b367c10 100644 --- a/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/VersionCommand.php +++ b/src/AntiMattr/MongoDB/Migrations/Tools/Console/Command/VersionCommand.php @@ -26,7 +26,7 @@ class VersionCommand extends AbstractCommand { const NAME = 'mongodb:migrations:version'; - protected function configure() + protected function configure(): void { $this ->setName($this->getName()) @@ -52,13 +52,12 @@ protected function configure() * @param \Symfony\Component\Console\Input\InputInterface * @param \Symfony\Component\Console\Output\OutputInterface * - * @throws AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version does not exist - * @throws InvalidArgumentException + * @throws \AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version does not exist + * @throws \InvalidArgumentException */ public function execute(InputInterface $input, OutputInterface $output) { $configuration = $this->getMigrationConfiguration($input, $output); - $migration = $this->createMigration($configuration); if (false === $input->getOption('add') && false === $input->getOption('delete')) { throw new \InvalidArgumentException('You must specify whether you want to --add or --delete the specified version.'); @@ -68,7 +67,7 @@ public function execute(InputInterface $input, OutputInterface $output) $markMigrated = $input->getOption('add') ? true : false; if (!$configuration->hasVersion($version)) { - throw new UnknownVersionException($version); + throw new UnknownVersionException("The version \"{$version}\" is not found."); } $version = $configuration->getVersion($version); diff --git a/src/AntiMattr/MongoDB/Migrations/Version.php b/src/AntiMattr/MongoDB/Migrations/Version.php index febd3d9..16cef11 100644 --- a/src/AntiMattr/MongoDB/Migrations/Version.php +++ b/src/AntiMattr/MongoDB/Migrations/Version.php @@ -1,4 +1,5 @@ configuration = $configuration; + $this->prefix = $prefix; $this->outputWriter = $configuration->getOutputWriter(); $this->class = $class; $this->connection = $configuration->getConnection(); @@ -175,7 +194,7 @@ public function analyze(Collection $collection) * Execute this migration version up or down. * * @param string $direction The direction to execute the migration - * @param bool $replay If the migration is being replayed + * @param bool $replay If the migration is being replayed * * @throws \Exception when migration fails */ @@ -195,9 +214,11 @@ public function execute($direction, $replay = false) $this->migration->{'pre' . ucfirst($direction)}($this->db); if ('up' === $direction) { - $this->outputWriter->write("\n" . sprintf(' ++ migrating %s', $this->version) . "\n"); + $this->outputWriter->write("\n" . sprintf(' ++ migrating %s', + $this->version) . "\n"); } else { - $this->outputWriter->write("\n" . sprintf(' -- reverting %s', $this->version) . "\n"); + $this->outputWriter->write("\n" . sprintf(' -- reverting %s', + $this->version) . "\n"); } $this->state = self::STATE_EXEC; @@ -254,8 +275,8 @@ public function execute($direction, $replay = false) * * @return array * - * @throws RuntimeException - * @throws InvalidArgumentException + * @throws \RuntimeException + * @throws \InvalidArgumentException * @throws Exception */ public function executeScript(Database $db, $file) @@ -298,10 +319,10 @@ public function markMigrated($replay = false) $this->configuration->createMigrationCollection(); $collection = $this->configuration->getCollection(); - $document = ['v' => $this->version, 't' => $this->createMongoTimestamp()]; + $document = ['v' => $this->version, 't' => $this->createMongoTimestamp(), 'prefix' => $this->prefix]; if ($replay) { - $query = ['v' => $this->version]; + $query = ['v' => $this->version, 'prefix' => $this->prefix]; // If the user asked for a 'replay' of a migration that // has not been run, it will be inserted anew $options = ['upsert' => true]; @@ -315,7 +336,7 @@ public function markNotMigrated() { $this->configuration->createMigrationCollection(); $collection = $this->configuration->getCollection(); - $collection->remove(['v' => $this->version]); + $collection->remove(['v' => $this->version, 'prefix' => $this->prefix]); } protected function updateStatisticsAfter() @@ -375,7 +396,7 @@ private function summarizeStatistics() public function __toString() { - return $this->version; + return (string)$this->version; } /** diff --git a/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationBuilderTest.php b/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationBuilderTest.php index 30a81f5..3d04031 100644 --- a/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationBuilderTest.php +++ b/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationBuilderTest.php @@ -1,76 +1,88 @@ createMock('Doctrine\MongoDB\Connection'); $outputWriter = new OutputWriter(); $onDiskConfig = ''; $config = ConfigurationBuilder::create() - ->setConnection($conn) - ->setOutputWriter($outputWriter) - ->setOnDiskConfiguration($onDiskConfig) - ->build(); + ->setConnection($conn) + ->setOutputWriter($outputWriter) + ->setOnDiskConfiguration($onDiskConfig) + ->build(); $this->assertInstanceOf(Configuration::class, $config); $this->assertSame($conn, $config->getConnection()); $this->assertSame($outputWriter, $config->getOutputWriter()); } - public function testBuildingWithYamlConfig() + public function testBuildingWithYamlConfig(): void { + /** @var Connection|MockObject $conn */ $conn = $this->createMock('Doctrine\MongoDB\Connection'); $outputWriter = new OutputWriter(); - $onDiskConfig = dirname(__DIR__) . '/Resources/fixtures/config.yml'; + $onDiskConfig = \dirname(__DIR__) . '/Resources/fixtures/config.yml'; $config = ConfigurationBuilder::create() - ->setConnection($conn) - ->setOutputWriter($outputWriter) - ->setOnDiskConfiguration($onDiskConfig) - ->build(); + ->setConnection($conn) + ->setOutputWriter($outputWriter) + ->setOnDiskConfiguration($onDiskConfig) + ->build(); $this->assertInstanceOf(Configuration::class, $config); $this->assertSame($conn, $config->getConnection()); $this->assertSame($outputWriter, $config->getOutputWriter()); - $this->assertEquals('/path/to/migrations/classes/AntiMattrMigrations', $config->getMigrationsDirectory()); - $this->assertEquals('AntiMattrMigrationsTest', $config->getMigrationsNamespace()); + $this->assertEquals( + './tests/AntiMattr/Tests/MongoDB/Migrations/Resources/Migrations', + $config->getMigrationsDirectory() + ); + $this->assertEquals('Example\Migrations\TestAntiMattr\MongoDB', $config->getMigrationsNamespace()); $this->assertEquals('AntiMattr Sandbox Migrations', $config->getName()); $this->assertEquals('antimattr_migration_versions_test', $config->getMigrationsCollectionName()); $this->assertEquals('test_antimattr_migrations', $config->getMigrationsDatabaseName()); - $this->assertEquals('/path/to/migrations/script_directory', $config->getMigrationsScriptDirectory()); + $this->assertEquals('./bin', $config->getMigrationsScriptDirectory()); } public function testBuildingWithXmlConfig() { + /** @var Connection|MockObject $conn */ $conn = $this->createMock('Doctrine\MongoDB\Connection'); $outputWriter = new OutputWriter(); - $onDiskConfig = dirname(__DIR__) . '/Resources/fixtures/config.xml'; + $onDiskConfig = \dirname(__DIR__) . '/Resources/fixtures/config.xml'; $config = ConfigurationBuilder::create() - ->setConnection($conn) - ->setOutputWriter($outputWriter) - ->setOnDiskConfiguration($onDiskConfig) - ->build(); + ->setConnection($conn) + ->setOutputWriter($outputWriter) + ->setOnDiskConfiguration($onDiskConfig) + ->build(); $this->assertInstanceOf(Configuration::class, $config); $this->assertSame($conn, $config->getConnection()); $this->assertSame($outputWriter, $config->getOutputWriter()); - $this->assertEquals('/path/to/migrations/classes/AntiMattrMigrations', $config->getMigrationsDirectory()); - $this->assertEquals('AntiMattrMigrationsTest', $config->getMigrationsNamespace()); + $this->assertEquals( + './tests/AntiMattr/Tests/MongoDB/Migrations/Resources/Migrations', + $config->getMigrationsDirectory() + ); + $this->assertEquals('Example\Migrations\TestAntiMattr\MongoDB', $config->getMigrationsNamespace()); $this->assertEquals('AntiMattr Sandbox Migrations', $config->getName()); $this->assertEquals('antimattr_migration_versions_test', $config->getMigrationsCollectionName()); $this->assertEquals('test_antimattr_migrations', $config->getMigrationsDatabaseName()); - $this->assertEquals('/path/to/migrations/script_directory', $config->getMigrationsScriptDirectory()); + $this->assertEquals('./bin', $config->getMigrationsScriptDirectory()); } } diff --git a/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationTest.php b/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationTest.php index 2379f5e..2d74b58 100644 --- a/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationTest.php +++ b/tests/AntiMattr/Tests/MongoDB/Migrations/Configuration/ConfigurationTest.php @@ -1,19 +1,28 @@ connection = $this->createMock('Doctrine\MongoDB\Connection'); + $this->connection = $this->createMock(Connection::class); $this->configuration = new Configuration($this->connection); + $this->configuration->setPrefix(Configuration::DEFAULT_PREFIX); } public function testConstructor() @@ -32,14 +41,14 @@ public function testGetCollection() $database = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($database); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($database); $database->expects($this->once()) - ->method('selectCollection') - ->with('antimattr_migration_versions_test') - ->willReturn($expectedCollection); + ->method('selectCollection') + ->with('antimattr_migration_versions_test') + ->willReturn($expectedCollection); $collection = $this->configuration->getCollection(); $this->assertEquals($expectedCollection, $collection); @@ -49,44 +58,47 @@ public function testGetCurrentVersion() { $this->prepareValidConfiguration(); - $directory = dirname(__DIR__) . '/Resources/Migrations/'; + $directory = \dirname(__DIR__) . '/Resources/Migrations/'; $this->configuration->registerMigrationsFromDirectory($directory); $collection = $this->createMock('Doctrine\MongoDB\Collection'); $database = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($database); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($database); $database->expects($this->once()) - ->method('selectCollection') - ->with('antimattr_migration_versions_test') - ->willReturn($collection); + ->method('selectCollection') + ->with('antimattr_migration_versions_test') + ->willReturn($collection); $cursor = $this->createMock('Doctrine\MongoDB\Cursor'); - $in = ['v' => ['$in' => ['20140822185742', '20140822185743', '20140822185744']]]; + $in = [ + 'v' => ['$in' => ['20140822185742', '20140822185743', '20140822185744']], + 'prefix' => Configuration::DEFAULT_PREFIX, + ]; $collection->expects($this->once()) - ->method('find') - ->with($in) - ->willReturn($cursor); + ->method('find') + ->with($in) + ->willReturn($cursor); $cursor->expects($this->once()) - ->method('sort') - ->with(['v' => -1]) - ->willReturn($cursor); + ->method('sort') + ->with(['v' => -1]) + ->willReturn($cursor); $cursor->expects($this->once()) - ->method('limit') - ->with(1) - ->willReturn($cursor); + ->method('limit') + ->with(1) + ->willReturn($cursor); $cursor->expects($this->once()) - ->method('getNext') - ->willReturn(['v' => '20140822185743']); + ->method('getNext') + ->willReturn(['v' => '20140822185743']); $version = $this->configuration->getCurrentVersion(); @@ -100,9 +112,9 @@ public function testGetDatabase() $expectedDatabase = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($expectedDatabase); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($expectedDatabase); $database = $this->configuration->getDatabase(); $this->assertEquals($expectedDatabase, $database); @@ -116,14 +128,14 @@ public function testGetMigratedVersions() $database = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($database); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($database); $database->expects($this->once()) - ->method('selectCollection') - ->with('antimattr_migration_versions_test') - ->willReturn($collection); + ->method('selectCollection') + ->with('antimattr_migration_versions_test') + ->willReturn($collection); $foundVersions = [ ['v' => 'found1'], @@ -136,8 +148,8 @@ public function testGetMigratedVersions() ]; $collection->expects($this->once()) - ->method('find') - ->willReturn($foundVersions); + ->method('find') + ->willReturn($foundVersions); $versions = $this->configuration->getMigratedVersions(); $this->assertEquals($expectedVersions, $versions); @@ -151,24 +163,24 @@ public function testGetNumberOfExecutedMigrations() $database = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($database); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($database); $database->expects($this->once()) - ->method('selectCollection') - ->with('antimattr_migration_versions_test') - ->willReturn($collection); + ->method('selectCollection') + ->with('antimattr_migration_versions_test') + ->willReturn($collection); $cursor = $this->createMock('Doctrine\MongoDB\Cursor'); $collection->expects($this->once()) - ->method('find') - ->willReturn($cursor); + ->method('find') + ->willReturn($cursor); $cursor->expects($this->once()) - ->method('count') - ->willReturn(2); + ->method('count') + ->willReturn(2); $this->assertEquals(2, $this->configuration->getNumberOfExecutedMigrations()); } @@ -178,16 +190,16 @@ public function testRegisterMigrationsFromDirectory() $this->configuration->setMigrationsNamespace('Example\Migrations\TestAntiMattr\MongoDB'); $this->assertFalse($this->configuration->hasVersion('20140822185742')); - $directory = dirname(__DIR__) . '/Resources/Migrations/'; + $directory = \dirname(__DIR__) . '/Resources/Migrations/'; $this->configuration->registerMigrationsFromDirectory($directory); - $this->assertEquals(3, count($this->configuration->getMigrations())); - $this->assertEquals(3, count($this->configuration->getAvailableVersions())); + $this->assertEquals(3, \count($this->configuration->getMigrations())); + $this->assertEquals(3, \count($this->configuration->getAvailableVersions())); $this->assertEquals(3, $this->configuration->getNumberOfAvailableMigrations()); $this->assertTrue($this->configuration->hasVersion('20140822185742')); - $version = $this->configuration->getVersion('20140822185742'); + $this->configuration->getVersion('20140822185742'); } /** @@ -200,7 +212,9 @@ public function testGetVersionThrowsUnknownVersionException() public function testHasVersionMigrated() { + /** @var Version|MockObject $version1 */ $version1 = $this->createMock('AntiMattr\MongoDB\Migrations\Version'); + /** @var Version|MockObject $version2 */ $version2 = $this->createMock('AntiMattr\MongoDB\Migrations\Version'); $this->prepareValidConfiguration(); @@ -209,32 +223,32 @@ public function testHasVersionMigrated() $database = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($database); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($database); $database->expects($this->once()) - ->method('selectCollection') - ->with('antimattr_migration_versions_test') - ->willReturn($collection); + ->method('selectCollection') + ->with('antimattr_migration_versions_test') + ->willReturn($collection); $version1->expects($this->once()) - ->method('getVersion') - ->willReturn('found'); + ->method('getVersion') + ->willReturn('found'); $version2->expects($this->once()) - ->method('getVersion') - ->willReturn('found2'); + ->method('getVersion') + ->willReturn('found2'); $collection->expects($this->at(1)) - ->method('findOne') - ->with(['v' => 'found']) - ->willReturn('foo'); + ->method('findOne') + ->with(['v' => 'found', 'prefix' => Configuration::DEFAULT_PREFIX]) + ->willReturn('foo'); $collection->expects($this->at(2)) - ->method('findOne') - ->with(['v' => 'found2']) - ->willReturn(null); + ->method('findOne') + ->with(['v' => 'found2', 'prefix' => Configuration::DEFAULT_PREFIX]) + ->willReturn(null); $this->assertTrue($this->configuration->hasVersionMigrated($version1)); $this->assertFalse($this->configuration->hasVersionMigrated($version2)); @@ -250,16 +264,17 @@ public function testValidateThrowsConfigurationValidationException() public function testGetUnavailableMigratedVersions() { + /** @var ConfigurationInterface|MockObject $configuration */ $configuration = $this->getMockBuilder('AntiMattr\MongoDB\Migrations\Configuration\Configuration') - ->disableOriginalConstructor() - ->setMethods(['getMigratedVersions', 'getAvailableVersions']) - ->getMock(); + ->disableOriginalConstructor() + ->setMethods(['getMigratedVersions', 'getAvailableVersions']) + ->getMock(); $configuration->expects($this->once()) - ->method('getMigratedVersions') - ->willReturn(['1', '2']); + ->method('getMigratedVersions') + ->willReturn(['1', '2']); $configuration->expects($this->once()) - ->method('getAvailableVersions') - ->willReturn(['2', '3']); + ->method('getAvailableVersions') + ->willReturn(['2', '3']); $this->assertEquals(['1'], $configuration->getUnavailableMigratedVersions()); } @@ -267,7 +282,8 @@ public function testGetUnavailableMigratedVersions() public function testValidate() { $this->prepareValidConfiguration(); - self::assertNull($this->configuration->validate()); + $this->configuration->validate(); + self::assertTrue(true); // All checks is passes, no exceptions is thrown. } /** @@ -282,24 +298,24 @@ public function testDuplicateInGetMigratedTimestampThrowsException() $database = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($database); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($database); $database->expects($this->once()) - ->method('selectCollection') - ->with('antimattr_migration_versions_test') - ->willReturn($collection); + ->method('selectCollection') + ->with('antimattr_migration_versions_test') + ->willReturn($collection); $cursor = $this->createMock('Doctrine\MongoDB\Cursor'); $collection->expects($this->once()) - ->method('find') - ->willReturn($cursor); + ->method('find') + ->willReturn($cursor); $cursor->expects($this->exactly(2)) - ->method('count') - ->willReturn(2); + ->method('count') + ->willReturn(2); $this->configuration->getMigratedTimestamp('1'); } @@ -312,35 +328,35 @@ public function testGetMigratedTimestamp() $database = $this->createMock('Doctrine\MongoDB\Database'); $this->connection->expects($this->once()) - ->method('selectDatabase') - ->with('test_antimattr_migrations') - ->willReturn($database); + ->method('selectDatabase') + ->with('test_antimattr_migrations') + ->willReturn($database); $database->expects($this->once()) - ->method('selectCollection') - ->with('antimattr_migration_versions_test') - ->willReturn($collection); + ->method('selectCollection') + ->with('antimattr_migration_versions_test') + ->willReturn($collection); $cursor = $this->createMock('Doctrine\MongoDB\Cursor'); $collection->expects($this->once()) - ->method('find') - ->willReturn($cursor); + ->method('find') + ->willReturn($cursor); $cursor->expects($this->exactly(2)) - ->method('count') - ->willReturn(1); + ->method('count') + ->willReturn(1); $cursor->expects($this->once()) - ->method('getNext') - ->willReturn(['t' => new \DateTime()]); + ->method('getNext') + ->willReturn(['t' => new \DateTime()]); - $this->assertTrue(is_numeric($this->configuration->getMigratedTimestamp('1'))); + $this->assertTrue(\is_numeric($this->configuration->getMigratedTimestamp('1'))); } private function prepareValidConfiguration() { - $directory = dirname(__DIR__) . '/Resources/Migrations/'; + $directory = \dirname(__DIR__) . '/Resources/Migrations/'; $this->configuration->setMigrationsDatabaseName('test_antimattr_migrations'); $this->configuration->setMigrationsDirectory($directory); $this->configuration->setMigrationsNamespace('Example\Migrations\TestAntiMattr\MongoDB'); diff --git a/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.xml b/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.xml index e92bfdd..e89ecd7 100644 --- a/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.xml +++ b/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.xml @@ -5,10 +5,10 @@ http://doctrine-project.org/schemas/migrations/configuration.xsd"> AntiMattr Sandbox Migrations - AntiMattrMigrationsTest + Example\Migrations\TestAntiMattr\MongoDB - /path/to/migrations/classes/AntiMattrMigrations - /path/to/migrations/script_directory + ./tests/AntiMattr/Tests/MongoDB/Migrations/Resources/Migrations + ./bin diff --git a/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.yml b/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.yml index 019dbc6..750c040 100644 --- a/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.yml +++ b/tests/AntiMattr/Tests/MongoDB/Migrations/Resources/fixtures/config.yml @@ -1,7 +1,7 @@ --- name: AntiMattr Sandbox Migrations -migrations_namespace: AntiMattrMigrationsTest +migrations_namespace: Example\Migrations\TestAntiMattr\MongoDB database: test_antimattr_migrations collection_name: antimattr_migration_versions_test -migrations_directory: /path/to/migrations/classes/AntiMattrMigrations -migrations_script_directory: /path/to/migrations/script_directory +migrations_directory: ./tests/AntiMattr/Tests/MongoDB/Migrations/Resources/Migrations +migrations_script_directory: ./bin diff --git a/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/MigrateCommandTest.php b/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/MigrateCommandTest.php index 7eba2f5..d7ba9a5 100644 --- a/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/MigrateCommandTest.php +++ b/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/MigrateCommandTest.php @@ -1,20 +1,26 @@ createMock('AntiMattr\MongoDB\Migrations\Configuration\Configuration'); - $executedVersion = $this->createMock('AntiMattr\MongoDB\Migrations\Version'); + /** @var Migration|MockObject $migration */ $migration = $this->createMock('AntiMattr\MongoDB\Migrations\Migration'); + /** @var QuestionHelper|MockObject $question */ $question = $this->createMock('Symfony\Component\Console\Helper\QuestionHelper'); // Variables and Objects @@ -42,7 +50,7 @@ public function testExecuteWithExectedUnavailableVersionAndInteraction() ] ); $interactive = true; - $executedVersions = [$executedVersion]; + $executedVersions = [$numVersion]; $availableVersions = []; $application = new Application(); $helperSet = new HelperSet( @@ -60,30 +68,26 @@ public function testExecuteWithExectedUnavailableVersionAndInteraction() // Expectations $configuration->expects($this->once()) - ->method('getMigratedVersions') - ->will( - $this->returnValue($executedVersions) - ) - ; + ->method('getMigratedVersions') + ->will( + $this->returnValue($executedVersions) + ); $configuration->expects($this->once()) - ->method('getAvailableVersions') - ->will( - $this->returnValue($availableVersions) - ) - ; + ->method('getAvailableVersions') + ->will( + $this->returnValue($availableVersions) + ); $question->expects($this->exactly(2)) - ->method('ask') - ->will( - $this->returnValue(true) - ) - ; + ->method('ask') + ->will( + $this->returnValue(true) + ); $migration->expects($this->once()) - ->method('migrate') - ->with($numVersion) - ; + ->method('migrate') + ->with($numVersion); // Run command, run. $this->command->run( @@ -95,8 +99,11 @@ public function testExecuteWithExectedUnavailableVersionAndInteraction() public function testExecute() { // Mocks + /** @var ConfigurationInterface|MockObject $configuration */ $configuration = $this->createMock('AntiMattr\MongoDB\Migrations\Configuration\Configuration'); + /** @var Version|MockObject $availableVersion */ $availableVersion = $this->createMock('AntiMattr\MongoDB\Migrations\Version'); + /** @var Migration|MockObject $migration */ $migration = $this->createMock('AntiMattr\MongoDB\Migrations\Migration'); // Variables and Objects @@ -117,23 +124,20 @@ public function testExecute() // Expectations $configuration->expects($this->once()) - ->method('getMigratedVersions') - ->will( - $this->returnValue([]) - ) - ; + ->method('getMigratedVersions') + ->will( + $this->returnValue([]) + ); $configuration->expects($this->once()) - ->method('getAvailableVersions') - ->will( - $this->returnValue($availableVersions) - ) - ; + ->method('getAvailableVersions') + ->will( + $this->returnValue($availableVersions) + ); $migration->expects($this->once()) - ->method('migrate') - ->with($numVersion) - ; + ->method('migrate') + ->with($numVersion); // Run command, run. $this->command->run( @@ -144,28 +148,27 @@ public function testExecute() public function testDefaultInteractionWillCancelMigration() { + /** @var Migration|MockObject $migration */ $migration = $this->createMock(Migration::class); $numVersion = '000123456789'; // We do not expect this to be called $migration->expects($this->never()) - ->method('migrate') - ->with($numVersion) - ; + ->method('migrate') + ->with($numVersion); $this->command->setMigration($migration); + /** @var ConfigurationInterface|MockObject $configuration */ $configuration = $this->createMock(Configuration::class); $configuration->expects($this->once()) - ->method('getAvailableVersions') - ->willReturn([]) - ; + ->method('getAvailableVersions') + ->willReturn([]); + $this->command->setMigrationConfiguration($configuration); - $executedVersion = $this->createMock(Version::class); $configuration->expects($this->once()) - ->method('getMigratedVersions') - ->willReturn([$executedVersion]) - ; + ->method('getMigratedVersions') + ->willReturn([$numVersion]); $application = new Application(); $application->setAutoExit(false); @@ -180,28 +183,26 @@ public function testDefaultInteractionWillCancelMigration() public function testDefaultSecondInteractionWillCancelMigration() { + /** @var Migration|MockObject $migration */ $migration = $this->createMock(Migration::class); $numVersion = '000123456789'; // We do not expect this to be called $migration->expects($this->never()) - ->method('migrate') - ->with($numVersion) - ; + ->method('migrate') + ->with($numVersion); $this->command->setMigration($migration); + /** @var ConfigurationInterface|MockObject $configuration */ $configuration = $this->createMock(Configuration::class); $configuration->expects($this->once()) - ->method('getAvailableVersions') - ->willReturn([]) - ; + ->method('getAvailableVersions') + ->willReturn([]); $this->command->setMigrationConfiguration($configuration); - $executedVersion = $this->createMock(Version::class); $configuration->expects($this->once()) - ->method('getMigratedVersions') - ->willReturn([$executedVersion]) - ; + ->method('getMigratedVersions') + ->willReturn([$numVersion]); $application = new Application(); $application->setAutoExit(false); @@ -229,7 +230,7 @@ protected function createMigration(Configuration $configuration) return $this->migration; } - protected function outputHeader(Configuration $configuration, OutputInterface $output) + protected function outputHeader(Configuration $configuration, OutputInterface $output): void { return; } diff --git a/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/StatusCommandTest.php b/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/StatusCommandTest.php index 5a6582a..ac92c67 100644 --- a/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/StatusCommandTest.php +++ b/tests/AntiMattr/Tests/MongoDB/Migrations/Tools/Console/Command/StatusCommandTest.php @@ -1,11 +1,15 @@ migration = $this->createMock('AntiMattr\MongoDB\Migrations\AbstractMigration'); $this->version = $this->createMock('AntiMattr\MongoDB\Migrations\Version'); $this->version->expects($this->any()) - ->method('getMigration') - ->will($this->returnValue($this->migration)); + ->method('getMigration') + ->will($this->returnValue($this->migration)); $this->version2 = $this->createMock('AntiMattr\MongoDB\Migrations\Version'); $this->version2->expects($this->any()) - ->method('getMigration') - ->will($this->returnValue($this->migration)); + ->method('getMigration') + ->will($this->returnValue($this->migration)); $this->command->setMigrationConfiguration($this->config); } @@ -60,8 +72,6 @@ public function testExecuteWithoutShowingVersions() $migrationsDirectory = 'migrations-directory'; $currentVersion = 'abcdefghijk'; $latestVersion = '1234567890'; - $executedMigrations = []; - $availableMigrations = []; $numExecutedMigrations = 0; $numExecutedUnavailableMigrations = 0; $numAvailableMigrations = 0; @@ -69,148 +79,133 @@ public function testExecuteWithoutShowingVersions() // Expectations $this->config->expects($this->once()) - ->method('getDetailsMap') - ->will( - $this->returnValue( - [ - 'name' => $configName, - 'database_driver' => $databaseDriver, - 'migrations_database_name' => $migrationsDatabaseName, - 'migrations_collection_name' => $migrationsCollectionName, - 'migrations_namespace' => $migrationsNamespace, - 'migrations_directory' => $migrationsDirectory, - 'current_version' => $currentVersion, - 'latest_version' => $latestVersion, - 'num_executed_migrations' => $numExecutedMigrations, - 'num_executed_unavailable_migrations' => $numExecutedUnavailableMigrations, - 'num_available_migrations' => $numAvailableMigrations, - 'num_new_migrations' => $numNewMigrations, - ] - ) - ) - ; + ->method('getDetailsMap') + ->will( + $this->returnValue( + [ + 'name' => $configName, + 'database_driver' => $databaseDriver, + 'migrations_database_name' => $migrationsDatabaseName, + 'migrations_collection_name' => $migrationsCollectionName, + 'migrations_namespace' => $migrationsNamespace, + 'migrations_directory' => $migrationsDirectory, + 'current_version' => $currentVersion, + 'latest_version' => $latestVersion, + 'num_executed_migrations' => $numExecutedMigrations, + 'num_executed_unavailable_migrations' => $numExecutedUnavailableMigrations, + 'num_available_migrations' => $numAvailableMigrations, + 'num_new_migrations' => $numNewMigrations, + ] + ) + ); $this->output->expects($this->at(0)) - ->method('writeln') - ->with( - "\n == Configuration\n" - ) - ; + ->method('writeln') + ->with( + "\n == Configuration\n" + ); $this->output->expects($this->at(1)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Name', - $configName - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Name', + $configName + ) + ); $this->output->expects($this->at(2)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Database Driver', - 'MongoDB' - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Database Driver', + 'MongoDB' + ) + ); $this->output->expects($this->at(3)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Database Name', - $migrationsDatabaseName - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Database Name', + $migrationsDatabaseName + ) + ); $this->output->expects($this->at(4)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Configuration Source', - 'manually configured' - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Configuration Source', + 'manually configured' + ) + ); $this->output->expects($this->at(5)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Version Collection Name', - $migrationsCollectionName - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Version Collection Name', + $migrationsCollectionName + ) + ); $this->output->expects($this->at(6)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Migrations Namespace', - $migrationsNamespace - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Migrations Namespace', + $migrationsNamespace + ) + ); $this->output->expects($this->at(7)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Migrations Directory', - $migrationsDirectory - ) - ) - ; - $this->output->expects($this->at(8)) // current version formatted - ->method('writeln') - ; - $this->output->expects($this->at(9)) // latest version formatted - ->method('writeln') - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Migrations Directory', + $migrationsDirectory + ) + ); + $this->output->expects($this->at(8))// current version formatted + ->method('writeln'); + $this->output->expects($this->at(9))// latest version formatted + ->method('writeln'); $this->output->expects($this->at(10)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Executed Migrations', - $numExecutedMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Executed Migrations', + $numExecutedMigrations + ) + ); $this->output->expects($this->at(11)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Executed Unavailable Migrations', - $numExecutedUnavailableMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Executed Unavailable Migrations', + $numExecutedUnavailableMigrations + ) + ); $this->output->expects($this->at(12)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Available Migrations', - $numAvailableMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Available Migrations', + $numAvailableMigrations + ) + ); $this->output->expects($this->at(13)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'New Migrations', - $numNewMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'New Migrations', + $numNewMigrations + ) + ); // Run command, run. $this->command->run( @@ -242,7 +237,6 @@ public function testExecuteWithShowingVersions() $numNewMigrations = 1; $notMigratedVersion = '20140822185743'; $migratedVersion = '20140822185745'; - $migrationDescription = 'drop all collections'; $unavailableMigratedVersion = '20140822185744'; // Expectations @@ -251,208 +245,187 @@ public function testExecuteWithShowingVersions() ->will($this->returnValue($this->outputFormatter)); $this->version->expects($this->exactly(2)) - ->method('getVersion') - ->will($this->returnValue($notMigratedVersion)); + ->method('getVersion') + ->will($this->returnValue($notMigratedVersion)); $this->version2->expects($this->exactly(3)) - ->method('getVersion') - ->will($this->returnValue($migratedVersion)); + ->method('getVersion') + ->will($this->returnValue($migratedVersion)); $this->migration ->method('getDescription') ->will($this->returnValue('drop all')); $this->config->expects($this->once()) - ->method('getDetailsMap') - ->will( - $this->returnValue( - [ - 'name' => $configName, - 'database_driver' => $databaseDriver, - 'migrations_database_name' => $migrationsDatabaseName, - 'migrations_collection_name' => $migrationsCollectionName, - 'migrations_namespace' => $migrationsNamespace, - 'migrations_directory' => $migrationsDirectory, - 'current_version' => $currentVersion, - 'latest_version' => $latestVersion, - 'num_executed_migrations' => $numExecutedMigrations, - 'num_executed_unavailable_migrations' => $numExecutedUnavailableMigrations, - 'num_available_migrations' => $numAvailableMigrations, - 'num_new_migrations' => $numNewMigrations, - ] - ) - ) - ; + ->method('getDetailsMap') + ->will( + $this->returnValue( + [ + 'name' => $configName, + 'database_driver' => $databaseDriver, + 'migrations_database_name' => $migrationsDatabaseName, + 'migrations_collection_name' => $migrationsCollectionName, + 'migrations_namespace' => $migrationsNamespace, + 'migrations_directory' => $migrationsDirectory, + 'current_version' => $currentVersion, + 'latest_version' => $latestVersion, + 'num_executed_migrations' => $numExecutedMigrations, + 'num_executed_unavailable_migrations' => $numExecutedUnavailableMigrations, + 'num_available_migrations' => $numAvailableMigrations, + 'num_new_migrations' => $numNewMigrations, + ] + ) + ); $this->config->expects($this->once()) - ->method('getUnavailableMigratedVersions') - ->will( - $this->returnValue( - [$unavailableMigratedVersion] - ) - ) - ; + ->method('getUnavailableMigratedVersions') + ->will( + $this->returnValue( + [$unavailableMigratedVersion] + ) + ); $this->config->expects($this->once()) - ->method('getMigrations') - ->will( - $this->returnValue( - [$this->version, $this->version2] - ) - ) - ; + ->method('getMigrations') + ->will( + $this->returnValue( + [$this->version, $this->version2] + ) + ); $this->config->expects($this->once()) - ->method('getMigratedVersions') - ->will( - $this->returnValue( - [$unavailableMigratedVersion, $migratedVersion] - ) - ) - ; + ->method('getMigratedVersions') + ->will( + $this->returnValue( + [$unavailableMigratedVersion, $migratedVersion] + ) + ); $this->output->expects($this->at(0)) - ->method('writeln') - ->with( - "\n == Configuration\n" - ) - ; + ->method('writeln') + ->with( + "\n == Configuration\n" + ); $this->output->expects($this->at(1)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Name', - $configName - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Name', + $configName + ) + ); $this->output->expects($this->at(2)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Database Driver', - 'MongoDB' - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Database Driver', + 'MongoDB' + ) + ); $this->output->expects($this->at(3)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Database Name', - $migrationsDatabaseName - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Database Name', + $migrationsDatabaseName + ) + ); $this->output->expects($this->at(4)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Configuration Source', - 'manually configured' - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Configuration Source', + 'manually configured' + ) + ); $this->output->expects($this->at(5)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Version Collection Name', - $migrationsCollectionName - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Version Collection Name', + $migrationsCollectionName + ) + ); $this->output->expects($this->at(6)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Migrations Namespace', - $migrationsNamespace - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Migrations Namespace', + $migrationsNamespace + ) + ); $this->output->expects($this->at(7)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Migrations Directory', - $migrationsDirectory - ) - ) - ; - $this->output->expects($this->at(8)) // current version formatted - ->method('writeln') - ; - $this->output->expects($this->at(9)) // latest version formatted - ->method('writeln') - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Migrations Directory', + $migrationsDirectory + ) + ); + $this->output->expects($this->at(8))// current version formatted + ->method('writeln'); + $this->output->expects($this->at(9))// latest version formatted + ->method('writeln'); $this->output->expects($this->at(10)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Executed Migrations', - $numExecutedMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Executed Migrations', + $numExecutedMigrations + ) + ); $this->output->expects($this->at(11)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Executed Unavailable Migrations', - $numExecutedUnavailableMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Executed Unavailable Migrations', + $numExecutedUnavailableMigrations + ) + ); $this->output->expects($this->at(12)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'Available Migrations', - $numAvailableMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'Available Migrations', + $numAvailableMigrations + ) + ); $this->output->expects($this->at(13)) - ->method('writeln') - ->with( - sprintf( - '%s::%s', - 'New Migrations', - $numNewMigrations - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + '%s::%s', + 'New Migrations', + $numNewMigrations + ) + ); $this->output->expects($this->at(14)) - ->method('writeln') - ->with("\n == Available Migration Versions\n") - ; + ->method('writeln') + ->with("\n == Available Migration Versions\n"); $this->output->expects($this->at(39)) - ->method('writeln') - ->with("\n == Previously Executed Unavailable Migration Versions\n") - ; + ->method('writeln') + ->with("\n == Previously Executed Unavailable Migration Versions\n"); $this->output->expects($this->at(40)) - ->method('writeln') - ->with( - sprintf( - ' >> %s (%s)', - \DateTime::createFromFormat('YmdHis', $unavailableMigratedVersion)->format('Y-m-d H:i:s'), - $unavailableMigratedVersion - ) - ) - ; + ->method('writeln') + ->with( + \sprintf( + ' >> %s (%s)', + \DateTime::createFromFormat('YmdHis', $unavailableMigratedVersion)->format('Y-m-d H:i:s'), + $unavailableMigratedVersion + ) + ); // Run command, run. $this->command->run( @@ -466,12 +439,12 @@ class StatusCommandStub extends StatusCommand { private $configuration; - public function setMigrationConfiguration(Configuration $configuration) + public function setMigrationConfiguration(ConfigurationInterface $configuration): void { $this->configuration = $configuration; } - public function getMigrationConfiguration(InputInterface $input, OutputInterface $output): Configuration + public function getMigrationConfiguration(InputInterface $input, OutputInterface $output): ConfigurationInterface { return $this->configuration; } diff --git a/tests/AntiMattr/Tests/MongoDB/Migrations/VersionTest.php b/tests/AntiMattr/Tests/MongoDB/Migrations/VersionTest.php index 7fdd27e..18104ba 100644 --- a/tests/AntiMattr/Tests/MongoDB/Migrations/VersionTest.php +++ b/tests/AntiMattr/Tests/MongoDB/Migrations/VersionTest.php @@ -1,9 +1,16 @@ versionName = '20140908000000'; $this->configuration->expects($this->once()) - ->method('getOutputWriter') - ->will($this->returnValue($this->outputWriter)); + ->method('getOutputWriter') + ->will($this->returnValue($this->outputWriter)); $this->configuration->expects($this->once()) - ->method('getConnection') - ->will($this->returnValue($this->connection)); + ->method('getConnection') + ->will($this->returnValue($this->connection)); $this->configuration->expects($this->once()) - ->method('getDatabase') - ->will($this->returnValue($this->db)); - - $this->version = new VersionStub($this->configuration, $this->versionName, $this->className); + ->method('getDatabase') + ->will($this->returnValue($this->db)); + + $this->version = new VersionStub( + $this->configuration, + Configuration::DEFAULT_PREFIX, + $this->versionName, + $this->className + ); $this->version->setStatistics($this->statistics); $this->version->setMigration($this->migration); } @@ -51,49 +68,51 @@ public function testConstructor() $this->assertSame($this->configuration, $this->version->getConfiguration()); $this->assertSame(Version::STATE_NONE, $this->version->getState()); $this->assertSame($this->versionName, $this->version->getVersion()); - $this->assertEquals($this->versionName, (string) $this->version); + $this->assertEquals($this->versionName, (string)$this->version); $this->assertNotNull($this->version->getMigration()); } public function testAnalyzeThrowsException() { + /** @var Collection|MockObject $collection */ $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->statistics->expects($this->once()) - ->method('setCollection') - ->with($collection); + ->method('setCollection') + ->with($collection); $collection->expects($this->once()) - ->method('getName') - ->will($this->returnValue('test_name')); + ->method('getName') + ->will($this->returnValue('test_name')); $expectedException = new \RuntimeException(); $this->statistics->expects($this->once()) - ->method('updateBefore') - ->will($this->throwException($expectedException)); + ->method('updateBefore') + ->will($this->throwException($expectedException)); $this->outputWriter->expects($this->once()) - ->method('write'); + ->method('write'); $this->version->analyze($collection); } public function testAnalyze() { + /** @var Collection|MockObject $collection */ $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->statistics->expects($this->once()) - ->method('setCollection') - ->with($collection); + ->method('setCollection') + ->with($collection); $collection->expects($this->once()) - ->method('getName') - ->will($this->returnValue('test_name')); + ->method('getName') + ->will($this->returnValue('test_name')); $this->statistics->expects($this->once()) - ->method('updateBefore'); + ->method('updateBefore'); $this->outputWriter->expects($this->never()) - ->method('write'); + ->method('write'); $this->version->analyze($collection); } @@ -105,20 +124,21 @@ public function testMarkMigrated() $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->configuration->expects($this->once()) - ->method('createMigrationCollection'); + ->method('createMigrationCollection'); $this->configuration->expects($this->once()) - ->method('getCollection') - ->will($this->returnValue($collection)); + ->method('getCollection') + ->will($this->returnValue($collection)); $insert = [ 'v' => $this->versionName, 't' => $timestamp, + 'prefix' => Configuration::DEFAULT_PREFIX, ]; $collection->expects($this->once()) - ->method('insert') - ->with($insert); + ->method('insert') + ->with($insert); $this->version->markMigrated(); } @@ -130,24 +150,27 @@ public function testMarkMigratedWithReplay() $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->configuration->expects($this->once()) - ->method('createMigrationCollection'); + ->method('createMigrationCollection'); $this->configuration->expects($this->once()) - ->method('getCollection') - ->will($this->returnValue($collection)); + ->method('getCollection') + ->will($this->returnValue($collection)); $query = [ 'v' => $this->versionName, + 'prefix' => Configuration::DEFAULT_PREFIX, + ]; $update = [ 'v' => $this->versionName, 't' => $timestamp, + 'prefix' => Configuration::DEFAULT_PREFIX, ]; $collection->expects($this->once()) - ->method('update') - ->with($query, $update); + ->method('update') + ->with($query, $update); $replay = true; $this->version->markMigrated($replay); @@ -160,38 +183,40 @@ public function testMarkNotMigrated() $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->configuration->expects($this->once()) - ->method('createMigrationCollection'); + ->method('createMigrationCollection'); $this->configuration->expects($this->once()) - ->method('getCollection') - ->will($this->returnValue($collection)); + ->method('getCollection') + ->will($this->returnValue($collection)); $remove = [ 'v' => $this->versionName, + 'prefix' => Configuration::DEFAULT_PREFIX, ]; $collection->expects($this->once()) - ->method('remove') - ->with($remove); + ->method('remove') + ->with($remove); $this->version->markNotMigrated(); } public function testUpdateStatisticsAfterThrowsException() { + /** @var Collection|MockObject $collection */ $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->statistics->expects($this->once()) - ->method('setCollection') - ->with($collection); + ->method('setCollection') + ->with($collection); $expectedException = new \RuntimeException(); $this->statistics->expects($this->once()) - ->method('updateAfter') - ->will($this->throwException($expectedException)); + ->method('updateAfter') + ->will($this->throwException($expectedException)); $this->outputWriter->expects($this->once()) - ->method('write'); + ->method('write'); $this->version->analyze($collection); $this->version->doUpdateStatisticsAfter(); @@ -199,24 +224,25 @@ public function testUpdateStatisticsAfterThrowsException() public function testUpdateStatisticsAfter() { + /** @var Collection|MockObject $collection */ $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->statistics->expects($this->once()) - ->method('setCollection') - ->with($collection); + ->method('setCollection') + ->with($collection); $this->statistics->expects($this->once()) - ->method('getCollection') - ->will($this->returnValue($collection)); + ->method('getCollection') + ->will($this->returnValue($collection)); $collection->expects($this->exactly(2)) - ->method('getName') - ->will($this->returnValue('test_name')); + ->method('getName') + ->will($this->returnValue('test_name')); $this->statistics->expects($this->once()) - ->method('updateAfter'); + ->method('updateAfter'); $this->outputWriter->expects($this->never()) - ->method('write'); + ->method('write'); $this->version->analyze($collection); $this->version->doUpdateStatisticsAfter(); @@ -225,8 +251,8 @@ public function testUpdateStatisticsAfter() public function testIsMigrated() { $this->configuration->expects($this->once()) - ->method('hasVersionMigrated') - ->with($this->version); + ->method('hasVersionMigrated') + ->with($this->version); $this->version->isMigrated(); } @@ -243,9 +269,9 @@ public function testExecuteDownWithReplayThrowsException() // These methods will not be called $this->migration->expects($this->never())->method('down'); $this->configuration->expects($this->never()) - ->method('createMigrationCollection'); + ->method('createMigrationCollection'); $this->configuration->expects($this->never()) - ->method('getCollection'); + ->method('getCollection'); $replay = true; $this->version->execute('down', $replay); @@ -259,16 +285,16 @@ public function testExecuteThrowsSkipException($direction) $expectedException = new \AntiMattr\MongoDB\Migrations\Exception\SkipException(); $this->migration->expects($this->once()) - ->method($direction) - ->will($this->throwException($expectedException)); + ->method($direction) + ->will($this->throwException($expectedException)); $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->configuration->expects($this->once()) - ->method('createMigrationCollection'); + ->method('createMigrationCollection'); $this->configuration->expects($this->once()) - ->method('getCollection') - ->will($this->returnValue($collection)); + ->method('getCollection') + ->will($this->returnValue($collection)); $this->version->execute($direction); } @@ -279,21 +305,21 @@ public function testExecuteThrowsSkipException($direction) public function testExecute($direction) { $this->migration->expects($this->once()) - ->method('pre' . $direction); + ->method('pre' . $direction); $this->migration->expects($this->once()) - ->method($direction); + ->method($direction); $this->migration->expects($this->once()) - ->method('post' . $direction); + ->method('post' . $direction); $collection = $this->createMock('Doctrine\MongoDB\Collection'); $this->configuration->expects($this->once()) - ->method('createMigrationCollection'); + ->method('createMigrationCollection'); $this->configuration->expects($this->once()) - ->method('getCollection') - ->will($this->returnValue($collection)); + ->method('getCollection') + ->will($this->returnValue($collection)); $this->version->execute($direction); }