diff --git a/scripts/Phalcon/Builder/Scaffold.php b/scripts/Phalcon/Builder/Scaffold.php index 9813a2c1b..ce6da020b 100644 --- a/scripts/Phalcon/Builder/Scaffold.php +++ b/scripts/Phalcon/Builder/Scaffold.php @@ -280,9 +280,9 @@ private function _captureFilterInput($var, $fields, $useGetSetters, $identityFie $code .= '$' . Utils::lowerCamelizeWithDelimiter($var, '-', true) . '->'; if ($useGetSetters) { - $code .= 'set' . Text::camelize($field) . '(' . $fieldCode . ')'; + $code .= 'set' . Utils::lowerCamelizeWithDelimiter($field, '_', true) . '(' . $fieldCode . ')'; } else { - $code .= Text::camelize($field, '-') . ' = ' . $fieldCode; + $code .= Utils::lowerCamelizeWithDelimiter($field, '-_', true) . ' = ' . $fieldCode; } $code .= ';' . PHP_EOL . "\t\t"; diff --git a/scripts/Phalcon/Commands/Builtin/Migration.php b/scripts/Phalcon/Commands/Builtin/Migration.php index 4bb8a5f8e..9bb46a6fd 100644 --- a/scripts/Phalcon/Commands/Builtin/Migration.php +++ b/scripts/Phalcon/Commands/Builtin/Migration.php @@ -4,7 +4,7 @@ +------------------------------------------------------------------------+ | Phalcon Developer Tools | +------------------------------------------------------------------------+ - | Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) | + | Copyright (c) 2011-2017 Phalcon Team (https://www.phalconphp.com) | +------------------------------------------------------------------------+ | This source file is subject to the New BSD License that is bundled | | with this package in the file LICENSE.txt. | @@ -47,13 +47,15 @@ public function getPossibleParams() 'config=s' => 'Configuration file', 'migrations=s' => 'Migrations directory', 'directory=s' => 'Directory where the project was created', - 'table=s' => 'Table to migrate. Default: all', + 'table=s' => 'Table to migrate. Table name or table prefix with asterisk. Default: all', 'version=s' => 'Version to migrate', 'descr=s' => 'Migration description (used for timestamp based migration)', 'data=s' => 'Export data [always|oncreate] (Import data when run migration)', 'force' => 'Forces to overwrite existing migrations', 'ts-based' => 'Timestamp based migration version', 'log-in-db' => 'Keep migrations log in the database table rather than in file', + 'dry' => 'Attempt requested operation without making changes to system (Generating only)', + 'verbose' => 'Output of debugging information during operation (Running only)', 'no-auto-increment' => 'Disable auto increment (Generating only)', 'help' => 'Shows this help [optional]', ]; @@ -111,23 +113,21 @@ public function run(array $parameters) } $tableName = $this->isReceivedOption('table') ? $this->getOption('table') : '@'; - $descr = $this->getOption('descr'); - $exportData = $this->getOption('data'); $action = $this->getOption(['action', 1]); - $version = $this->getOption('version'); switch ($action) { case 'generate': Migrations::generate([ 'directory' => $path, 'tableName' => $tableName, - 'exportData' => $exportData, + 'exportData' => $this->getOption('data'), 'migrationsDir' => $migrationsDir, - 'version' => $version, + 'version' => $this->getOption('version'), 'force' => $this->isReceivedOption('force'), 'noAutoIncrement' => $this->isReceivedOption('no-auto-increment'), 'config' => $config, - 'descr' => $descr, + 'descr' => $this->getOption('descr'), + 'verbose' => $this->isReceivedOption('dry'), ]); break; case 'run': @@ -138,8 +138,9 @@ public function run(array $parameters) 'force' => $this->isReceivedOption('force'), 'tsBased' => $migrationsTsBased, 'config' => $config, - 'version' => $version, + 'version' => $this->getOption('version'), 'migrationsInDb' => $migrationsInDb, + 'verbose' => $this->isReceivedOption('verbose'), ]); break; case 'list': @@ -150,7 +151,7 @@ public function run(array $parameters) 'force' => $this->isReceivedOption('force'), 'tsBased' => $migrationsTsBased, 'config' => $config, - 'version' => $version, + 'version' => $this->getOption('version'), 'migrationsInDb' => $migrationsInDb, ]); break; diff --git a/scripts/Phalcon/Commands/Command.php b/scripts/Phalcon/Commands/Command.php index 45b259a17..6f63af53e 100644 --- a/scripts/Phalcon/Commands/Command.php +++ b/scripts/Phalcon/Commands/Command.php @@ -4,7 +4,7 @@ +------------------------------------------------------------------------+ | Phalcon Developer Tools | +------------------------------------------------------------------------+ - | Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) | + | Copyright (c) 2011-2017 Phalcon Team (https://www.phalconphp.com) | +------------------------------------------------------------------------+ | This source file is subject to the New BSD License that is bundled | | with this package in the file LICENSE.txt. | @@ -135,7 +135,7 @@ protected function getConfig($path) { foreach (['app/config/', 'config/'] as $configPath) { foreach (['ini', 'php', 'json', 'yaml', 'yml'] as $extension) { - if (file_exists($path . $configPath . "/config." . $extension)) { + if (file_exists($path . $configPath . "config." . $extension)) { return $this->loadConfig($path . $configPath . "/config." . $extension); } } diff --git a/scripts/Phalcon/Commands/CommandsListener.php b/scripts/Phalcon/Commands/CommandsListener.php index 0048834e8..1d1345b35 100644 --- a/scripts/Phalcon/Commands/CommandsListener.php +++ b/scripts/Phalcon/Commands/CommandsListener.php @@ -54,6 +54,7 @@ public function beforeCommand(Event $event, Command $command) if ($command->canBeExternal() == false) { $path = $command->getOption('directory'); + if ($path) $path = realpath($path) . DIRECTORY_SEPARATOR; if (!file_exists($path.'.phalcon') || !is_dir($path.'.phalcon')) { throw new DotPhalconMissingException(); } diff --git a/scripts/Phalcon/Console/OptionParserTrait.php b/scripts/Phalcon/Console/OptionParserTrait.php new file mode 100644 index 000000000..7f7d62bcd --- /dev/null +++ b/scripts/Phalcon/Console/OptionParserTrait.php @@ -0,0 +1,49 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Console; + +/** + * \Phalcon\Utils\OptionParserTrait + * + * Parsing CLI options + * + * @package Phalcon\Utils + * @copyright Copyright (c) 2011-2017 Phalcon Team (team@phalconphp.com) + * @license New BSD License + */ +trait OptionParserTrait +{ + /** + * Get prefix from the option + * + * @param string $prefix + * @param mixed $prefixEnd + * + * @return mixed + */ + public function getPrefixOption($prefix, $prefixEnd = '*') + { + if (substr($prefix, -1) != $prefixEnd) { + return ''; + } + + return substr($prefix, 0, -1); + } +} diff --git a/scripts/Phalcon/Console/OptionStack.php b/scripts/Phalcon/Console/OptionStack.php new file mode 100644 index 000000000..e22be0e5a --- /dev/null +++ b/scripts/Phalcon/Console/OptionStack.php @@ -0,0 +1,146 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Console; + +use Phalcon\Console\OptionParserTrait; + +/** + * Phalcon\Console\OptionStack + * + * CLI options + * + * @package Phalcon\Console; + * @copyright Copyright (c) 2011-2017 Phalcon Team (team@phalconphp.com) + * @license New BSD License + */ +class OptionStack +{ + use OptionParserTrait; + + /** + * Parameters received by the script. + * @var array + */ + protected $options = []; + + /** + * Set recieved options + * + * @param array $options + */ + public function setOptions(array $options) + { + $this->options = array_merge($this->options, $options); + } + + /** + * Add option to array + * + * @param mixed $key + * @param mixed $option + * @param mixed $defaultValue + */ + public function setOption($key, $option, $defaultValue = '') + { + if (!empty($option)) { + $this->options[$key] = $option; + + return; + } + + $this->options[$key] = $defaultValue; + } + + /** + * Set option if value isn't exist + * + * @param string $key + * @param mixed $defaultValue + */ + public function setDefaultOption($key, $defaultValue) + { + if (!isset($this->options[$key])) { + $this->options[$key] = $defaultValue; + } + } + + /** + * Get recieved options + * + * @return mixed + */ + public function getOptions() + { + return $this->options; + } + + /** + * Get option + * @param string $key + * + * @return mixed + */ + public function getOption($key) + { + if (!isset($this->options[$key])) { + return ''; + } + + return $this->options[$key]; + } + + /** + * Get option if existence or get default option + * + * @param string $key + * @param mixed $defaultOption + * + * @return mixed + */ + public function getValidOption($key, $defaultOption = '') + { + if (isset($this->options[$key])) { + return $this->options[$key]; + } + + return $defaultOption; + } + + /** + * Count options + * + * @return integer + */ + public function countOptions() + { + return count($this->options); + } + + /** + * Indicates whether the script was a particular option. + * + * @param string $key + * @return boolean + */ + public function isReceivedOption($key) + { + return isset($this->options[$key]); + } +} diff --git a/scripts/Phalcon/Devtools/Version.php b/scripts/Phalcon/Devtools/Version.php index af16a1584..1bd7126ec 100644 --- a/scripts/Phalcon/Devtools/Version.php +++ b/scripts/Phalcon/Devtools/Version.php @@ -39,6 +39,6 @@ class Version extends PhVersion */ protected static function _getVersion() { - return [3, 2, 3, 4, 1]; + return [3, 2, 5, 4, 0]; } } diff --git a/scripts/Phalcon/Listeners/DbProfilerListener.php b/scripts/Phalcon/Listeners/DbProfilerListener.php new file mode 100644 index 000000000..d058280e9 --- /dev/null +++ b/scripts/Phalcon/Listeners/DbProfilerListener.php @@ -0,0 +1,52 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Listeners; + +use Phalcon\Mvc\Model\Migration\Profiler; +use Phalcon\Events\Event; + +/** + * Phalcon\Listeners\DbProfilerListener + * + * Db event listener + * + * @package Phalcon\Listeners + */ +class DbProfilerListener +{ + protected $_profiler; + + public function __construct() + { + $this->_profiler = new Profiler(); + } + + public function beforeQuery(Event $event, $connection) + { + $this->_profiler->startProfile( + $connection->getSQLStatement() + ); + } + + public function afterQuery() + { + $this->_profiler->stopProfile(); + } +} diff --git a/scripts/Phalcon/Migrations.php b/scripts/Phalcon/Migrations.php index f5c7f921d..87f74b1f8 100644 --- a/scripts/Phalcon/Migrations.php +++ b/scripts/Phalcon/Migrations.php @@ -4,7 +4,7 @@ +------------------------------------------------------------------------+ | Phalcon Developer Tools | +------------------------------------------------------------------------+ - | Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) | + | Copyright (c) 2011-2017 Phalcon Team (https://www.phalconphp.com) | +------------------------------------------------------------------------+ | This source file is subject to the New BSD License that is bundled | | with this package in the file LICENSE.txt. | @@ -34,6 +34,9 @@ use Phalcon\Mvc\Model\Migration as ModelMigration; use Phalcon\Version\IncrementalItem as IncrementalVersion; use Phalcon\Version\ItemCollection as VersionCollection; +use Phalcon\Console\OptionStack; +use Phalcon\Mvc\Model\Migration\TableAware\ListTablesIterator; +use Phalcon\Mvc\Model\Migration\TableAware\ListTablesDb; /** * Migrations Class @@ -74,95 +77,85 @@ public static function isConsole() */ public static function generate(array $options) { - $tableName = $options['tableName']; - $exportData = $options['exportData']; - $migrationsDir = $options['migrationsDir']; - $version = isset($options['version']) ? $options['version'] : null; - $force = $options['force']; - $config = $options['config']; - $descr = isset($options['descr']) ? $options['descr'] : null; - $noAutoIncrement = isset($options['noAutoIncrement']) ? $options['noAutoIncrement'] : null; + $optionStack = new OptionStack(); + $modelMigration = new ModelMigration(); + $listTables = new ListTablesDb(); + $optionStack->setOptions($options); + $optionStack->setDefaultOption('version', null); + $optionStack->setDefaultOption('descr', null); + $optionStack->setDefaultOption('noAutoIncrement', null); + $optionStack->setDefaultOption('verbose', false); // Migrations directory - if ($migrationsDir && !file_exists($migrationsDir)) { - mkdir($migrationsDir, 0755, true); + if ($optionStack->getOption('migrationsDir') && !file_exists($optionStack->getOption('migrationsDir'))) { + mkdir($optionStack->getOption('migrationsDir'), 0755, true); } - // Use timestamped version if description is provided - if ($descr) { - $version = (string)(int)(microtime(true) * pow(10, 6)); - VersionCollection::setType(VersionCollection::TYPE_TIMESTAMPED); - $versionItem = VersionCollection::createItem($version . '_' . $descr); - - // Elsewhere use old-style incremental versioning - // The version is specified - } elseif ($version) { - VersionCollection::setType(VersionCollection::TYPE_INCREMENTAL); - $versionItem = VersionCollection::createItem($version); - - // The version is guessed automatically - } else { - VersionCollection::setType(VersionCollection::TYPE_INCREMENTAL); - $versionItems = ModelMigration::scanForVersions($migrationsDir); - - if (!isset($versionItems[0])) { - $versionItem = VersionCollection::createItem('1.0.0'); - - } else { - /** @var IncrementalVersion $versionItem */ - $versionItem = VersionCollection::maximum($versionItems); - $versionItem = $versionItem->addMinor(1); - } - } + $versionItem = self::getVersionNameGeneratingMigration($optionStack); // Path to migration dir - $migrationPath = rtrim($migrationsDir, '\\/') . DIRECTORY_SEPARATOR . $versionItem->getVersion(); + $migrationPath = rtrim($optionStack->getOption('migrationsDir'), '\\/') . DIRECTORY_SEPARATOR . $versionItem->getVersion(); if (!file_exists($migrationPath)) { - if (is_writable(dirname($migrationPath))) { + if (is_writable(dirname($migrationPath)) && !$optionStack->getOption('verbose')) { mkdir($migrationPath); - } else { + } elseif (!is_writable(dirname($migrationPath))) { throw new \RuntimeException("Unable to write '{$migrationPath}' directory. Permission denied"); } - } elseif (!$force) { + } elseif (!$optionStack->getOption('force')) { throw new \LogicException('Version ' . $versionItem->getVersion() . ' already exists'); } // Try to connect to the DB - if (!isset($config->database)) { + if (!isset($optionStack->getOption('config')->database)) { throw new \RuntimeException('Cannot load database configuration'); } - ModelMigration::setup($config->database); - ModelMigration::setSkipAutoIncrement($noAutoIncrement); - ModelMigration::setMigrationPath($migrationsDir); + + ModelMigration::setup($optionStack->getOption('config')->database, $optionStack->getOption('verbose')); + ModelMigration::setSkipAutoIncrement($optionStack->getOption('noAutoIncrement')); + ModelMigration::setMigrationPath($optionStack->getOption('migrationsDir')); $wasMigrated = false; - if ($tableName === '@') { - $migrations = ModelMigration::generateAll($versionItem, $exportData); - foreach ($migrations as $tableName => $migration) { - if ($tableName === self::MIGRATION_LOG_TABLE) { - continue; + if ($optionStack->getOption('tableName') === '@') { + $migrations = ModelMigration::generateAll($versionItem, $optionStack->getOption('exportData')); + if (!$optionStack->getOption('verbose')) { + foreach ($migrations as $tableName => $migration) { + if ($tableName === self::MIGRATION_LOG_TABLE) { + continue; + } + $tableFile = $migrationPath . DIRECTORY_SEPARATOR . $tableName . '.php'; + $wasMigrated = file_put_contents( + $tableFile, + 'getPrefixOption($optionStack->getOption('tableName')); + if (!empty($prefix)) { + $optionStack->setOption('tableName', $listTables->listTablesForPrefix($prefix)); + } + + if ($optionStack->getOption('tableName') == '') { + print Color::info('No one table is created. You should create tables first.') . PHP_EOL; + return; + } + + $tables = explode(',', $optionStack->getOption('tableName')); foreach ($tables as $table) { - $migration = ModelMigration::generate($versionItem, $table, $exportData); - $tableFile = $migrationPath . DIRECTORY_SEPARATOR . $table . '.php'; - $wasMigrated = file_put_contents( - $tableFile, - 'getOption('exportData')); + if (!$optionStack->getOption('verbose')) { + $tableFile = $migrationPath . DIRECTORY_SEPARATOR . $table . '.php'; + $wasMigrated = file_put_contents( + $tableFile, + 'getVersion() . ' was successfully generated') . PHP_EOL; - } elseif (self::isConsole()) { + } elseif (self::isConsole() && !$optionStack->getOption('verbose')) { print Color::info('Nothing to generate. You should create tables first.') . PHP_EOL; } } @@ -179,43 +172,48 @@ public static function generate(array $options) */ public static function run(array $options) { + $optionStack = new OptionStack(); + $listTables = new ListTablesIterator(); + $optionStack->setOptions($options); + $optionStack->setDefaultOption('verbose', false); + // Define versioning type to be used - if (isset($options['tsBased']) && true === $options['tsBased']) { + if (isset($options['tsBased']) && $optionStack->getOption('tsBased') === true) { VersionCollection::setType(VersionCollection::TYPE_TIMESTAMPED); } else { VersionCollection::setType(VersionCollection::TYPE_INCREMENTAL); } - $migrationsDir = rtrim($options['migrationsDir'], '\\/'); + $migrationsDir = rtrim($optionStack->getOption('migrationsDir'), '\\/'); if (!file_exists($migrationsDir)) { throw new ModelException('Migrations directory was not found.'); } - /** @var Config $config */ - $config = $options['config']; - if (!$config instanceof Config) { + if (!$optionStack->getOption('config') instanceof Config) { throw new ModelException('Internal error. Config should be an instance of ' . Config::class); } // Init ModelMigration - if (!isset($config->database)) { + if (!isset($optionStack->getOption('config')->database)) { throw new ScriptException('Cannot load database configuration'); } $finalVersion = null; - if (isset($options['version']) && $options['version'] !== null) { + if (isset($options['version']) && $optionStack->getOption('version') !== null) { $finalVersion = VersionCollection::createItem($options['version']); } - $tableName = '@'; - if (isset($options['tableName'])) { - $tableName = $options['tableName']; - } + $optionStack->setOption('tableName', $options['tableName'], '@'); $versionItems = ModelMigration::scanForVersions($migrationsDir); if (!isset($versionItems[0])) { - throw new ModelException('Migrations were not found at ' . $migrationsDir); + if (php_sapi_name() == 'cli') { + fwrite(STDERR, PHP_EOL . 'Migrations were not found at ' . $migrationsDir . PHP_EOL); + exit; + } else { + throw new ModelException('Migrations were not found at ' . $migrationsDir); + } } // Set default final version @@ -223,11 +221,11 @@ public static function run(array $options) $finalVersion = VersionCollection::maximum($versionItems); } - ModelMigration::setup($config->database); + ModelMigration::setup($optionStack->getOption('config')->database, $optionStack->getOption('verbose')); ModelMigration::setMigrationPath($migrationsDir); - self::connectionSetup($options); - $initialVersion = self::getCurrentVersion($options); - $completedVersions = self::getCompletedVersions($options); + self::connectionSetup($optionStack->getOptions()); + $initialVersion = self::getCurrentVersion($optionStack->getOptions()); + $completedVersions = self::getCompletedVersions($optionStack->getOptions()); // Everything is up to date if ($initialVersion->getStamp() === $finalVersion->getStamp()) { @@ -252,6 +250,7 @@ public static function run(array $options) // Run migration $versionsBetween = VersionCollection::between($initialVersion, $finalVersion, $versionItems); + $prefix = $optionStack->getPrefixOption($optionStack->getOption('tableName')); foreach ($versionsBetween as $versionItem) { // If we are rolling back, we skip migrating when initialVersion is the same as current @@ -273,26 +272,35 @@ public static function run(array $options) } $migrationStartTime = date("Y-m-d H:i:s"); - if ($tableName === '@') { - // Directory depends on Forward or Back Migration - $iterator = new DirectoryIterator( - $migrationsDir . DIRECTORY_SEPARATOR . (ModelMigration::DIRECTION_BACK === $direction ? $initialVersion->getVersion() : $versionItem->getVersion()) - ); + + // Directory depends on Forward or Back Migration + $iterator = new DirectoryIterator( + $migrationsDir . DIRECTORY_SEPARATOR . (ModelMigration::DIRECTION_BACK === $direction ? $initialVersion->getVersion() : $versionItem->getVersion()) + ); + + if ($optionStack->getOption('tableName') === '@') { foreach ($iterator as $fileInfo) { if (!$fileInfo->isFile() || 0 !== strcasecmp($fileInfo->getExtension(), 'php')) { continue; } - ModelMigration::migrate($initialVersion, $versionItem, $fileInfo->getBasename('.php'), $direction); + ModelMigration::migrate($initialVersion, $versionItem, $fileInfo->getBasename('.php')); } } else { - ModelMigration::migrate($initialVersion, $versionItem, $tableName, $direction); + if (!empty($prefix)) { + $optionStack->setOption('tableName', $listTables->listTablesForPrefix($prefix, $iterator)); + } + + $tables = explode(',', $optionStack->getOption('tableName')); + foreach ($tables as $tableName) { + ModelMigration::migrate($initialVersion, $versionItem, $tableName); + } } if (ModelMigration::DIRECTION_FORWARD == $direction) { - self::addCurrentVersion($options, (string)$versionItem, $migrationStartTime); + self::addCurrentVersion($optionStack->getOptions(), (string)$versionItem, $migrationStartTime); print Color::success('Version ' . $versionItem . ' was successfully migrated'); } else { - self::removeCurrentVersion($options, (string)$initialVersion); + self::removeCurrentVersion($optionStack->getOptions(), (string)$initialVersion); print Color::success('Version ' . $initialVersion . ' was successfully rolled back'); } @@ -581,4 +589,42 @@ public static function getCompletedVersions($options) return array_flip($completedVersions); } + + /** + * Get version name to generate migration + * + * @param OptionStack $optionStack Applications options + * @return IncrementalVersion + */ + protected function getVersionNameGeneratingMigration($optionStack) + { + // Use timestamped version if description is provided + if ($optionStack->getOption('descr')) { + $optionStack->setOption('version', (string)(int)(microtime(true) * pow(10, 6))); + VersionCollection::setType(VersionCollection::TYPE_TIMESTAMPED); + $versionItem = VersionCollection::createItem($optionStack->getOption('version') . '_' . $optionStack->getOption('descr')); + + // Elsewhere use old-style incremental versioning + // The version is specified + } elseif ($optionStack->getOption('version')) { + VersionCollection::setType(VersionCollection::TYPE_INCREMENTAL); + $versionItem = VersionCollection::createItem($optionStack->getOption('version')); + + // The version is guessed automatically + } else { + VersionCollection::setType(VersionCollection::TYPE_INCREMENTAL); + $versionItems = ModelMigration::scanForVersions($optionStack->getOption('migrationsDir')); + + if (!isset($versionItems[0])) { + $versionItem = VersionCollection::createItem('1.0.0'); + + } else { + /** @var IncrementalVersion $versionItem */ + $versionItem = VersionCollection::maximum($versionItems); + $versionItem = $versionItem->addMinor(1); + } + } + + return $versionItem; + } } diff --git a/scripts/Phalcon/Mvc/Model/Migration.php b/scripts/Phalcon/Mvc/Model/Migration.php index 8953e63be..6e7ef7a80 100644 --- a/scripts/Phalcon/Mvc/Model/Migration.php +++ b/scripts/Phalcon/Mvc/Model/Migration.php @@ -4,7 +4,7 @@ +------------------------------------------------------------------------+ | Phalcon Developer Tools | +------------------------------------------------------------------------+ - | Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) | + | Copyright (c) 2011-2017 Phalcon Team (https://www.phalconphp.com) | +------------------------------------------------------------------------+ | This source file is subject to the New BSD License that is bundled | | with this package in the file LICENSE.txt. | @@ -38,6 +38,7 @@ use Phalcon\Db\Dialect\PostgresqlExtended; use Phalcon\Db\Adapter\Pdo\PostgresqlExtended as AdapterPostgresqlExtended; use Phalcon\Utils\Nullify; +use Phalcon\Listeners\DbProfilerListener; /** * Phalcon\Mvc\Model\Migration @@ -86,11 +87,12 @@ class Migration * Prepares component * * @param \Phalcon\Config $database Database config + * @param bool $verbose array with settings * @since 3.2.1 Using Postgresql::describeReferences and PostgresqlExtended dialect class * * @throws \Phalcon\Db\Exception */ - public static function setup($database) + public static function setup($database, $verbose = false) { if (!isset($database->adapter)) { throw new DbException('Unspecified database Adapter in your configuration!'); @@ -128,24 +130,18 @@ public static function setup($database) self::$_connection->setDialect(new PostgresqlExtended); } - if (Migrations::isConsole()) { - $profiler = new Profiler(); + if (!Migrations::isConsole() || !$verbose) { + return; + } - $eventsManager = new EventsManager(); - $eventsManager->attach( - 'db', - function ($event, $connection) use ($profiler) { - if ($event->getType() == 'beforeQuery') { - $profiler->startProfile($connection->getSQLStatement()); - } - if ($event->getType() == 'afterQuery') { - $profiler->stopProfile(); - } - } - ); + $eventsManager = new EventsManager(); - self::$_connection->setEventsManager($eventsManager); - } + $eventsManager->attach( + 'db', + new DbProfilerListener() + ); + + self::$_connection->setEventsManager($eventsManager); } /** @@ -452,7 +448,7 @@ public static function generate(ItemInterface $version, $table, $exportData = nu return $classData; } - public static function migrate($fromVersion, $toVersion, $tableName, $direction = self::DIRECTION_FORWARD) + public static function migrate($fromVersion, $toVersion, $tableName) { if (!is_object($fromVersion)) { $fromVersion = VersionCollection::createItem($fromVersion); @@ -462,7 +458,7 @@ public static function migrate($fromVersion, $toVersion, $tableName, $direction $toVersion = VersionCollection::createItem($toVersion); } - if ($fromVersion->getStamp() == $toVersion->getStamp() && self::DIRECTION_FORWARD == $direction) { + if ($fromVersion->getStamp() == $toVersion->getStamp()) { return; // nothing to do } @@ -898,4 +894,14 @@ function ($value) { fclose($batchHandler); self::$_connection->commit(); } + + /** + * Get db connection + * + * @return \Phalcon\Db\AdapterInterface + */ + public function getConnection() + { + return self::$_connection; + } } diff --git a/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesDb.php b/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesDb.php new file mode 100644 index 000000000..3c639ebf5 --- /dev/null +++ b/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesDb.php @@ -0,0 +1,68 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Mvc\Model\Migration\TableAware; + +use Phalcon\Mvc\Model\Migration\TableAware\ListTablesInterface; +use InvalidArgumentException; +use Phalcon\Mvc\Model\Migration as ModelMigration; +use Phalcon\Db\Exception as DbException; + +/** + * Phalcon\Mvc\Model\Migration\TableAware\ListTablesDb + * + * @package Phalcon\Mvc\Model\Migration\TableAware + */ +class ListTablesDb implements ListTablesInterface +{ + /** + * Get table names with prefix for running migration + * + * @param string $tablePrefix + * @param \DirectoryIterator $iterator + * @return string + */ + public function listTablesForPrefix($tablePrefix, \DirectoryIterator $iterator = null) + { + if (empty($tablePrefix)) { + throw new InvalidArgumentException("Parameters weren't defined in " . __METHOD__); + } + + $modelMigration = new ModelMigration(); + $connection = $modelMigration->getConnection(); + + $tablesList = $connection->listTables(); + if (empty($tablesList)) { + return ''; + } + + $strlen = strlen($tablePrefix); + foreach ($tablesList as $key => $value) { + if (substr($value, 0, $strlen) != $tablePrefix) { + unset($tablesList[$key]); + } + } + + if (empty($tablesList)) { + throw new DbException("Specified table prefix doesn't match with any table name"); + } + + return implode(',', $tablesList); + } +} diff --git a/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesInterface.php b/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesInterface.php new file mode 100644 index 000000000..84bc904c6 --- /dev/null +++ b/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesInterface.php @@ -0,0 +1,37 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Mvc\Model\Migration\TableAware; + +/** + * Phalcon\Mvc\Model\Migration\TableAware\ListTablesInterface + * + * @package Phalcon\Mvc\Model\Migration\TableAware + */ +interface ListTablesInterface +{ + /** + * Get list table from prefix + * + * @param string $tablePrefix Table prefix + * @param \DirectoryIterator $iterator + * @return string + */ + public function listTablesForPrefix($tablePrefix, \DirectoryIterator $iterator = null); +} diff --git a/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesIterator.php b/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesIterator.php new file mode 100644 index 000000000..5d07df83f --- /dev/null +++ b/scripts/Phalcon/Mvc/Model/Migration/TableAware/ListTablesIterator.php @@ -0,0 +1,60 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Mvc\Model\Migration\TableAware; + +use Phalcon\Mvc\Model\Migration\TableAware\ListTablesInterface; +use DirectoryIterator; +use InvalidArgumentException; + +/** + * Phalcon\Mvc\Model\Migration\TableAware\ListTablesIterator + * + * @package Phalcon\Mvc\Model\Migration\TableAware + */ +class ListTablesIterator implements ListTablesInterface +{ + /** + * Get table names with prefix for running migration + * + * @param string $tablePrefix + * @param DirectoryIterator $iterator + * @return string + */ + public function listTablesForPrefix($tablePrefix, DirectoryIterator $iterator = null) + { + if (empty($tablePrefix) || empty($iterator)) { + throw new InvalidArgumentException("Parameters weren't defined in " . __METHOD__); + } + + $strlen = strlen($tablePrefix); + $fileNames = []; + foreach ($iterator as $fileInfo) { + if (substr($fileInfo->getFilename(), 0, $strlen) == $tablePrefix) { + $file = explode('.', $fileInfo->getFilename()); + $fileNames[] = $file[0]; + } + } + + $fileNames = array_unique($fileNames); +// natsort($fileNames); + + return implode(',', $fileNames); + } +} diff --git a/tests/_data/console/app/test_table_prefix/migrations/1.0.0/issue595_1.php b/tests/_data/console/app/test_table_prefix/migrations/1.0.0/issue595_1.php new file mode 100644 index 000000000..ed23f539e --- /dev/null +++ b/tests/_data/console/app/test_table_prefix/migrations/1.0.0/issue595_1.php @@ -0,0 +1,76 @@ +morphTable('issue595_1', [ + 'columns' => [ + new Column( + 'id', + [ + 'type' => Column::TYPE_INTEGER, + 'unsigned' => true, + 'notNull' => true, + 'autoIncrement' => true, + 'size' => 10, + 'first' => true + ] + ), + new Column( + 'name', + [ + 'type' => Column::TYPE_VARCHAR, + 'notNull' => true, + 'size' => 45, + 'after' => 'id' + ] + ) + ], + 'indexes' => [ + new Index('PRIMARY', ['id'], 'PRIMARY') + ], + 'options' => [ + 'TABLE_TYPE' => 'BASE TABLE', + 'AUTO_INCREMENT' => '1', + 'ENGINE' => 'InnoDB', + 'TABLE_COLLATION' => 'utf8_general_ci' + ], + ] + ); + } + + /** + * Run the migrations + * + * @return void + */ + public function up() + { + + } + + /** + * Reverse the migrations + * + * @return void + */ + public function down() + { + + } + +} diff --git a/tests/_data/console/app/test_table_prefix/migrations/1.0.0/issue595_2.php b/tests/_data/console/app/test_table_prefix/migrations/1.0.0/issue595_2.php new file mode 100644 index 000000000..1ab6a29db --- /dev/null +++ b/tests/_data/console/app/test_table_prefix/migrations/1.0.0/issue595_2.php @@ -0,0 +1,76 @@ +morphTable('issue595_2', [ + 'columns' => [ + new Column( + 'id', + [ + 'type' => Column::TYPE_INTEGER, + 'unsigned' => true, + 'notNull' => true, + 'autoIncrement' => true, + 'size' => 10, + 'first' => true + ] + ), + new Column( + 'version', + [ + 'type' => Column::TYPE_INTEGER, + 'notNull' => true, + 'size' => 45, + 'after' => 'id' + ] + ) + ], + 'indexes' => [ + new Index('PRIMARY', ['id'], 'PRIMARY') + ], + 'options' => [ + 'TABLE_TYPE' => 'BASE TABLE', + 'AUTO_INCREMENT' => '1', + 'ENGINE' => 'InnoDB', + 'TABLE_COLLATION' => 'utf8_general_ci' + ], + ] + ); + } + + /** + * Run the migrations + * + * @return void + */ + public function up() + { + + } + + /** + * Reverse the migrations + * + * @return void + */ + public function down() + { + + } + +} diff --git a/tests/_data/schemas/mysql/dump.sql b/tests/_data/schemas/mysql/dump.sql index 320921e4e..10aa3c96d 100644 --- a/tests/_data/schemas/mysql/dump.sql +++ b/tests/_data/schemas/mysql/dump.sql @@ -33,3 +33,31 @@ CREATE TABLE `test_many_running` ( `active` tinyint(1) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `test_dry_verbose`; +CREATE TABLE `test_dry_verbose` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(45) NOT NULL, + `created_at` datetime NOT NULL, + `active` tinyint(1) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Table structure for testing table prefix, issue #595 +-- +DROP TABLE IF EXISTS `issue595_1`; +CREATE TABLE `issue595_1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(45) NOT NULL, + `version` int(45) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `issue595_2`; +CREATE TABLE `issue595_2` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `version` int(45) NOT NULL, + `name` varchar(45) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/tests/console/GenerateDryVerboseMigrationCept.php b/tests/console/GenerateDryVerboseMigrationCept.php new file mode 100644 index 000000000..16ee53e6b --- /dev/null +++ b/tests/console/GenerateDryVerboseMigrationCept.php @@ -0,0 +1,24 @@ +wantToTest('Generating migartion with --dry mode anf without'); + +$I->amInPath(dirname(app_path())); + +$I->runShellCommand('phalcon migration --action=generate --migrations=app/test_dry_verbose/migrations --table=test_dry_verbose --config=app/mysql/config.php'); +$I->seeInShellOutput('Success: Version 1.0.0 was successfully generated'); +$I->seeFileFound(app_path('test_dry_verbose/migrations/1.0.0/test_dry_verbose.php')); + +$I->runShellCommand('phalcon migration --action=generate --migrations=app/test_dry_verbose/migrations --table=test_dry_verbose --config=app/mysql/config.php'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully generated'); +$I->seeFileFound(app_path('test_dry_verbose/migrations/1.0.1/test_dry_verbose.php')); + +$I->runShellCommand('phalcon migration --action=generate --migrations=app/test_dry_verbose/migrations --table=test_dry_verbose --config=app/mysql/config.php --dry'); +$I->seeInShellOutput('DESCRIBE `devtools`.`test_dry_verbose`'); +$I->dontSeeInShellOutput('Success: Version 1.0.2 was successfully generated'); +$I->dontSeeFileFound(app_path('test_dry_verbose/migrations/1.0.2/test_dry_verbose.dat')); diff --git a/tests/console/GenerateTablePrefixMigrationCept.php b/tests/console/GenerateTablePrefixMigrationCept.php new file mode 100644 index 000000000..05367db4e --- /dev/null +++ b/tests/console/GenerateTablePrefixMigrationCept.php @@ -0,0 +1,20 @@ +wantToTest('Generating migration for testing table prefix'); + +$I->amInPath(dirname(app_path())); + +$I->dontSeeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_1.php')); +$I->dontSeeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_2.php')); + +$I->runShellCommand('phalcon migration --action=generate --config=app/mysql/config.php --migrations=app/test_table_prefix/migrations --table=issue595*'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully generated'); + +$I->seeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_1.php')); +$I->seeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_2.php')); diff --git a/tests/console/RunDryVerboseMigrationCept.php b/tests/console/RunDryVerboseMigrationCept.php new file mode 100644 index 000000000..8d2b54852 --- /dev/null +++ b/tests/console/RunDryVerboseMigrationCept.php @@ -0,0 +1,30 @@ +wantToTest('Running migration with --verbose mode and without'); + +$I->amInPath(dirname(app_path())); +$I->cleanDir(tests_path('_data/console/.phalcon')); + +$I->seeFileFound(app_path('test_dry_verbose/migrations/1.0.0/test_dry_verbose.php')); +$I->seeFileFound(app_path('test_dry_verbose/migrations/1.0.1/test_dry_verbose.php')); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_dry_verbose/migrations/ --version=1.0.0'); +$I->seeInShellOutput('Success: Version 1.0.0 was successfully migrated'); +$I->dontSeeInShellOutput('DESCRIBE `devtools`.`test_dry_verbose`'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_dry_verbose/migrations/ --version=1.0.1'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully migrated'); +$I->dontSeeInShellOutput('DESCRIBE `devtools`.`test_dry_verbose`'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_dry_verbose/migrations/ --version=1.0.0 --verbose'); +$I->seeInShellOutput('DESCRIBE `devtools`.`test_dry_verbose`'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully rolled back'); + +$I->cleanDir(tests_path('_data/console/.phalcon')); +$I->deleteDir(app_path('test_dry_verbose')); diff --git a/tests/console/RunTablePrefixMigrationCept.php b/tests/console/RunTablePrefixMigrationCept.php new file mode 100644 index 000000000..58e99bbff --- /dev/null +++ b/tests/console/RunTablePrefixMigrationCept.php @@ -0,0 +1,26 @@ +wantToTest('Running migration for testing table prefix'); + +$I->amInPath(dirname(app_path())); +$I->cleanDir(tests_path('_data/console/.phalcon')); + +$I->seeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_1.php')); +$I->seeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_2.php')); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_table_prefix/migrations/ --version=1.0.0 --table=issue595*'); +$I->seeInShellOutput('Success: Version 1.0.0 was successfully migrated'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_table_prefix/migrations/ --version=1.0.1 --table=issue595*'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully migrated'); + +$I->deleteDir(app_path('test_table_prefix/migrations/1.0.1/')); +$I->dontSeeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_1.php')); +$I->dontSeeFileFound(app_path('test_table_prefix/migrations/1.0.1/issue595_2.php')); +$I->cleanDir(tests_path('_data/console/.phalcon')); diff --git a/tests/console/RunUpDownMigrationCept.php b/tests/console/RunUpDownMigrationCept.php new file mode 100644 index 000000000..def12a8ee --- /dev/null +++ b/tests/console/RunUpDownMigrationCept.php @@ -0,0 +1,50 @@ +wantToTest('Running migration with different situations and without migration'); + +$I->amInPath(dirname(app_path())); +$I->cleanDir(tests_path('_data/console/.phalcon')); + +$I->copyDir('app/test_many_running', 'app/test_up_down'); +$I->seeFileFound(app_path('test_up_down/migrations/1.0.12/test_many_running.php')); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.0'); +$I->seeInShellOutput('Success: Version 1.0.0 was successfully migrated'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.1'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully migrated'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.0'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully rolled back'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.5'); +$I->seeInShellOutput('Success: Version 1.0.5 was successfully migrated'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.0'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully rolled back'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.5'); +$I->seeInShellOutput('Success: Version 1.0.5 was successfully migrated'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.12'); +$I->seeInShellOutput('Success: Version 1.0.12 was successfully migrated'); + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.0'); +$I->seeInShellOutput('Success: Version 1.0.1 was successfully rolled back'); + +$I->cleanDir(app_path('test_up_down/migrations')); + +$I->dontSeeFileFound(app_path('test_up_down/migrations/1.0.0/test_many_running.php')); +$I->dontSeeFileFound(app_path('test_up_down/migrations/1.0.12/test_many_running.php')); + + +$I->runShellCommand('phalcon migration --action=run --config=app/mysql/config.php --migrations=app/test_up_down/migrations --table=test_many_running --version=1.0.0'); +$I->seeInShellOutput('Phalcon DevTools'); + +$I->cleanDir(tests_path('_data/console/.phalcon')); diff --git a/tests/unit/Console/OptionStackTest.php b/tests/unit/Console/OptionStackTest.php new file mode 100644 index 000000000..70dcf9c09 --- /dev/null +++ b/tests/unit/Console/OptionStackTest.php @@ -0,0 +1,219 @@ + | + +------------------------------------------------------------------------+ +*/ + +class OptionStackTest extends UnitTest +{ + use OptionParserTrait; + + protected $options; + + public function _before() + { + $this->options = new OptionStack(); + } + + /** + * Tests OptionStack::setOptions, OptionStack::getOptions + * + * @test + * @author Sergii Svyrydenko + * @since 2017-09-28 + */ + public function shouldSetOptionsAndGetOptions() + { + $this->options->setOptions(['test' => 'foo', 'test2' => 'bar']); + + $this->specify( + "Options didn't set", + function($options, $expected) + { + expect($options)->equals($expected); + }, + [ + 'examples' => [ + [$this->options->getOptions(), ['test' => 'foo', 'test2' => 'bar']] + ] + ] + ); + } + + /** + * Tests OptionStack::setOption, OptionStack::getOption + * + * @test + * @author Sergii Svyrydenko + * @since 2017-09-28 + */ + public function shouldSetOptionAndGetOption11() + { + $this->specify( + "Option didn't set", + function($value, $defaultValue, $expected) + { + $this->options->setOption('set-test', $value, $defaultValue); + + expect($this->options->getOption('set-test'))->equals($expected); + }, + [ + 'examples' => [ + ['foo-bar', 'bar-foo', 'foo-bar'], + ['', 'bar-foo', 'bar-foo'] + ] + ] + ); + } + + /** + * Tests OptionStack::setDefaultOption + * + * @test + * @author Sergii Svyrydenko + * @since 2017-09-28 + */ + public function shouldSetDefaultOptionIfOptionDidntExist() + { + $this->options->setOption('test', 'bar'); + + $this->specify( + "Method setDefaultOption didn't work well", + function($key, $defaultValue, $expected) + { + $this->options->setDefaultOption($key, $defaultValue); + + expect($this->options->getOption($key))->equals($expected); + }, + [ + 'examples' => [ + ['test', 'foo-bar', 'bar'], + ['test2', 'bar-foo', 'bar-foo'] + ] + ] + ); + } + + /** + * Tests OptionStack::isReceivedOption + * + * @test + * @author Sergii Svyrydenko + * @since 2017-09-28 + */ + public function shouldCheckingRecievedOption() + { + $this->options->setOption('true-option', 'foo-bar'); + + $this->specify( + "Checking option didn't wotk", + function($option, $expected) + { + expect($option)->equals($expected); + }, + [ + 'examples' => [ + [$this->options->isReceivedOption('true-option', $this->options->getOptions()), true], + [$this->options->isReceivedOption('false-option', $this->options->getOptions()), false] + ] + ] + ); + } + + /** + * Tests OptionStack::getValidOption + * + * @test + * @author Sergii Svyrydenko + * @since 2017-09-28 + */ + public function shouldReturnValidOptionOrSetDefault() + { + $this->options->setOptions(['test' => 'foo', 'test2' => 'bar']); + + $this->specify( + "Valid value didn't return", + function($option, $expected) + { + expect($option)->equals($expected); + }, + [ + 'examples' => [ + [$this->options->getValidOption('test', 'bar'), 'foo'], + [$this->options->getValidOption('false-option', 'bar'), 'bar'], + ] + ] + ); + } + + /** + * Tests OptionParserTrait::getPrefixOption + * + * @test + * @issue 595 + * @author Sergii Svyrydenko + * @since 2017-10-06 + */ + public function shouldReturnPrefixFromOptionWithoutSetPrefix() + { + $this->options->setOptions(['test' => 'foo', 'test2' => 'bar']); + + $this->specify( + 'Method' . __METHOD__ . 'does not return option prefix', + function($prefix, $expected) { + expect($this->getPrefixOption($prefix))->equals($expected); + }, + [ + 'examples' => [ + ['foo*', 'foo'], + ['bar*', 'bar'] + ] + ] + ); + } + + /** + * Tests OptionParserTrait::getPrefixOption + * + * @test + * @issue 595 + * @author Sergii Svyrydenko + * @since 2017-10-06 + */ + public function shouldReturnPrefixFromOptionWithSetPrefix() + { + $this->options->setOptions(['test' => 'foo', 'test2' => 'bar']); + + $this->specify( + 'Method' . __METHOD__ . 'does not return option prefix', + function($prefix, $prefixEnd, $expected) { + expect($this->getPrefixOption($prefix, $prefixEnd))->equals($expected); + }, + [ + 'examples' => [ + ['foo^', '^', 'foo'], + ['bar?', '?', 'bar'] + ] + ] + ); + } +} diff --git a/tests/unit/Mvc/Model/Migration/TableAware/ListTablesDbTest.php b/tests/unit/Mvc/Model/Migration/TableAware/ListTablesDbTest.php new file mode 100644 index 000000000..a48fdff0c --- /dev/null +++ b/tests/unit/Mvc/Model/Migration/TableAware/ListTablesDbTest.php @@ -0,0 +1,69 @@ + | + +------------------------------------------------------------------------+ +*/ + +class ListTablesDbTest extends UnitTest +{ + public function _before() + { + parent::_before(); + + try { + $config = include(app_path('mysql/config.php')); + if (is_array($config)) { + $config = new Config($config); + } + + ModelMigration::setup($config->database); + } catch (\PDOException $e) { + throw new \PHPUnit_Framework_SkippedTestError("Unable to connect to the database: " . $e->getMessage()); + } + } + + /** + * Tests ListTablesDb::listTablesForPrefix + * + * @test + * @issue 595 + * @author Sergii Svyrydenko + * @since 2017-10-06 + */ + public function shouldReturnListTablesFromDb() + { + $listTables = new ListTablesDb(); + + $this->specify( + 'Method' . __METHOD__ . 'did not return table list', + function ($tablePrefix, $expected) use ($listTables) { + expect($listTables->listTablesForPrefix($tablePrefix))->equals($expected); + }, + [ + 'examples' => [ + ['issue595', 'issue595_1,issue595_2'] + ] + ] + ); + } +} diff --git a/tests/unit/Mvc/Model/Migration/TableAware/ListTablesIteratorTest.php b/tests/unit/Mvc/Model/Migration/TableAware/ListTablesIteratorTest.php new file mode 100644 index 000000000..d6dc00fcd --- /dev/null +++ b/tests/unit/Mvc/Model/Migration/TableAware/ListTablesIteratorTest.php @@ -0,0 +1,53 @@ + | + +------------------------------------------------------------------------+ +*/ + +class ListTablesIteratorTest extends UnitTest +{ + /** + * Tests ListTablesIterator::listTablesForPrefix + * + * @test + * @issue 595 + * @author Sergii Svyrydenko + * @since 2017-10-06 + */ + public function shouldReturnListTablesFromIterator() + { + $iterator = new DirectoryIterator(app_path('test_table_prefix/migrations/1.0.0')); + $listTables = new ListTablesIterator(); + + $this->specify( + 'Method' . __METHOD__ . 'did not return table list', + function($tablePrefix, $expected) use ($iterator, $listTables){ + expect($listTables->listTablesForPrefix($tablePrefix, $iterator))->equals($expected); + }, + [ + 'examples' => [ + ['issue', 'issue595_1,issue595_2'] + ] + ] + ); + } +}