/** * Generate specified table migration * * @param $version * @param $table * @param null $exportData * * @return string * @throws Exception */ public static function generate($version, $table, $exportData = null) { $oldColumn = null; $allFields = array(); $numericFields = array(); $tableDefinition = array(); if (isset(self::$_databaseConfig->schema)) { $defaultSchema = self::$_databaseConfig->schema; } elseif (isset(self::$_databaseConfig->adapter) && self::$_databaseConfig->adapter == 'Postgresql') { $defaultSchema = 'public'; } elseif (isset(self::$_databaseConfig->dbname)) { $defaultSchema = self::$_databaseConfig->dbname; } else { $defaultSchema = null; } $description = self::$_connection->describeColumns($table, $defaultSchema); foreach ($description as $field) { $fieldDefinition = array(); switch ($field->getType()) { case Column::TYPE_INTEGER: $fieldDefinition[] = "'type' => Column::TYPE_INTEGER"; $numericFields[$field->getName()] = true; break; case Column::TYPE_VARCHAR: $fieldDefinition[] = "'type' => Column::TYPE_VARCHAR"; break; case Column::TYPE_CHAR: $fieldDefinition[] = "'type' => Column::TYPE_CHAR"; break; case Column::TYPE_DATE: $fieldDefinition[] = "'type' => Column::TYPE_DATE"; break; case Column::TYPE_DATETIME: $fieldDefinition[] = "'type' => Column::TYPE_DATETIME"; break; case Column::TYPE_DECIMAL: $fieldDefinition[] = "'type' => Column::TYPE_DECIMAL"; $numericFields[$field->getName()] = true; break; case Column::TYPE_TEXT: $fieldDefinition[] = "'type' => Column::TYPE_TEXT"; break; case Column::TYPE_BOOLEAN: $fieldDefinition[] = "'type' => Column::TYPE_BOOLEAN"; break; case Column::TYPE_FLOAT: $fieldDefinition[] = "'type' => Column::TYPE_FLOAT"; break; case Column::TYPE_DOUBLE: $fieldDefinition[] = "'type' => Column::TYPE_DOUBLE"; break; default: throw new Exception('Unrecognized data type ' . $field->getType() . ' at column ' . $field->getName()); } //if ($field->isPrimary()) { // $fieldDefinition[] = "'primary' => true"; //} if ($field->isUnsigned()) { $fieldDefinition[] = "'unsigned' => true"; } if ($field->isNotNull()) { $fieldDefinition[] = "'notNull' => true"; } if ($field->isAutoIncrement()) { $fieldDefinition[] = "'autoIncrement' => true"; } if ($field->getSize()) { $fieldDefinition[] = "'size' => " . $field->getSize(); } else { $fieldDefinition[] = "'size' => 1"; } if ($field->getScale()) { $fieldDefinition[] = "'scale' => " . $field->getScale(); } if ($oldColumn != null) { $fieldDefinition[] = "'after' => '" . $oldColumn . "'"; } else { $fieldDefinition[] = "'first' => true"; } $oldColumn = $field->getName(); $tableDefinition[] = "\t\t\t\tnew Column(\n\t\t\t\t\t'" . $field->getName() . "',\n\t\t\t\t\tarray(\n\t\t\t\t\t\t" . join(",\n\t\t\t\t\t\t", $fieldDefinition) . "\n\t\t\t\t\t)\n\t\t\t\t)"; $allFields[] = "'" . $field->getName() . "'"; } $indexesDefinition = array(); $indexes = self::$_connection->describeIndexes($table, $defaultSchema); foreach ($indexes as $indexName => $dbIndex) { $indexDefinition = array(); foreach ($dbIndex->getColumns() as $indexColumn) { $indexDefinition[] = "'" . $indexColumn . "'"; } $indexesDefinition[] = "\t\t\t\tnew Index('" . $indexName . "', array(" . join(", ", $indexDefinition) . "))"; } $referencesDefinition = array(); $references = self::$_connection->describeReferences($table, $defaultSchema); foreach ($references as $constraintName => $dbReference) { $columns = array(); foreach ($dbReference->getColumns() as $column) { $columns[] = "'" . $column . "'"; } $referencedColumns = array(); foreach ($dbReference->getReferencedColumns() as $referencedColumn) { $referencedColumns[] = "'" . $referencedColumn . "'"; } $referenceDefinition = array(); $referenceDefinition[] = "'referencedSchema' => '" . $dbReference->getReferencedSchema() . "'"; $referenceDefinition[] = "'referencedTable' => '" . $dbReference->getReferencedTable() . "'"; $referenceDefinition[] = "'columns' => array(" . join(",", $columns) . ")"; $referenceDefinition[] = "'referencedColumns' => array(" . join(",", $referencedColumns) . ")"; $referencesDefinition[] = "\t\t\t\tnew Reference('" . $constraintName . "', array(\n\t\t\t\t\t" . join(",\n\t\t\t\t\t", $referenceDefinition) . "\n\t\t\t\t))"; } $optionsDefinition = array(); $tableOptions = self::$_connection->tableOptions($table, $defaultSchema); foreach ($tableOptions as $optionName => $optionValue) { if (self::$_skipAI && strtoupper($optionName) == "AUTO_INCREMENT") { $optionValue = ''; } $optionsDefinition[] = "\t\t\t\t'" . strtoupper($optionName) . "' => '" . $optionValue . "'"; } $classVersion = preg_replace('/[^0-9A-Za-z]/', '', $version); $className = Text::camelize($table) . 'Migration_' . $classVersion; $classData = "use Phalcon\\Db\\Column;\nuse Phalcon\\Db\\Index;\nuse Phalcon\\Db\\Reference;\nuse Phalcon\\Mvc\\Model\\Migration;\n\nclass " . $className . " extends Migration\n" . "{\n\n" . "\tpublic function up()\n" . "\t{\n\t\t\$this->morphTable(\n\t\t\t'" . $table . "',\n\t\t\tarray(" . "\n\t\t\t'columns' => array(\n" . join(",\n", $tableDefinition) . "\n\t\t\t),"; if (count($indexesDefinition)) { $classData .= "\n\t\t\t'indexes' => array(\n" . join(",\n", $indexesDefinition) . "\n\t\t\t),"; } if (count($referencesDefinition)) { $classData .= "\n\t\t\t'references' => array(\n" . join(",\n", $referencesDefinition) . "\n\t\t\t),"; } if (count($optionsDefinition)) { $classData .= "\n\t\t\t'options' => array(\n" . join(",\n", $optionsDefinition) . "\n\t\t\t)\n"; } $classData .= "\t\t)\n\t\t);\n\t}"; if ($exportData == 'always' || $exportData == 'oncreate') { if ($exportData == 'oncreate') { $classData .= "\n\n\tpublic function afterCreateTable() {\n"; } else { $classData .= "\n\n\tpublic function afterUp() {\n"; } $classData .= "\t\t\$this->batchInsert('{$table}', array(\n\t\t\t" . join(",\n\t\t\t", $allFields) . "\n\t\t));"; $fileHandler = fopen(self::$_migrationPath . '/' . $table . '.dat', 'w'); $cursor = self::$_connection->query('SELECT * FROM ' . $table); $cursor->setFetchMode(Db::FETCH_ASSOC); while ($row = $cursor->fetchArray()) { $data = array(); foreach ($row as $key => $value) { if (isset($numericFields[$key])) { if ($value === '' || is_null($value)) { $data[] = 'NULL'; } else { $data[] = addslashes($value); } } else { $data[] = "'" . addslashes($value) . "'"; } unset($value); } fputs($fileHandler, join('|', $data) . PHP_EOL); unset($row); unset($data); } fclose($fileHandler); $classData .= "\n\t}"; } $classData .= "\n}\n"; $classData = str_replace("\t", " ", $classData); return $classData; }