Commits

Phil Sturgeon committed 36b9dc1 Merge

Fixed conflict with migrations merge.

Comments (0)

Files changed (5)

application/config/migration.php

+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/*
+|--------------------------------------------------------------------------
+| Enable/Disable Migrations
+|--------------------------------------------------------------------------
+|
+| Migrations are disabled by default for security reasons.
+| You should enable migrations whenever you intend to do a schema migration
+| and disable it back when you're done.
+|
+*/
+$config['migration_enabled'] = TRUE;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations version
+|--------------------------------------------------------------------------
+|
+| This is used to set migration version that the file system should be on.
+| If you run $this->migration->latest() this is the version that schema will
+| be upgraded / downgraded to.
+|
+*/
+$config['migration_version'] = 0;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations Path
+|--------------------------------------------------------------------------
+|
+| Path to your migrations folder.
+| Typically, it will be within your application path.
+| Also, writing permission is required within the migrations path.
+|
+*/
+$config['migration_path'] = APPPATH . 'migrations/';
+
+
+/* End of file migration.php */
+/* Location: ./application/config/migration.php */

system/database/drivers/mysql/mysql_driver.php

 	 */
 	function _insert($table, $keys, $values)
 	{
-		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+		return "INSERT INTO ".$table." (`".implode('`, `', $keys)."`) VALUES (".implode(', ', $values).")";
 	}
 
 	// --------------------------------------------------------------------
 	 */
 	function _replace($table, $keys, $values)
 	{
-		return "REPLACE INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+		return "REPLACE INTO ".$table." (`".implode('`, `', $keys)."`) VALUES (".implode(', ', $values).")";
 	}
 
 	// --------------------------------------------------------------------
 	 */
 	function _insert_batch($table, $keys, $values)
 	{
-		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
+		return "INSERT INTO ".$table." (`".implode('`, `', $keys)."`) VALUES ".implode(', ', $values);
 	}
 
 	// --------------------------------------------------------------------

system/language/english/migration_lang.php

+<?php
+
+$lang['migration_none_found']			= "No migrations were found.";
+$lang['migration_not_found']			= "This migration could not be found.";
+$lang['migration_multiple_version']		= "This are multiple migrations with the same version number: %d.";
+$lang['migration_class_doesnt_exist']	= "The migration class \"%s\" could not be found.";
+$lang['migration_missing_up_method']	= "The migration class \"%s\" is missing an 'up' method.";
+$lang['migration_missing_down_method']	= "The migration class \"%s\" is missing an 'up' method.";
+$lang['migration_invalid_filename']		= "Migration \"%s\" has an invalid filename.";
+
+
+/* End of file migration_lang.php */
+/* Location: ./system/language/english/migration_lang.php */

system/libraries/Migration.php

