Development

Changeset 10225

You must first sign up to be able to contribute.

Changeset 10225

Show
Ignore:
Timestamp:
07/11/08 20:29:49 (5 years ago)
Author:
Kris.Wallsmith
Message:

sfPropelMigrationsLightPlugin:

  • Added symfony 1.1 tasks
  • Added auto-generation of first migration
  • Added ->loadSql() method to run SQL from a file
  • Coding standards fixes
  • Set svn:eol-style and svn:keyword properties
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • plugins/sfPropelMigrationsLightPlugin/trunk/LICENSE

    • Property svn:eol-style set to native
    r5481 r10225  
    1 Copyright (c) 2006-2007 Martin Kreidenweis 
     1Copyright (c) 2006-2008 Martin Kreidenweis 
    22 
    33Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 
  • plugins/sfPropelMigrationsLightPlugin/trunk/README

    • Property svn:eol-style set to native
    r9213 r10225  
    88 
    99This plugins is called "light", because it doesn't do any RDBMS-abstraction. So you'll have to manually write SQL code. It currently works quite alright for me, though. And you don't have to write all the SQL code manually of course. Actually you'll just make a {{{diff}}} of the {{{schema.sql}}} file created by propel and copy'n'paste the right parts of it in a new migration file. 
     10 
    1011I think something more general is planned for [http://propel.phpdb.org/trac/wiki/Development/Roadmap Propel 2.0]. 
    11  
    1212 
    1313== Installation == 
     
    2424 
    2525=== step one -- create migration === 
     26 
    2627The plugin provides an {{{init-migration}}} task. So run {{{php symfony init-migration migration_name}}}. This will generate a new migration class stub in the migrations directory. The migration name is purely informational. I doesn't have to be unique. 
    2728 
     
    4950}}} 
    5051 
     52For the special case of your first migration, the plugin will write the migration for you, using all `*.sql` files that have been automatically generated by Propel. 
     53 
    5154=== step two -- run the migration === 
    5255To actually update the database you have to run the {{{migrate}}} task.  
     
    5861(So put a call to it in your upgrade script if you have one.) 
    5962There's no harm done by calling the migrate task even if no migrations have been added. It just won't do anything. 
    60  
    6163 
    6264== More Information == 
     
    7779Then, in {{{Migration042::up()}}} you'd write {{{$this->loadFixtures();}}} at some point and it will load all the YAML files in the "042" directory. 
    7880 
    79  
    8081== Changelog == 
    8182 
     83=== 2008-07-11 | 1.1.0 (Kris.Wallsmith) === 
     84 
     85 * Added symfony 1.1 tasks 
     86 * Added auto-generation of first migration 
     87 * Added `->loadSql()` method to run SQL from a file 
     88 * Coding standards fixes 
     89 
    8290=== 2008-05-23 | 1.0.1 === 
    83 * develop7: fixed syntax error in sfMigration::addColumn() 
    84   
     91 
     92 * develop7: fixed syntax error in sfMigration::addColumn() 
     93 
    8594=== 2007-10-12 | 0.5.0 Beta === 
    8695 
    8796Finally released as a plugin. This is my first plugin, hope everything works... 
    8897Comments welcome. :) 
    89  
    9098 
    9199=== 2007-09-07 === 
  • plugins/sfPropelMigrationsLightPlugin/trunk/data/tasks/sfPakePropelMigrationsLight.php

    • Property svn:eol-style set to native
    • Property svn:keywords set to Id
    r5736 r10225  
    11<?php 
     2 
    23/* 
    34 * This file is part of the sfPropelMigrationsLightPlugin package. 
    4  * (c) 2006-2007 Martin Kreidenweis <sf@kreidenweis.com> 
    5  * 
     5 * (c) 2006-2008 Martin Kreidenweis <sf@kreidenweis.com> 
     6 *  
    67 * For the full copyright and license information, please view the LICENSE 
    78 * file that was distributed with this source code. 
     
    910 
    1011/** 
     12 * Symfony 1.0 tasks for sfPropelMigrationsLightPlugin. 
     13 *  
    1114 * @package    symfony 
    1215 * @subpackage plugin 
     
    2528  if (count($args) == 0) 
    2629  { 
    27     throw new Exception('You must provide a migration name.'); 
     30    throw new sfException('You must provide a migration name.'); 
    2831  } 
    2932 
    30   if($args[0]) 
     33  if ($args[0]) 
    3134  { 
    3235    $migrator = new sfMigrator(); 
    33      
     36 
    3437    if (!is_dir($migrator->getMigrationsDir())) 
    3538    { 
    3639      pake_mkdirs($migrator->getMigrationsDir()); 
    3740    } 
    38      
    39     pake_echo_action("migrations", "generating new migration stub"); 
     41 
     42    pake_echo_action('migrations', 'generating new migration stub'); 
    4043    $filename = $migrator->generateMigration($args[0]); 
    41     pake_echo_action("file+", $filename); 
     44    pake_echo_action('file+', $filename); 
    4245  } 
    4346} 
    44  
    4547 
    4648function run_migrate($task, $args) 
     
    4850  if (count($args) == 0) 
    4951  { 
    50     throw new Exception('You must provide a app.'); 
     52    throw new sfException('You must provide a app.'); 
    5153  } 
    5254 
     
    6163  define('SF_ROOT_DIR',    sfConfig::get('sf_root_dir')); 
    6264  define('SF_APP',         $app); 
    63   define('SF_ENVIRONMENT', ($env)?$env:'cli'); 
     65  define('SF_ENVIRONMENT', $env ? $env : 'cli'); 
    6466  define('SF_DEBUG',       true); 
    6567 
     
    7072  $databaseManager->initialize(); 
    7173 
    72    
    7374  $migrator = new sfMigrator(); 
    74    
     75 
    7576  // if no other arguments besides app, then migrate to latest version 
    7677  if (count($args) == 1)  
     
    7879    $runMigrationsCount = $migrator->migrate(); 
    7980  } 
    80   elseif (isset($args[1]) && preg_match('/^\d+$/', $args[1])) 
     81  elseif (isset($args[1]) && ctype_digit($args[1])) 
    8182  { 
    82     $runMigrationsCount = $migrator->migrate((int)$args[1]); 
     83    $runMigrationsCount = $migrator->migrate($args[1]); 
    8384  } 
    8485  else 
    8586  { 
    86     throw new Exception("You can provide a destination migration number as a second parameter"); 
     87    throw new sfException('You can provide a destination migration number as a second parameter'); 
    8788  } 
    88    
     89 
    8990  $currentVersion = $migrator->getCurrentVersion(); 
    90    
    91   pake_echo_action("migrations", "migrated ".$runMigrationsCount." step(s)"); 
    92   pake_echo_action("migrations", "current database version: ".$currentVersion); 
     91 
     92  pake_echo_action('migrations', 'migrated '.$runMigrationsCount.' step(s)'); 
     93  pake_echo_action('migrations', 'current database version: '.$currentVersion); 
    9394} 
  • plugins/sfPropelMigrationsLightPlugin/trunk/lib/sfMigration.class.php

    • Property svn:eol-style set to native
    • Property svn:keywords set to Id
    r9603 r10225  
    11<?php 
     2 
    23/* 
    34 * This file is part of the sfPropelMigrationsLightPlugin package. 
    4  * (c) 2006-2007 Martin Kreidenweis <sf@kreidenweis.com> 
    5  * 
     5 * (c) 2006-2008 Martin Kreidenweis <sf@kreidenweis.com> 
     6 *  
    67 * For the full copyright and license information, please view the LICENSE 
    78 * file that was distributed with this source code. 
     
    910 
    1011/** 
    11  * Base class for all Migrations 
    12  * 
     12 * Base class for all migrations. 
     13 *  
    1314 * @package    symfony 
    1415 * @subpackage plugin 
     
    1819abstract class sfMigration 
    1920{ 
    20   private $migrator = null; 
    21   private $migrationNumber = null; 
    22  
    23   /** 
    24    * constructor 
    25    * 
    26    * @param sfMigrator $migrator   the migrator instance calling this migration 
    27    * @param int $migrationNumber  the DB version the migration (up) will migrates to 
     21  protected 
     22    $migrator        = null, 
     23    $migrationNumber = null; 
     24 
     25  /** 
     26   * Constructor. 
     27   *  
     28   * @param sfMigrator $migrator        The migrator instance calling this migration 
     29   * @param integer    $migrationNumber The DB version the migration (up) will migrate to 
    2830   */ 
    2931  public function __construct(sfMigrator $migrator, $migrationNumber) 
     
    3234    $this->migrationNumber = $migrationNumber; 
    3335  } 
    34    
    35   /** 
    36    * returns the migrator instance that called the migration 
    37    * 
     36 
     37  /** 
     38   * Get the migrator instance that called this migration. 
     39   *  
    3840   * @return sfMigrator 
    3941   */ 
     
    4244    return $this->migrator; 
    4345  } 
    44    
    45   /** 
    46    * returns the Propel connection 
    47    * 
    48    * @return Connection 
     46 
     47  /** 
     48   * Get the Propel connection. 
     49   *  
     50   * @return mixed 
    4951   */ 
    5052  protected function getConnection() 
     
    5254    return Propel::getConnection(); 
    5355  } 
    54    
    55   /** 
    56    * returns the migration number of this migration 
    57    * 
    58    * @param mixed $formatted  if true the result is a zero-padded string, otherwise an int is returned 
    59    * @return mixed 
     56 
     57  /** 
     58   * Get the migration number of this migration. 
     59   *  
     60   * @param   boolean $formatted If true the result is a zero-padded string, otherwise an integer is returned 
     61   *  
     62   * @return  mixed 
    6063   */ 
    6164  protected function getMigrationNumber($formatted = true) 
    6265  { 
    63     if ($formatted) 
    64     { 
    65       return sprintf("%03d", $this->migrationNumber); 
    66     } 
    67     else 
    68     { 
    69       return (int)$this->migrationNumber; 
    70     } 
    71   } 
    72    
    73   /** 
    74    * Executes a SQL statement, returns the number of affected rows 
    75    * 
    76    * @param string $sql the SQL code to execute 
    77    * @return number of affected rows 
    78    * @throws SQLException 
    79    */ 
    80   protected final function executeSQL($sql) 
     66    return $formatted ? sprintf('%03d', $this->migrationNumber) : (int) $this->migrationNumber; 
     67  } 
     68 
     69  /** 
     70   * Execute a SQL statement. 
     71   *  
     72   * @param   string $sql the SQL code to execute 
     73   *  
     74   * @return  integer Number of affected rows 
     75   */ 
     76  protected function executeSQL($sql) 
    8177  { 
    8278    return sfMigrator::executeUpdate($sql); 
     
    8480 
    8581  /** 
    86    * Executes the SQL query and returns the resultset
    87    *  
    88    * @param string $sql The SQL statement. 
    89    * @param int $fetchmode 
    90    * @return object ResultSet 
    91    * @throws SQLException if a database access error occurs. 
    92    */ 
    93   protected final function executeQuery($sql, $fetchmode = null) 
     82   * Execute a SQL query
     83   *  
     84   * @param   string $sql The SQL statement. 
     85   * @param   integer $fetchmode 
     86   *  
     87   * @return  mixed 
     88   */ 
     89  protected function executeQuery($sql, $fetchmode = null) 
    9490  { 
    9591    return sfMigrator::executeQuery($sql, $fetchmode); 
     
    9793 
    9894  /** 
    99    * Adds a column to an existing table  
     95   * Add a column to an existing table. 
    10096   * 
    10197   * @param  string  $table   the table name 
     
    107103  protected function addColumn($table, $column, $type, $notNull = false, $default = null) 
    108104  { 
    109     $sql = "ALTER TABLE $table ADD COLUMN $column $type"; 
    110     if ($notNull) {  
    111       $sql .= " NOT NULL"; 
    112     } 
    113     if ($default !== null) {  
    114       if (!is_int($default)) { 
    115         $default = "'" . $default . "'"; 
     105    $sql = sprintf('ALTER TABLE %s ADD COLUMN %s %s', $table, $column, $type); 
     106 
     107    if ($notNull) 
     108    { 
     109      $sql .= ' NOT NULL'; 
     110    } 
     111 
     112    if (!is_null($default)) 
     113    { 
     114      if (!ctype_digit($default)) 
     115      { 
     116        $default = '"'.$default.'"'; 
    116117      } 
    117       $sql .= " DEFAULT $default";  
    118     } 
    119  
    120     return self::executeSQL($sql); 
     118 
     119      $sql .= ' DEFAULT '.$default; 
     120    } 
     121 
     122    return $this->executeSQL($sql); 
    121123  } 
    122124 
    123125  /** 
    124126   * Loads the fixture files of the migration. 
     127   *  
    125128   * Has to be called manually. 
    126    * 
    127    * Be careful. Due to the nature Propel and fixture-loading works you'll probably get problems 
    128    * when you change the definitions of affected tables in later migrations. 
    129    * 
    130    * @param bool $deleteOldRecords  whether the affected tables' content should be deleted prior to loading the fixtures, default: false 
     129   *  
     130   * Be careful. Due to the nature Propel and fixture-loading works you'll  
     131   * probably get problems when you change the definitions of affected tables  
     132   * in later migrations. 
     133   *  
     134   * @param boolean $deleteOldRecords Whether the affected tables' content should be deleted prior to loading the fixtures, default: false 
    131135   */ 
    132136  protected function loadFixtures($deleteOldRecords = false) 
    133137  { 
    134     $fixturesDir = $this->getMigrator()->getMigrationsFixturesDir() . DIRECTORY_SEPARATOR . $this->getMigrationNumber(); 
    135      
     138    $fixturesDir = $this->getMigrator()->getMigrationsFixturesDir().DIRECTORY_SEPARATOR.$this->getMigrationNumber(); 
     139 
    136140    if (!is_dir($fixturesDir)) 
    137141    { 
    138       throw new sfException("no fixtures exist for migration " . $this->getMigrationNumber()); 
    139     } 
    140      
     142      throw new sfException('No fixtures exist for migration '.$this->getMigrationNumber()); 
     143    } 
     144 
    141145    $data = new sfPropelData(); 
    142146    $data->setDeleteCurrentData($deleteOldRecords); 
     
    145149 
    146150  /** 
    147    * begins a transaction 
     151   * Execute SQL from a file. 
     152   *  
     153   * @param   string $file Path to the SQL file 
     154   */ 
     155  protected function loadSql($file) 
     156  { 
     157    if (!is_readable($file)) 
     158    { 
     159      throw new sfException(sprintf('The SL file %s does not exist or is not readable.', $file)); 
     160    } 
     161 
     162    foreach (explode(';', file_get_contents($file)) as $query) 
     163    { 
     164      if (trim($query)) 
     165      { 
     166        $this->executeQuery($query); 
     167      } 
     168    } 
     169  } 
     170 
     171  /** 
     172   * Begin a transaction. 
    148173   */ 
    149174  protected function begin() 
    150175  { 
    151     $this->getConnection()->begin(); 
    152   } 
    153  
    154   /** 
    155    * commits transaction 
     176    $con = $this->getConnection(); 
     177 
     178    $con instanceof PropelPDO ? $con->beginTransaction() : $con->begin(); 
     179  } 
     180 
     181  /** 
     182   * Commit a transaction. 
    156183   */ 
    157184  protected function commit() 
     
    161188 
    162189  /** 
    163    * rolls back transaction 
     190   * Rollback a transaction. 
    164191   */ 
    165192  protected function rollback() 
     
    169196 
    170197  /** 
    171    * output some diagnostic or informational message 
     198   * Output some diagnostic or informational message. 
     199   *  
     200   * @param   string $text 
    172201   */ 
    173202  protected function diag($text) 
     
    178207 
    179208  /** 
    180    * bring the Database Schema up to the current Version from the previous one 
     209   * Migrate the schema up, from the previous version to the current one. 
    181210   */ 
    182211  abstract public function up(); 
    183212 
    184213  /** 
    185    * bring the schema down to the previous version, i.e. undo the modifications made in up() 
     214   * Migrate the schema down to the previous version, i.e. undo the modifications made in up() 
    186215   */ 
    187216  abstract public function down(); 
  • plugins/sfPropelMigrationsLightPlugin/trunk/lib/sfMigrator.class.php

    • Property svn:eol-style set to native
    • Property svn:keywords set to Id
    r6149 r10225  
    11<?php 
     2 
    23/* 
    34 * This file is part of the sfPropelMigrationsLightPlugin package. 
    4  * (c) 2006-2007 Martin Kreidenweis <sf@kreidenweis.com> 
    5  * 
     5 * (c) 2006-2008 Martin Kreidenweis <sf@kreidenweis.com> 
     6 *  
    67 * For the full copyright and license information, please view the LICENSE 
    78 * file that was distributed with this source code. 
    89 */ 
    910 
    10  
    1111/** 
    12  * manages all calls to the sfMigration class instances  
     12 * Manage all calls to the sfMigration class instances. 
    1313 *  
    1414 * @package    symfony 
     
    2020{ 
    2121  /** 
    22    * string array of migration files' names 
    23    * 
     22   * Migration filenames. 
     23   *  
    2424   * @var array $migrations 
    2525   */ 
    26   private $migrations = array(); 
    27    
     26  protected $migrations = array(); 
     27 
     28  /** 
     29   * Perform an update on the database. 
     30   *  
     31   * @param   string $sql 
     32   *  
     33   * @return  integer 
     34   */ 
     35  static public function executeUpdate($sql) 
     36  { 
     37    $con = Propel::getConnection(); 
     38 
     39    return $con instanceof PropelPDO ? $con->exec($sql) : $con->executeUpdate($sql); 
     40  } 
     41 
     42  /** 
     43   * Perform a query on the database. 
     44   *  
     45   * @param   string $sql 
     46   * @param   string $fetchmode 
     47   *  
     48   * @return  mixed 
     49   */ 
     50  static public static function executeQuery($sql, $fetchmode = null) 
     51  { 
     52    $con = Propel::getConnection(); 
     53     
     54    if ($con instanceof PropelPDO) 
     55    { 
     56      $stmt = $con->prepare($sql); 
     57      $stmt->execute(); 
     58 
     59      return $stmt; 
     60    } 
     61    else 
     62    { 
     63      return $con->executeQuery($sql, $fetchmode); 
     64    } 
     65  } 
     66 
     67  /** 
     68   * Constructor. 
     69   */ 
    2870  public function __construct() 
    2971  { 
     
    3274 
    3375  /** 
    34    * does all the migrating 
    35    * 
    36    * @param int $destVersion version number to migrate to, default: migrates to max existing 
    37    * @return int number of executed migrations 
     76   * Execute migrations. 
     77   *  
     78   * @param   integer $destVersion  Version number to migrate to, defaults to  
     79   *                                the max existing 
     80   *  
     81   * @return  integer Number of executed migrations 
    3882   */ 
    3983  public function migrate($destVersion = null) 
    4084  { 
    4185    $maxVersion = $this->getMaxVersion(); 
    42     if ($destVersion === null)  
     86    if ($destVersion === null) 
    4387    { 
    4488      $destVersion = $maxVersion; 
     
    4690    else 
    4791    { 
    48       $destVersion = (int)$destVersion; 
     92      $destVersion = (int) $destVersion; 
     93 
    4994      if (($destVersion > $maxVersion) || ($destVersion < 0)) 
    5095      { 
    51         throw new sfException("Migration $destVersion does not exist."); 
    52       } 
    53     } 
    54      
     96        throw new sfException(sprintf('Migration %d does not exist.', $destVersion)); 
     97      } 
     98    } 
     99 
    55100    $sourceVersion = $this->getCurrentVersion(); 
    56      
     101 
    57102    // do appropriate stuff according to migration direction 
    58103    if ($destVersion == $sourceVersion) 
     
    60105      return 0; 
    61106    } 
    62     else if ($destVersion < $sourceVersion) 
     107    elseif ($destVersion < $sourceVersion) 
    63108    { 
    64109      $res = $this->migrateDown($sourceVersion, $destVersion); 
    65110    } 
    66     else  
    67     {  
    68       $res = $this->migrateUp($sourceVersion, $destVersion);  
    69     } 
    70          
     111    else 
     112    { 
     113      $res = $this->migrateUp($sourceVersion, $destVersion); 
     114    } 
     115 
    71116    return $res; 
    72117  } 
    73    
    74   /** 
    75    * Generates a new, emtpy migration stub 
    76    *  
    77    * @param string $name  name of the new migration 
    78    * @return string       filename of the new migration file 
     118 
     119  /** 
     120   * Generate a new migration stub 
     121   *  
     122   * @param   string $name Name of the new migration 
     123   *  
     124   * @return  string Filename of the new migration file 
    79125   */ 
    80126  public function generateMigration($name)  
    81127  { 
    82     $template = "<?php 
    83  
    84 class %MigrationClassName% extends sfMigration { 
    85   public function up()  
    86   { 
    87      
    88   } 
    89  
    90   public function down()  
    91   { 
    92      
    93   } 
    94 } 
    95 "; 
    96      
    97128    // calculate version number for new migration 
    98     $maxVersion = (int)$this->getMaxVersion(); 
    99     $newVersion = sprintf("%03d", $maxVersion + 1); 
    100      
    101     // generate new migration class stub 
    102     $newClass = str_replace('%MigrationClassName%', 'Migration'.$newVersion, $template); 
    103      
     129    $maxVersion = sprintf('%03d', $this->getMaxVersion()); 
     130    $newVersion = sprintf('%03d', $maxVersion + 1); 
     131 
    104132    // sanitize name 
    105133    $name = preg_replace('/[^a-zA-Z0-9]/', '_', $name); 
    106      
     134 
     135    $upLogic = ''; 
     136    $downLogic = ''; 
     137 
     138    if ('001' == $newVersion) 
     139    { 
     140      $this->generateFirstMigrationLogic($name, $newVersion, $upLogic, $downLogic); 
     141    } 
     142 
     143    $newClass = <<<EOF 
     144<?php 
     145 
     146/** 
     147 * Migrations between versions $maxVersion and $newVersion. 
     148 */ 
     149class Migration$newVersion extends sfMigration 
     150
     151  /** 
     152   * Migrate up to version $newVersion. 
     153   */ 
     154  public function up() 
     155  { 
     156    $upLogic 
     157  } 
     158 
     159  /** 
     160   * Migrate down to version $maxVersion. 
     161   */ 
     162  public function down() 
     163  { 
     164    $downLogic 
     165  } 
     166
     167 
     168EOF; 
     169 
    107170    // write new migration stub 
    108171    $newFileName = $this->getMigrationsDir().DIRECTORY_SEPARATOR.$newVersion.'_'.$name.'.php'; 
    109172    file_put_contents($newFileName, $newClass); 
    110      
     173 
    111174    return $newFileName; 
    112175  } 
    113    
    114   /** 
    115    * Writes the given version as current version to the database 
     176 
     177  /** 
     178   * Get the list of migration filenames. 
     179   *  
     180   * @return array 
     181   */ 
     182  public function getMigrations() 
     183  { 
     184    return $this->migrations; 
     185  } 
     186 
     187  /** 
     188   * @return integer The lowest migration that exists 
     189   */ 
     190  public function getMinVersion()  
     191  { 
     192    return $this->migrations ? $this->getMigrationNumberFromFile($this->migrations[0]) : 0; 
     193  } 
     194 
     195  /** 
     196   * @return integer The highest existing migration that exists 
     197   */ 
     198  public function getMaxVersion() 
     199  { 
     200    $count = count($this->migrations); 
     201 
     202    return $count ? $this->getMigrationNumberFromFile($this->migrations[$count - 1]) : 0; 
     203  } 
     204 
     205  /** 
     206   * Get the current schema version from the database. 
     207   *  
     208   * If no schema version is currently stored in the database, one is created  
     209   * and initialized with 0. 
    116210   * 
    117    * @param int $version  new current version 
    118    */ 
    119   protected function setCurrentVersion($version) 
    120   { 
    121     $version = (int)$version; 
    122  
    123     self::executeUpdate("UPDATE schema_info SET version = $version"); 
    124   } 
    125  
    126   /** 
    127    * migrates down from version $from to version $to 
    128    * 
    129    * @param int $from 
    130    * @param int $to 
    131    * @return int number of executed migrations 
    132    */ 
    133   protected function migrateDown($from, $to)  
    134   { 
    135     $con = Propel::getConnection(); 
    136     $counter = 0; 
    137      
    138     // iterate over all needed migrations 
    139     for ($i = $from; $i > $to; $i--) 
    140     { 
    141       if ($con instanceof PropelPDO) { 
    142         $con->beginTransaction(); 
    143       } else { 
    144         $con->begin(); 
    145       } 
    146       try 
    147       { 
    148         $migration = $this->getMigrationObject($i); 
    149         $migration->down(); 
    150          
    151         $this->setCurrentVersion($i-1); 
    152          
    153         $con->commit(); 
    154       } 
    155       catch (Exception $e) 
    156       { 
    157         $con->rollback(); 
    158         throw $e; 
    159       } 
    160        
    161       $counter++; 
    162     } 
    163      
    164     return $counter; 
    165   } 
    166    
    167   /** 
    168    * migrates up from version $from to version $to 
    169    *  
    170    * @param int $from 
    171    * @param int $to 
    172    * @return int number of executed migrations 
    173    */ 
    174   protected function migrateUp($from, $to)  
    175   { 
    176     $con = Propel::getConnection(); 
    177     $counter = 0; 
    178  
    179     // iterate over all needed migrations 
    180     for ($i = $from + 1; $i <= $to; $i++) 
    181     { 
    182       if ($con instanceof PropelPDO) { 
    183         $con->beginTransaction(); 
    184       } else { 
    185         $con->begin(); 
    186       } 
    187       try 
    188       { 
    189         $migration = $this->getMigrationObject($i); 
    190         $migration->up(); 
    191          
    192         $this->setCurrentVersion($i); 
    193          
    194         $con->commit(); 
    195       } 
    196       catch (Exception $e) 
    197       { 
    198         $con->rollback(); 
    199         throw $e; 
    200       } 
    201          
    202       $counter++; 
    203     } 
    204  
    205     return $counter; 
    206   } 
    207    
    208   /** 
    209    * returns the migration object for the given version 
    210    * 
    211    * @param int $version 
    212    * @return sfMigration 
    213    */ 
    214   protected function getMigrationObject($version) 
    215   { 
    216     $file = $this->getMigrationFileName($version); 
    217  
    218     // load the migration class 
    219     require_once($file); 
    220     $migrationClass = 'Migration'.$this->getMigrationNumberFromFile($file); 
    221      
    222     return new $migrationClass($this, $version); 
    223   } 
    224    
    225   /** 
    226    * version to filename 
    227    * 
    228    * @param int $version 
    229    * @return string filename 
    230    */ 
    231   protected function getMigrationFileName($version) 
    232   { 
    233     return $this->migrations[$version-1]; 
    234   } 
    235      
    236   /** 
    237    * loads all migration file names 
    238    */ 
    239   protected function loadMigrations()  
    240   { 
    241     $this->migrations = sfFinder::type('file')->name('/^\d{3}.*\.php$/')->maxdepth(0)->in($this->getMigrationsDir()); 
    242      
    243     sort($this->migrations); 
    244  
    245     if (count($this->migrations) > 0) 
    246     { 
    247       $minVersion = $this->getMinVersion(); 
    248       $maxVersion = $this->getMaxVersion(); 
    249  
    250       if ($minVersion != 1)  
    251       { 
    252         throw new sfInitializationException("First migration is not migration 1. Some migration files may be missing."); 
    253       } 
    254        
    255       if (($maxVersion - $minVersion + 1) != count($this->migrations)) 
    256       { 
    257         throw new sfInitializationException("Migration count unexpected. Migration files may be missing. Migration numbers must be unique."); 
    258       } 
    259     } 
    260   } 
    261    
    262   /** 
    263    * returns the list of migration filenames 
    264    * 
    265    * @return array 
    266    */ 
    267   public function getMigrations()  
    268   { 
    269     return $this->migrations; 
    270   } 
    271    
    272   /** 
    273    * @return the lowest migration that exists 
    274    */ 
    275   public function getMinVersion()  
    276   { 
    277     if (count($this->migrations) == 0) 
    278     { 
    279       return 0; 
    280     } 
    281     else 
    282     { 
    283       return $this->getMigrationNumberFromFile($this->migrations[0]); 
    284     } 
    285   } 
    286  
    287   /** 
    288    * @return the highest existing migration number 
    289    */ 
    290   public function getMaxVersion() 
    291   { 
    292     if (count($this->migrations) == 0) 
    293     { 
    294       return 0; 
    295     } 
    296     else 
    297     { 
    298       return $this->getMigrationNumberFromFile($this->migrations[count($this->migrations)-1]); 
    299     }   
    300   } 
    301    
    302   /** 
    303    * retrives the current schema version from the database 
    304    *  
    305    * if no schema version is currently stored in the database,  
    306    * one is created and initialized with 0 
    307    * 
    308    * @return int 
     211   * @return integer 
    309212   */ 
    310213  public function getCurrentVersion()  
    311214  { 
    312215    // check if schema_info table exists 
    313     $result = self::executeQuery("SHOW TABLES LIKE 'schema_info'"); 
    314  
    315     $exists = false; 
    316     if ($result instanceof PDOStatement) { 
    317       $exists = ($result->rowCount() == 1); 
    318     } else { 
    319       $exists = ($result->getRecordCount() == 1); 
    320     } 
    321      
    322     if ($exists) 
    323     { 
    324       $result = self::executeQuery("SELECT version FROM schema_info"); 
    325  
    326       if ($result instanceof PDOStatement)  
     216    $result = $this->executeQuery('SHOW TABLES LIKE "schema_info"'); 
     217 
     218    if ($result instanceof PDOStatement ? $result->rowCount() : $result->getRecordCount()) 
     219    { 
     220      $result = $this->executeQuery('SELECT version FROM schema_info'); 
     221 
     222      if ($result instanceof PDOStatement) 
    327223      { 
    328224        $currentVersion = $result->fetchColumn(0); 
    329       }  
    330       else  
     225      } 
     226      else 
    331227      { 
    332228        if ($result->next()) 
     
    336232        else 
    337233        { 
    338           throw new sfDatabaseException("unable to retrieve current schema version"); 
     234          throw new sfDatabaseException('Unable to retrieve current schema version.'); 
    339235        } 
    340236      } 
     
    342238    else 
    343239    { 
    344       // no schema_info table exists yet 
    345       // so we create it 
    346       self::executeUpdate("CREATE TABLE schema_info (version INTEGER UNSIGNED)"); 
    347       // and insert the version record 
    348       // if no schema_info existed before, we'll call that version 0 
    349       self::executeUpdate("INSERT INTO schema_info SET version = 0"); 
     240      // no schema_info table exists yet so we create it 
     241      $this->executeUpdate('CREATE TABLE schema_info (version INTEGER UNSIGNED)'); 
     242 
     243      // and insert the version record as 0 
     244      $this->executeUpdate('INSERT INTO schema_info SET version = 0'); 
    350245      $currentVersion = 0; 
    351246    } 
    352      
     247 
    353248    return $currentVersion; 
    354249  } 
    355250   
    356251  /** 
    357    * returns the number encoded in the given migration file name 
    358    *  
    359    * @param string $file the filename to look at 
     252   * Get the number encoded in the given migration file name. 
     253   *  
     254   * @param   string $file The filename to look at 
     255   *  
     256   * @return  integer 
    360257   */ 
    361258  public function getMigrationNumberFromFile($file)  
    362259  { 
    363     $matches = array(); 
    364     $match_count = preg_match('#'.preg_quote(DIRECTORY_SEPARATOR, '#').'(\d{3}).*\.php$#', $file, $matches); 
    365     $number = $matches[1]; 
    366      
    367     if ($match_count < 1) { 
    368       throw new sfParseException("Migration filename could not be parsed."); 
    369     } 
    370      
     260    $number = substr(basename($file), 0, 3); 
     261 
     262    if (!ctype_digit($number)) 
     263    { 
     264      throw new sfParseException('Migration filename could not be parsed.'); 
     265    } 
     266 
    371267    return $number; 
    372268  } 
     269 
     270  /** 
     271   * Get the directory where migration classes are saved. 
     272   *  
     273   * @return  string 
     274   */ 
     275  public function getMigrationsDir()  
     276  { 
     277    return sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'migrations'; 
     278  } 
     279 
     280  /** 
     281   * Get the directory where migration fixtures are saved. 
     282   *  
     283   * @return  string 
     284   */ 
     285  public function getMigrationsFixturesDir() 
     286  { 
     287    return $this->getMigrationsDir().DIRECTORY_SEPARATOR.'fixtures'; 
     288  } 
     289 
     290  /** 
     291   * Write the given version as current version to the database. 
     292   *  
     293   * @param integer $version New current version 
     294   */ 
     295  protected function setCurrentVersion($version) 
     296  { 
     297    $version = (int) $version; 
     298 
     299    $this->executeUpdate("UPDATE schema_info SET version = $version"); 
     300  } 
     301 
     302  /** 
     303   * Migrate down, from version $from to version $to. 
     304   *  
     305   * @param   integer $from 
     306   * @param   integer $to 
     307   *  
     308   * @return  integer Number of executed migrations 
     309   */ 
     310  protected function migrateDown($from, $to) 
     311  { 
     312    $con = Propel::getConnection(); 
     313    $counter = 0; 
     314 
     315    // iterate over all needed migrations 
     316    for ($i = $from; $i > $to; $i--) 
     317    { 
     318      try 
     319      { 
     320        $con instanceof PropelPDO ? $con->beginTransaction() : $con->begin(); 
     321 
     322        $migration = $this->getMigrationObject($i); 
     323        $migration->down(); 
     324 
     325        $this->setCurrentVersion($i-1); 
     326 
     327        $con->commit(); 
     328      } 
     329      catch (Exception $e) 
     330      { 
     331        $con->rollback(); 
     332        throw $e; 
     333      } 
     334 
     335      $counter++; 
     336    } 
     337 
     338    return $counter; 
     339  } 
     340 
     341  /** 
     342   * Migrate up, from version $from to version $to. 
     343   *  
     344   * @param   integer $from 
     345   * @param   integer $to 
     346   * @return  integer Number of executed migrations 
     347   */ 
     348  protected function migrateUp($from, $to) 
     349  { 
     350    $con = Propel::getConnection(); 
     351    $counter = 0; 
     352 
     353    // iterate over all needed migrations 
     354    for ($i = $from + 1; $i <= $to; $i++) 
     355    { 
     356      try 
     357      { 
     358        $con instanceof PropelPDO ? $con->beginTransaction() : $con->begin(); 
     359 
     360        $migration = $this->getMigrationObject($i); 
     361        $migration->up(); 
     362 
     363        $this->setCurrentVersion($i); 
     364 
     365        $con->commit(); 
     366      } 
     367      catch (Exception $e) 
     368      { 
     369        $con->rollback(); 
     370        throw $e; 
     371      } 
     372 
     373      $counter++; 
     374    } 
     375 
     376    return $counter; 
     377  } 
     378 
     379  /** 
     380   * Get the migration object for the given version. 
     381   *  
     382   * @param   integer $version 
     383   *  
     384   * @return  sfMigration 
     385   */ 
     386  protected function getMigrationObject($version) 
     387  { 
     388    $file = $this->getMigrationFileName($version); 
     389 
     390    // load the migration class 
     391    require_once $file; 
     392    $migrationClass = 'Migration'.$this->getMigrationNumberFromFile($file); 
     393 
     394    return new $migrationClass($this, $version); 
     395  } 
     396 
     397  /** 
     398   * Version to filename. 
     399   * 
     400   * @param   integer $version 
     401   *  
     402   * @return  string Filename 
     403   */ 
     404  protected function getMigrationFileName($version) 
     405  { 
     406    return $this->migrations[$version-1]; 
     407  } 
     408 
     409  /** 
     410   * Load all migration file names. 
     411   */ 
     412  protected function loadMigrations() 
     413  { 
     414    $this->migrations = sfFinder::type('file')->name('/^\d{3}.*\.php$/')->maxdepth(0)->in($this->getMigrationsDir()); 
     415 
     416    sort($this->migrations); 
     417 
     418    if (count($this->migrations) > 0) 
     419    { 
     420      $minVersion = $this->getMinVersion(); 
     421      $maxVersion = $this->getMaxVersion(); 
     422 
     423      if (1 != $minVersion)  
     424      { 
     425        throw new sfInitializationException('First migration is not migration 1. Some migration files may be missing.'); 
     426      } 
     427 
     428      if (($maxVersion - $minVersion + 1) != count($this->migrations)) 
     429      { 
     430        throw new sfInitializationException('Migration count unexpected. Migration files may be missing. Migration numbers must be unique.'); 
     431      } 
     432    } 
     433  } 
    373434   
    374   public function getMigrationsDir()  
    375   { 
    376     return sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'migrations'; 
    377   } 
    378    
    379   public function getMigrationsFixturesDir() 
    380   { 
    381     return $this->getMigrationsDir().DIRECTORY_SEPARATOR.'fixtures'; 
    382   } 
    383    
    384   public static function executeUpdate($sql) 
    385   { 
    386     $connection = Propel::getConnection(); 
    387      
    388     if (version_compare(Propel::VERSION, "1.3.x", ">=")) { 
    389       return $connection->exec($sql); 
    390     } else { 
    391       return $connection->executeUpdate($sql); 
    392     } 
    393   } 
    394    
    395   public static function executeQuery($sql, $fetchmode = null) 
    396   { 
    397     $connection = Propel::getConnection(); 
    398      
    399     if (version_compare(Propel::VERSION, "1.3.x", ">="))  
    400     { 
    401       $stmt = $connection->prepare($sql); 
    402       $stmt->execute(); 
    403        
    404       return $stmt; 
    405     } 
    406     else  
    407     { 
    408       return $connection->executeQuery($sql, $fetchmode); 
     435  /** 
     436   * Auto generate logic for the first migration. 
     437   *  
     438   * @param   string $name 
     439   * @param   string $newVersion 
     440   * @param   string $upLogic 
     441   * @param   string $downLogic 
     442   */ 
     443  protected function generateFirstMigrationLogic($name, $newVersion, & $upLogic, & $downLogic) 
     444  { 
     445    $sqlFiles = sfFinder::type('file')->name('*.sql')->in(sfConfig::get('sf_root_dir').'/data/sql'); 
     446    if ($sqlFiles) 
     447    { 
     448      // use propel sql files for the up logic 
     449      $sql = ''; 
     450      foreach ($sqlFiles as $sqlFile) 
     451      { 
     452        $sql .= file_get_contents($sqlFile); 
     453      } 
     454      file_put_contents($this->getMigrationsDir().DIRECTORY_SEPARATOR.$newVersion.'_'.$name.'.sql', $sql); 
     455      $upLogic .= sprintf('$this->loadSql(dirname(__FILE__).\'/%s_%s.sql\');', $newVersion, $name); 
     456 
     457      // drop tables for down logic 
     458      $downLines = array(); 
     459 
     460      // disable mysql foreign key checks 
     461      if (false !== $fkChecks = strpos($sql, 'FOREIGN_KEY_CHECKS')) 
     462      { 
     463        $downLines[] = '$this->executeSQL(\'SET FOREIGN_KEY_CHECKS=0\');'; 
     464        $downLines[] = ''; 
     465      } 
     466 
     467      preg_match_all('/DROP TABLE IF EXISTS `(\w+)`;/', $sql, $matches); 
     468      foreach ($matches[1] as $match) 
     469      { 
     470        $downLines[] = sprintf('$this->executeSQL(\'DROP TABLE %s\');', $match); 
     471      } 
     472 
     473      // enable mysql foreign key checks 
     474      if (false !== $fkChecks) 
     475      { 
     476        $downLines[] = ''; 
     477        $downLines[] = '$this->executeSQL(\'SET FOREIGN_KEY_CHECKS=1\');'; 
     478      } 
     479 
     480      $downLogic .= join("\n    ", $downLines); 
    409481    } 
    410482  } 
  • plugins/sfPropelMigrationsLightPlugin/trunk/package-sfPropelMigrationsLightPlugin.xml

    r9214 r10225  
    1818    <active>yes</active> 
    1919  </contributor> 
     20  <contributor> 
     21    <name>Kris Wallsmith</name> 
     22    <user>Kris.Wallsmith</user> 
     23    <email>kris.wallsmith@gmail.com</email> 
     24    <active>yes</active> 
     25  </contributor> 
    2026  <date>[automatic]</date> 
    2127  <version> 
    22     <release>1.0.1</release> 
    23     <api>1.0.1</api> 
     28    <release>1.1.0</release> 
     29    <api>1.1.0</api> 
    2430  </version> 
    2531  <stability> 
     
    4248        <channel>pear.symfony-project.com</channel> 
    4349        <min>0.8.1</min> 
    44         <max>1.1.0</max> 
    45         <exclude>1.1.0</exclude> 
     50        <max>1.2.0</max> 
     51        <exclude>1.2.0</exclude> 
    4652      </package> 
    4753    </required>