예제 #1
0
 /**
  * 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;
 }