+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package		CodeIgniter
+ * @author		EllisLab Dev Team
+ * @copyright	Copyright (c) 2006 - 2011, EllisLab, Inc.
+ * @license		http://codeigniter.com/user_guide/license.html
+ * @link		http://codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Migration Class
+ *
+ * All migrations should implement this, forces up() and down() and gives
+ * access to the CI super-global.
+ *
+ * @package		CodeIgniter
+ * @subpackage	Libraries
+ * @category	Libraries
+ * @author		Reactor Engineers
+ * @link
+ */
+class CI_Migration {
+
+	protected $_migration_enabled = FALSE;
+	protected $_migration_path = NULL;
+	protected $_migration_version = 0;
+
+	public $error = '';
+
+	public function __construct($config = array())
+	{
+		# Only run this constructor on main library load
+		if (get_parent_class($this) !== FALSE)
+		{
+			return;
+		}
+
+		foreach ($config as $key => $val)
+		{
+			$this->{'_' . $key} = $val;
+		}
+
+		log_message('debug', 'Migrations class initialized');
+
+		// Are they trying to use migrations while it is disabled?
+		if ($this->_migration_enabled !== TRUE)
+		{
+			show_error('Migrations has been loaded but is disabled or set up incorrectly.');
+		}
+
+		// If not set, set it
+		$this->_migration_path == '' OR $this->_migration_path = APPPATH . 'migrations/';
+
+		// Add trailing slash if not set
+		$this->_migration_path = rtrim($this->_migration_path, '/').'/';
+
+		// Load migration language
+		$this->lang->load('migration');
+
+		// They'll probably be using dbforge
+		$this->load->dbforge();
+
+		// If the migrations table is missing, make it
+		if ( ! $this->db->table_exists('migrations'))
+		{
+			$this->dbforge->add_field(array(
+				'version' => array('type' => 'INT', 'constraint' => 3),
+			));
+
+			$this->dbforge->create_table('migrations', TRUE);
+
+			$this->db->insert('migrations', array('version' => 0));
+		}
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Migrate to a schema version
+	 *
+	 * Calls each migration step required to get to the schema version of
+	 * choice
+	 *
+	 * @access	public
+	 * @param $version integer	Target schema version
+	 * @return	mixed	TRUE if already latest, FALSE if failed, int if upgraded
+	 */
+	public function version($target_version)
+	{
+		$start = $current_version = $this->_get_version();
+		$stop = $target_version;
+
+		if ($target_version > $current_version)
+		{
+			// Moving Up
+			++$start;
+			++$stop;
+			$step = 1;
+		}
+
+		else
+		{
+			// Moving Down
+			$step = -1;
+		}
+		
+		$method = $step === 1 ? 'up' : 'down';
+		$migrations = array();
+
+		// We now prepare to actually DO the migrations
+		// But first let's make sure that everything is the way it should be
+		for ($i = $start; $i != $stop; $i += $step)
+		{
+			$f = glob(sprintf($this->_migration_path . '%03d_*.php', $i));
+
+			// Only one migration per step is permitted
+			if (count($f) > 1)
+			{
+				$this->error = sprintf($this->lang->line('migration_multiple_version'), $i);
+				return FALSE;
+			}
+
+			// Migration step not found
+			if (count($f) == 0)
+			{
+				// If trying to migrate up to a version greater than the last
+				// existing one, migrate to the last one.
+				if ($step == 1)
+				{
+					break;
+				}
+
+				// If trying to migrate down but we're missing a step,
+				// something must definitely be wrong.
+				$this->error = sprintf($this->lang->line('migration_not_found'), $i);
+				return FALSE;
+			}
+
+			$file = basename($f[0]);
+			$name = basename($f[0], '.php');
+
+			// Filename validations
+			if (preg_match('/^\d{3}_(\w+)$/', $name, $match))
+			{
+				$match[1] = strtolower($match[1]);
+
+				// Cannot repeat a migration at different steps
+				if (in_array($match[1], $migrations))
+				{
+					$this->error = sprintf($this->lang->line('migration_multiple_version'), $match[1]);
+					return FALSE;
+				}
+
+				include $f[0];
+				$class = 'Migration_' . ucfirst($match[1]);
+
+				if ( ! class_exists($class))
+				{
+					$this->error = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
+					return FALSE;
+				}
+
+				if ( ! is_callable(array($class, $method)))
+				{
+					$this->error = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
+					return FALSE;
+				}
+
+				$migrations[] = $match[1];
+			}
+			else
+			{
+				exit('313');
+				$this->error = sprintf($this->lang->line('migration_invalid_filename'), $file);
+				return FALSE;
+			}
+		}
+
+		log_message('debug', 'Current migration: ' . $current_version);
+
+		$version = $i + ($step == 1 ? -1 : 0);
+
+		// If there is nothing to do so quit
+		if ($migrations === array())
+		{
+			return TRUE;
+		}
+
+		log_message('debug', 'Migrating from ' . $method . ' to version ' . $version);
+
+		// Loop through the migrations
+		foreach ($migrations AS $migration)
+		{
+			// Run the migration class
+			$class = 'Migration_' . ucfirst(strtolower($migration));
+			call_user_func(array(new $class, $method));
+
+			$current_version += $step;
+			$this->_update_version($current_version);
+		}
+
+		log_message('debug', 'Finished migrating to '.$current_version);
+
+		return $current_version;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set's the schema to the latest migration
+	 *
+	 * @access	public
+	 * @return	mixed	true if already latest, false if failed, int if upgraded
+	 */
+	public function latest()
+	{
+		if ( ! $migrations = $this->find_migrations())
+		{
+			$this->error = $this->line->lang('migration_none_found');
+			return false;
+		}
+
+		$last_migration = basename(end($migrations));
+		
+		// Calculate the last migration step from existing migration
+		// filenames and procceed to the standard version migration
+		return $this->version((int) substr($last_migration, 0, 3));
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set's the schema to the migration version set in config
+	 *
+	 * @access	public
+	 * @return	mixed	true if already current, false if failed, int if upgraded
+	 */
+	public function current()
+	{
+		return $this->version($this->_migration_version);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Error string
+	 *
+	 * @access	public
+	 * @return	string	Error message returned as a string
+	 */
+	public function error_string()
+	{
+		return $this->error;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set's the schema to the latest migration
+	 *
+	 * @access	protected
+	 * @return	mixed	true if already latest, false if failed, int if upgraded
+	 */
+	protected function find_migrations()
+	{
+		// Load all *_*.php files in the migrations path
+		$files = glob($this->_migration_path . '*_*.php');
+		$file_count = count($files);
+		
+		for ($i = 0; $i < $file_count; $i++)
+		{
+			// Mark wrongly formatted files as false for later filtering
+			$name = basename($files[$i], '.php');
+			if ( ! preg_match('/^\d{3}_(\w+)$/', $name))
+			{
+				$files[$i] = FALSE;
+			}
+		}
+		
+		sort($files);
+
+		return $files;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Retrieves current schema version
+	 *
+	 * @access	protected
+	 * @return	integer	Current Migration
+	 */
+	protected function _get_version()
+	{
+		$row = $this->db->get('migrations')->row();
+		return $row ? $row->version : 0;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Stores the current schema version
+	 *
+	 * @access	protected
+	 * @param $migrations integer	Migration reached
+	 * @return	void					Outputs a report of the migration
+	 */
+	protected function _update_version($migrations)
+	{
+		return $this->db->update('migrations', array(
+			'version' => $migrations
+		));
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Enable the use of CI super-global
+	 *
+	 * @access	public
+	 * @param $var
+	 * @return	mixed
+	 */
+	public function __get($var)
+	{
+		return get_instance()->$var;
+	}
+}
+
+/* End of file Migration.php */
+/* Location: ./system/libraries/Migration.php */

user_guide/changelog.html

 	<li class="reactor">Fixed issue #41: Added audio/mp3 mime type to mp3.</li>
 	<li class="reactor">Fixed a bug (Core #329) where the file caching driver referenced the incorrect cache directory.</li>
 	<li class="reactor">Fixed a bug (Reactor #69) where the SHA1 library was named incorrectly.</li>
+	<li class="reactor">MySQL Driver will now wrap field names for <kbd>insert()</kbd>, <kbd>update()</kbd> and <kbd>replace()</kbd> with backticks (`) so fields like "default" and "order" will not cause SQL errors.</li>
 </ul>
 
 <h2>Version 2.0.0</h2>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.