From 3d7a91e12beb6b932befc4b4d74467a8557f158b Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Wed, 18 Jun 2014 17:13:16 +0300 Subject: [PATCH 1/4] `yii\mongodb\Migration` created --- extensions/mongodb/Migration.php | 137 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 extensions/mongodb/Migration.php diff --git a/extensions/mongodb/Migration.php b/extensions/mongodb/Migration.php new file mode 100644 index 0000000..3b6fe45 --- /dev/null +++ b/extensions/mongodb/Migration.php @@ -0,0 +1,137 @@ + + * @since 2.0 + */ +abstract class Migration extends Component implements MigrationInterface +{ + /** + * @var Connection|string the MongoDB connection object or the application component ID of the MongoDB connection + * that this migration should work with. + */ + public $db = 'mongodb'; + + /** + * Initializes the migration. + * This method will set [[db]] to be the 'db' application component, if it is null. + */ + public function init() + { + parent::init(); + $this->db = Instance::ensure($this->db, Connection::className()); + } + + /** + * Creates new collection with the specified options. + * @param string|array $collection name of the collection + * @param array $options collection options in format: "name" => "value" + * @return \MongoCollection new Mongo collection instance. + */ + public function createCollection($collection, $options = []) + { + if (is_array($collection)) { + list($database, $collectionName) = $collection; + } else { + $database = null; + $collectionName = $collection; + } + echo " > create collection " . $this->composeCollectionLogName($collection) . " ..."; + $time = microtime(true); + $this->db->getDatabase($database)->createCollection($collectionName, $options); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Drops existing collection. + * @param string|array $collection name of the collection + */ + public function dropCollection($collection) + { + echo " > drop collection " . $this->composeCollectionLogName($collection) . " ..."; + $time = microtime(true); + $this->db->getCollection($collection)->drop(); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Creates an index on the collection and the specified fields. + * @param string|array $collection name of the collection + * @param array|string $columns column name or list of column names. + * @param array $options list of options in format: optionName => optionValue. + */ + public function createIndex($collection, $columns, $options = []) + { + echo " > create index on " . $this->composeCollectionLogName($collection) . " (" . Json::encode((array)$columns) . empty($options) ? "" : ", " . Json::encode($options) . ") ..."; + $time = microtime(true); + $this->db->getCollection($collection)->createIndex($columns, $options); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Drop indexes for specified column(s). + * @param string|array $collection name of the collection + * @param string|array $columns column name or list of column names. + */ + public function dropIndex($collection, $columns) + { + echo " > drop index on " . $this->composeCollectionLogName($collection) . " (" . Json::encode((array)$columns) . ") ..."; + $time = microtime(true); + $this->db->getCollection($collection)->dropIndex($columns); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Drops all indexes for specified collection. + * @param string|array $collection name of the collection. + */ + public function dropAllIndexes($collection) + { + echo " > drop all indexes on " . $this->composeCollectionLogName($collection) . ") ..."; + $time = microtime(true); + $this->db->getCollection($collection)->dropAllIndexes(); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Composes string representing collection name. + * @param array|string $collection collection name. + * @return string collection name. + */ + protected function composeCollectionLogName($collection) + { + if (is_array($collection)) { + list($database, $collection) = $collection; + return $database . '.' . $collection; + } else { + return $collection; + } + } +} \ No newline at end of file From 407ce75880ac4833b6213d8c10736e642bc091da Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Wed, 18 Jun 2014 17:46:20 +0300 Subject: [PATCH 2/4] `yii\mongodb\console\controllers\MigrateController` created --- .../console/controllers/MigrateController.php | 160 +++++++++++++++++++++ extensions/mongodb/views/migration.php | 24 ++++ 2 files changed, 184 insertions(+) create mode 100644 extensions/mongodb/console/controllers/MigrateController.php create mode 100644 extensions/mongodb/views/migration.php diff --git a/extensions/mongodb/console/controllers/MigrateController.php b/extensions/mongodb/console/controllers/MigrateController.php new file mode 100644 index 0000000..0a93499 --- /dev/null +++ b/extensions/mongodb/console/controllers/MigrateController.php @@ -0,0 +1,160 @@ + [ + * 'mongodb-migrate' => 'yii\mongodb\console\controllers\MigrateController' + * ], + * ]; + * ~~~ + * + * Below are some common usages of this command: + * + * ~~~ + * # creates a new migration named 'create_user_table' + * yii mongodb-migrate/create create_user_table + * + * # applies ALL new migrations + * yii mongodb-migrate + * + * # reverts the last applied migration + * yii mongodb-migrate/down + * ~~~ + * + * @author Klimov Paul + * @since 2.0 + */ +class MigrateController extends BaseMigrateController +{ + /** + * @var string|array the name of the collection for keeping applied migration information. + */ + public $migrationCollection = 'migration'; + /** + * @inheritdoc + */ + public $templateFile = '@yii/mongodb/views/migration.php'; + /** + * @var Connection|string the DB connection object or the application + * component ID of the DB connection. + */ + public $db = 'mongodb'; + + /** + * @inheritdoc + */ + public function options($actionId) + { + return array_merge( + parent::options($actionId), + ['migrationCollection', 'db'] // global for all actions + ); + } + + /** + * This method is invoked right before an action is to be executed (after all possible filters.) + * It checks the existence of the [[migrationPath]]. + * @param \yii\base\Action $action the action to be executed. + * @throws Exception if db component isn't configured + * @return boolean whether the action should continue to be executed. + */ + public function beforeAction($action) + { + if (parent::beforeAction($action)) { + if ($action->id !== 'create') { + if (is_string($this->db)) { + $this->db = Yii::$app->get($this->db); + } + if (!$this->db instanceof Connection) { + throw new Exception("The 'db' option must refer to the application component ID of a MongoDB connection."); + } + } + return true; + } else { + return false; + } + } + + /** + * Creates a new migration instance. + * @param string $class the migration class name + * @return \yii\mongodb\Migration the migration instance + */ + protected function createMigration($class) + { + $file = $this->migrationPath . DIRECTORY_SEPARATOR . $class . '.php'; + require_once($file); + + return new $class(['db' => $this->db]); + } + + /** + * @inheritdoc + */ + protected function getMigrationHistory($limit) + { + $query = new Query; + $rows = $query->select(['version', 'apply_time']) + ->from($this->migrationCollection) + ->orderBy('version DESC') + ->limit($limit) + ->all($this->db); + $history = ArrayHelper::map($rows, 'version', 'apply_time'); + if (empty($history)) { + $this->addMigrationHistory(self::BASE_MIGRATION); + } + unset($history[self::BASE_MIGRATION]); + + return $history; + } + + /** + * @inheritdoc + */ + protected function addMigrationHistory($version) + { + $this->db->getCollection($this->migrationCollection)->insert([ + 'version' => $version, + 'apply_time' => time(), + ]); + } + + /** + * @inheritdoc + */ + protected function removeMigrationHistory($version) + { + $this->db->getCollection($this->migrationCollection)->remove([ + 'version' => $version, + ]); + } +} diff --git a/extensions/mongodb/views/migration.php b/extensions/mongodb/views/migration.php new file mode 100644 index 0000000..46f5d02 --- /dev/null +++ b/extensions/mongodb/views/migration.php @@ -0,0 +1,24 @@ + + +class extends \yii\mongodb\Migration +{ + public function up() + { + + } + + public function down() + { + echo " cannot be reverted.\n"; + + return false; + } +} From 3253bf316cb19d8d767c876506e35bf6a3722073 Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Wed, 18 Jun 2014 17:59:19 +0300 Subject: [PATCH 3/4] Data manipulation methods added to `yii\mongodb\Migration` --- extensions/mongodb/Migration.php | 84 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/extensions/mongodb/Migration.php b/extensions/mongodb/Migration.php index 3b6fe45..e92e2be 100644 --- a/extensions/mongodb/Migration.php +++ b/extensions/mongodb/Migration.php @@ -53,7 +53,6 @@ abstract class Migration extends Component implements MigrationInterface * Creates new collection with the specified options. * @param string|array $collection name of the collection * @param array $options collection options in format: "name" => "value" - * @return \MongoCollection new Mongo collection instance. */ public function createCollection($collection, $options = []) { @@ -121,6 +120,89 @@ abstract class Migration extends Component implements MigrationInterface } /** + * Inserts new data into collection. + * @param array|string $collection collection name. + * @param array|object $data data to be inserted. + * @param array $options list of options in format: optionName => optionValue. + * @return \MongoId new record id instance. + */ + public function insert($collection, $data, $options = []) + { + echo " > insert into " . $this->composeCollectionLogName($collection) . ") ..."; + $time = microtime(true); + $id = $this->db->getCollection($collection)->insert($data, $options); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + return $id; + } + + /** + * Inserts several new rows into collection. + * @param array|string $collection collection name. + * @param array $rows array of arrays or objects to be inserted. + * @param array $options list of options in format: optionName => optionValue. + * @return array inserted data, each row will have "_id" key assigned to it. + */ + public function batchInsert($collection, $rows, $options = []) + { + echo " > insert into " . $this->composeCollectionLogName($collection) . ") ..."; + $time = microtime(true); + $rows = $this->db->getCollection($collection)->batchInsert($rows, $options); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + return $rows; + } + + /** + * Updates the rows, which matches given criteria by given data. + * Note: for "multiple" mode Mongo requires explicit strategy "$set" or "$inc" + * to be specified for the "newData". If no strategy is passed "$set" will be used. + * @param array|string $collection collection name. + * @param array $condition description of the objects to update. + * @param array $newData the object with which to update the matching records. + * @param array $options list of options in format: optionName => optionValue. + * @return integer|boolean number of updated documents or whether operation was successful. + */ + public function update($collection, $condition, $newData, $options = []) + { + echo " > update " . $this->composeCollectionLogName($collection) . ") ..."; + $time = microtime(true); + $result = $this->db->getCollection($collection)->update($condition, $newData, $options); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + return $result; + } + + /** + * Update the existing database data, otherwise insert this data + * @param array|string $collection collection name. + * @param array|object $data data to be updated/inserted. + * @param array $options list of options in format: optionName => optionValue. + * @return \MongoId updated/new record id instance. + */ + public function save($collection, $data, $options = []) + { + echo " > save " . $this->composeCollectionLogName($collection) . ") ..."; + $time = microtime(true); + $id = $this->db->getCollection($collection)->save($data, $options); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + return $id; + } + + /** + * Removes data from the collection. + * @param array|string $collection collection name. + * @param array $condition description of records to remove. + * @param array $options list of options in format: optionName => optionValue. + * @return integer|boolean number of updated documents or whether operation was successful. + */ + public function remove($collection, $condition = [], $options = []) + { + echo " > remove " . $this->composeCollectionLogName($collection) . ") ..."; + $time = microtime(true); + $result = $this->db->getCollection($collection)->remove($condition, $options); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + return $result; + } + + /** * Composes string representing collection name. * @param array|string $collection collection name. * @return string collection name. From d011675b77c93b5a83ba6eb515ea352682c26beb Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Wed, 18 Jun 2014 18:02:03 +0300 Subject: [PATCH 4/4] mongodb/CHANGELOG updated --- extensions/mongodb/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/mongodb/CHANGELOG.md b/extensions/mongodb/CHANGELOG.md index 0fab685..55d89b0 100644 --- a/extensions/mongodb/CHANGELOG.md +++ b/extensions/mongodb/CHANGELOG.md @@ -7,6 +7,7 @@ Yii Framework 2 mongodb extension Change Log - Bug #3385: Fixed "The 'connected' property is deprecated" (samdark) - Enh #3520: Added `unlinkAll()`-method to active record to remove all records of a model relation (NmDimas, samdark, cebe) - Enh #3778: Gii generator for Active Record model added (klimov-paul) +- Enh: Migration support added (klimov-paul) 2.0.0-beta April 13, 2014