Example #1
0
 /**
  * Generate specified table migration
  *
  * @param      $version
  * @param      $table
  * @param null $exportData
  *
  * @return string
  * @throws \Phalcon\Db\Exception
  */
 public static function generate($version, $table, $exportData = null)
 {
     $oldColumn = null;
     $allFields = [];
     $numericFields = [];
     $tableDefinition = [];
     $snippet = new Snippet();
     $defaultSchema = Utils::resolveDbSchema(self::$_databaseConfig);
     $description = self::$_connection->describeColumns($table, $defaultSchema);
     foreach ($description as $field) {
         /** @var \Phalcon\Db\ColumnInterface $field */
         $fieldDefinition = [];
         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_TIMESTAMP:
                 $fieldDefinition[] = "'type' => Column::TYPE_TIMESTAMP";
                 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;
             case Column::TYPE_TINYBLOB:
                 $fieldDefinition[] = "'type' => Column::TYPE_TINYBLOB";
                 break;
             case Column::TYPE_BLOB:
                 $fieldDefinition[] = "'type' => Column::TYPE_BLOB";
                 break;
             case Column::TYPE_MEDIUMBLOB:
                 $fieldDefinition[] = "'type' => Column::TYPE_MEDIUMBLOB";
                 break;
             case Column::TYPE_LONGBLOB:
                 $fieldDefinition[] = "'type' => Column::TYPE_LONGBLOB";
                 break;
             case Column::TYPE_JSON:
                 $fieldDefinition[] = "'type' => Column::TYPE_JSON";
                 break;
             case Column::TYPE_JSONB:
                 $fieldDefinition[] = "'type' => Column::TYPE_JSONB";
                 break;
             case Column::TYPE_BIGINTEGER:
                 $fieldDefinition[] = "'type' => Column::TYPE_BIGINTEGER";
                 break;
             default:
                 throw new DbException('Unrecognized data type ' . $field->getType() . ' at column ' . $field->getName());
         }
         if (null !== ($default = $field->getDefault())) {
             $fieldDefinition[] = "'default' => \"{$default}\"";
         }
         //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 (self::$_databaseConfig->adapter == 'Postgresql' && in_array($field->getType(), [Column::TYPE_BOOLEAN, Column::TYPE_INTEGER, Column::TYPE_BIGINTEGER])) {
             // nothing
         } else {
             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[] = $snippet->getColumnDefinition($field->getName(), $fieldDefinition);
         $allFields[] = "'" . $field->getName() . "'";
     }
     $indexesDefinition = [];
     $indexes = self::$_connection->describeIndexes($table, $defaultSchema);
     foreach ($indexes as $indexName => $dbIndex) {
         /** @var \Phalcon\Db\Index $dbIndex */
         $indexDefinition = [];
         foreach ($dbIndex->getColumns() as $indexColumn) {
             $indexDefinition[] = "'" . $indexColumn . "'";
         }
         $indexesDefinition[] = $snippet->getIndexDefinition($indexName, $indexDefinition, $dbIndex->getType());
     }
     $referencesDefinition = [];
     $references = self::$_connection->describeReferences($table, $defaultSchema);
     foreach ($references as $constraintName => $dbReference) {
         $columns = [];
         foreach ($dbReference->getColumns() as $column) {
             $columns[] = "'" . $column . "'";
         }
         $referencedColumns = [];
         foreach ($dbReference->getReferencedColumns() as $referencedColumn) {
             $referencedColumns[] = "'" . $referencedColumn . "'";
         }
         $referenceDefinition = [];
         $referenceDefinition[] = "'referencedSchema' => '" . $dbReference->getReferencedSchema() . "'";
         $referenceDefinition[] = "'referencedTable' => '" . $dbReference->getReferencedTable() . "'";
         $referenceDefinition[] = "'columns' => [" . join(",", $columns) . "]";
         $referenceDefinition[] = "'referencedColumns' => [" . join(",", $referencedColumns) . "]";
         $referenceDefinition[] = "'onUpdate' => '" . $dbReference->getOnUpdate() . "'";
         $referenceDefinition[] = "'onDelete' => '" . $dbReference->getOnDelete() . "'";
         $referencesDefinition[] = $snippet->getReferenceDefinition($constraintName, $referenceDefinition);
     }
     $optionsDefinition = [];
     $tableOptions = self::$_connection->tableOptions($table, $defaultSchema);
     foreach ($tableOptions as $optionName => $optionValue) {
         if (self::$_skipAI && strtoupper($optionName) == "AUTO_INCREMENT") {
             $optionValue = '';
         }
         $optionsDefinition[] = "'" . strtoupper($optionName) . "' => '" . $optionValue . "'";
     }
     $classVersion = preg_replace('/[^0-9A-Za-z]/', '', $version);
     $className = Text::camelize($table) . 'Migration_' . $classVersion;
     // morph()
     $classData = $snippet->getMigrationMorph($className, $table, $tableDefinition);
     if (count($indexesDefinition)) {
         $classData .= $snippet->getMigrationDefinition('indexes', $indexesDefinition);
     }
     if (count($referencesDefinition)) {
         $classData .= $snippet->getMigrationDefinition('references', $referencesDefinition);
     }
     if (count($optionsDefinition)) {
         $classData .= $snippet->getMigrationDefinition('options', $optionsDefinition);
     }
     $classData .= "            ]\n        );\n    }\n";
     // up()
     $classData .= $snippet->getMigrationUp();
     if ($exportData == 'always') {
         $classData .= $snippet->getMigrationBatchInsert($table, $allFields);
     }
     $classData .= "\n    }\n";
     // down()
     $classData .= $snippet->getMigrationDown();
     if ($exportData == 'always') {
         $classData .= $snippet->getMigrationBatchDelete($table);
     }
     $classData .= "\n    }\n";
     // afterCreateTable()
     if ($exportData == 'oncreate') {
         $classData .= $snippet->getMigrationAfterCreateTable($table, $allFields);
     }
     // end of class
     $classData .= "\n}\n";
     // dump data
     if ($exportData == 'always' || $exportData == 'oncreate') {
         $fileHandler = fopen(self::$_migrationPath . $version . '/' . $table . '.dat', 'w');
         $cursor = self::$_connection->query('SELECT * FROM ' . $table);
         $cursor->setFetchMode(Db::FETCH_ASSOC);
         while ($row = $cursor->fetchArray()) {
             $data = [];
             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);
     }
     return $classData;
 }