/** * Primary task entry point * * @param array $args The current supplied options. */ public function execute($args) { $output = ''; // Add support for old migration style if (!is_array($args) || !array_key_exists('name', $args)) { $cargs = $this->parse_args($_SERVER['argv']); //input sanity check if (!is_array($cargs) || !array_key_exists('name', $cargs)) { $output .= $this->help(); return $output; } $migration_name = $cargs['name']; } else { $migration_name = $args['name']; } if (!array_key_exists('module', $args)) { $args['module'] = ''; } //clear any filesystem stats cache clearstatcache(); $framework = $this->get_framework(); $migrations_dir = $framework->migrations_directory($args['module']); if (!is_dir($migrations_dir)) { $output .= "\n\tMigrations directory (" . $migrations_dir . " doesn't exist, attempting to create.\n"; if (mkdir($migrations_dir, 0755, true) === FALSE) { $output .= "\n\tUnable to create migrations directory at " . $migrations_dir . ", check permissions?\n"; } else { $output .= "\n\tCreated OK\n"; } } //generate a complete migration file $next_version = Ruckusing_Util_Migrator::generate_timestamp(); $class = Ruckusing_Util_Naming::camelcase($migration_name); if (!self::classNameIsCorrect($class)) { throw new Ruckusing_Exception("Bad migration name,PHP class can't be named as {$class}.Please, choose another name.", Ruckusing_Exception::INVALID_ARGUMENT); } $all_dirs = $framework->migrations_directories(); if ($re = self::classNameIsDuplicated($class, $all_dirs)) { throw new Ruckusing_Exception("This migration name is already used in the \"{$re}\" directory. Please, choose another name.", Ruckusing_Exception::INVALID_ARGUMENT); } $file_name = $next_version . '_' . $class . '.php'; //check to make sure our destination directory is writable if (!is_writable($migrations_dir)) { throw new Ruckusing_Exception("ERROR: migration directory '" . $migrations_dir . "' is not writable by the current user. Check permissions and try again.", Ruckusing_Exception::INVALID_MIGRATION_DIR); } //write it out! $full_path = $migrations_dir . DIRECTORY_SEPARATOR . $file_name; $template_str = self::get_template($class); $file_result = file_put_contents($full_path, $template_str); if ($file_result === FALSE) { throw new Ruckusing_Exception("Error writing to migrations directory/file. Do you have sufficient privileges?", Ruckusing_Exception::INVALID_MIGRATION_DIR); } else { $output .= "\n\tCreated migration: {$file_name}\n\n"; } return $output; }
/** * Check an index * * @param string $table_name the table name * @param string $column_name the column name * @param array $options index options * * @throws Ruckusing_Exception * @return boolean */ public function has_index($table_name, $column_name, $options = array()) { if (empty($table_name)) { throw new Ruckusing_Exception("Missing table name parameter", Ruckusing_Exception::INVALID_ARGUMENT); } if (empty($column_name)) { throw new Ruckusing_Exception("Missing column name parameter", Ruckusing_Exception::INVALID_ARGUMENT); } //did the user specify an index name? if (is_array($options) && array_key_exists('name', $options)) { $index_name = $options['name']; } else { $index_name = Ruckusing_Util_Naming::index_name($table_name, $column_name); } $indexes = $this->indexes($table_name); foreach ($indexes as $idx) { if ($idx['name'] == $index_name) { return true; } } return false; }
/** * Run migrations * * @param array $migrations nigrations to run * @param $string $target_method direction to migrate to 'up'/'down' * @param string $destination version to migrate to * * @return array */ private function run_migrations($migrations, $target_method, $destination) { $last_version = -1; foreach ($migrations as $file) { $full_path = $this->_migratorDirs[$file['module']] . DIRECTORY_SEPARATOR . $file['file']; if (is_file($full_path) && is_readable($full_path)) { require_once $full_path; $klass = Ruckusing_Util_Naming::class_from_migration_file($file['file']); $obj = new $klass($this->_adapter); $start = $this->start_timer(); try { //start transaction $this->_adapter->start_transaction(); $result = $obj->{$target_method}(); //successfully ran migration, update our version and commit $this->_migrator_util->resolve_current_version($file['version'], $target_method); $this->_adapter->commit_transaction(); } catch (Ruckusing_Exception $e) { $this->_adapter->rollback_transaction(); //wrap the caught exception in our own throw new Ruckusing_Exception(sprintf("%s - %s", $file['class'], $e->getMessage()), Ruckusing_Exception::MIGRATION_FAILED); } $end = $this->end_timer(); $diff = $this->diff_timer($start, $end); $this->_return .= sprintf("========= %s ======== (%.2f)\n", $file['class'], $diff); $last_version = $file['version']; $exec = true; } } //update the schema info $result = array('last_version' => $last_version); return $result; }
/** * Load all taks * * @param string $task_dir the task dir path */ private function load_all_tasks($task_dir) { if (!is_dir($task_dir)) { throw new Ruckusing_Exception(sprintf("Task dir: %s does not exist", $task_dir), Ruckusing_Exception::INVALID_ARGUMENT); return false; } $namespaces = scandir($task_dir); foreach ($namespaces as $namespace) { if ($namespace == '.' || $namespace == '..' || !is_dir($task_dir . DIRECTORY_SEPARATOR . $namespace)) { continue; } $files = scandir($task_dir . DIRECTORY_SEPARATOR . $namespace); $regex = '/^(\\w+)\\.php$/'; foreach ($files as $file) { //skip over invalid files if ($file == '.' || $file == ".." || !preg_match($regex, $file, $matches)) { continue; } require_once $task_dir . DIRECTORY_SEPARATOR . $namespace . DIRECTORY_SEPARATOR . $file; $klass = Ruckusing_Util_Naming::class_from_file_name($task_dir . DIRECTORY_SEPARATOR . $namespace . DIRECTORY_SEPARATOR . $file); $task_name = Ruckusing_Util_Naming::task_from_class_name($klass); $this->register_task($task_name, new $klass($this->get_adapter())); } } }
/** * test index name */ public function test_index_name() { $column = "first_name"; $this->assertEquals("idx_users_first_name", Ruckusing_Util_Naming::index_name("users", $column)); $column = "age"; $this->assertEquals("idx_users_age", Ruckusing_Util_Naming::index_name("users", $column)); $column = array('listing_id', 'review_id'); $this->assertEquals("idx_users_listing_id_and_review_id", Ruckusing_Util_Naming::index_name("users", $column)); }