Вход Регистрация
Файл: Main Website Files/system/libraries/Migration.php
Строк: 500
<?php
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP
 *
 * This content is released under the MIT License (MIT)
 *
 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
 *
 * Permission 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:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @package    CodeIgniter
 * @author    EllisLab Dev Team
 * @copyright    Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
 * @copyright    Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
 * @license    http://opensource.org/licenses/MIT    MIT License
 * @link    http://codeigniter.com
 * @since    Version 3.0.0
 * @filesource
 */
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * 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 {

    
/**
     * Whether the library is enabled
     *
     * @var bool
     */
    
protected $_migration_enabled FALSE;

    
/**
     * Migration numbering type
     *
     * @var    bool
     */
    
protected $_migration_type 'sequential';

    
/**
     * Path to migration classes
     *
     * @var string
     */
    
protected $_migration_path NULL;

    
/**
     * Current migration version
     *
     * @var mixed
     */
    
protected $_migration_version 0;

    
/**
     * Database table with migration info
     *
     * @var string
     */
    
protected $_migration_table 'migrations';

    
/**
     * Whether to automatically run migrations
     *
     * @var    bool
     */
    
protected $_migration_auto_latest FALSE;

    
/**
     * Migration basename regex
     *
     * @var bool
     */
    
protected $_migration_regex NULL;

    
/**
     * Error message
     *
     * @var string
     */
    
protected $_error_string '';

    
/**
     * Initialize Migration Class
     *
     * @param    array    $config
     * @return    void
     */
    
public function __construct($config = array())
    {
        
// Only run this constructor on main library load
        
if ( ! in_array(get_class($this), array('CI_Migration'config_item('subclass_prefix').'Migration'), TRUE))
        {
            return;
        }

        foreach (
$config as $key => $val)
        {
            
$this->{'_'.$key} = $val;
        }

        
log_message('info''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();

        
// Make sure the migration table name was set.
        
if (empty($this->_migration_table))
        {
            
show_error('Migrations configuration file (migration.php) must have "migration_table" set.');
        }

        
// Migration basename regex
        
$this->_migration_regex = ($this->_migration_type === 'timestamp')
            ? 
'/^d{14}_(w+)$/'
            
'/^d{3}_(w+)$/';

        
// Make sure a valid migration numbering type was set.
        
if ( ! in_array($this->_migration_type, array('sequential''timestamp')))
        {
            
show_error('An invalid migration numbering type was specified: '.$this->_migration_type);
        }

        
// If the migrations table is missing, make it
        
if ( ! $this->db->table_exists($this->_migration_table))
        {
            
$this->dbforge->add_field(array(
                
'version' => array('type' => 'BIGINT''constraint' => 20),
            ));

            
$this->dbforge->create_table($this->_migration_tableTRUE);

            
$this->db->insert($this->_migration_table, array('version' => 0));
        }

        
// Do we auto migrate to the latest migration?
        
if ($this->_migration_auto_latest === TRUE && ! $this->latest())
        {
            
show_error($this->error_string());
        }
    }

    
// --------------------------------------------------------------------

    /**
     * Migrate to a schema version
     *
     * Calls each migration step required to get to the schema version of
     * choice
     *
     * @param    string    $target_version    Target schema version
     * @return    mixed    TRUE if already latest, FALSE if failed, string if upgraded
     */
    
public function version($target_version)
    {
        
// Note: We use strings, so that timestamp versions work on 32-bit systems
        
$current_version $this->_get_version();

        if (
$this->_migration_type === 'sequential')
        {
            
$target_version sprintf('%03d'$target_version);
        }
        else
        {
            
$target_version = (string) $target_version;
        }

        
$migrations $this->find_migrations();

        if (
$target_version && ! isset($migrations[$target_version]))
        {
            
$this->_error_string sprintf($this->lang->line('migration_not_found'), $target_version);
            return 
FALSE;
        }

        if (
$target_version $current_version)
        {
            
// Moving Up
            
$method 'up';
        }
        else
        {
            
// Moving Down, apply in reverse order
            
$method 'down';
            
krsort($migrations);
        }

        if (empty(
$migrations))
        {
            return 
TRUE;
        }

        
$previous FALSE;

        
// Validate all available migrations, and run the ones within our target range
        
foreach ($migrations as $number => $file)
        {
            
// Check for sequence gaps
            
if ($this->_migration_type === 'sequential' && $previous !== FALSE && abs($number $previous) > 1)
            {
                
$this->_error_string sprintf($this->lang->line('migration_sequence_gap'), $number);
                return 
FALSE;
            }

            include_once(
$file);
            
$class 'Migration_'.ucfirst(strtolower($this->_get_migration_name(basename($file'.php'))));

            
// Validate the migration file structure
            
if ( ! class_exists($classFALSE))
            {
                
$this->_error_string sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
                return 
FALSE;
            }

            
$previous $number;

            
// Run migrations that are inside the target range
            
if (
                (
$method === 'up'   && $number $current_version && $number <= $target_version) OR
                (
$method === 'down' && $number <= $current_version && $number $target_version)
            )
            {
                
$instance = new $class();
                if ( ! 
is_callable(array($instance$method)))
                {
                    
$this->_error_string sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
                    return 
FALSE;
                }

                
log_message('debug''Migrating '.$method.' from version '.$current_version.' to version '.$number);
                
call_user_func(array($instance$method));
                
$current_version $number;
                
$this->_update_version($current_version);
            }
        }

        
// This is necessary when moving down, since the the last migration applied
        // will be the down() method for the next migration up from the target
        
if ($current_version <> $target_version)
        {
            
$current_version $target_version;
            
$this->_update_version($current_version);
        }

        
log_message('debug''Finished migrating to '.$current_version);

        return 
$current_version;
    }

    
// --------------------------------------------------------------------

    /**
     * Sets the schema to the latest migration
     *
     * @return    mixed    TRUE if already latest, FALSE if failed, string if upgraded
     */
    
public function latest()
    {
        
$migrations $this->find_migrations();

        if (empty(
$migrations))
        {
            
$this->_error_string $this->lang->line('migration_none_found');
            return 
FALSE;
        }

        
$last_migration basename(end($migrations));

        
// Calculate the last migration step from existing migration
        // filenames and proceed to the standard version migration
        
return $this->version($this->_get_migration_number($last_migration));
    }

    
// --------------------------------------------------------------------

    /**
     * Sets the schema to the migration version set in config
     *
     * @return    mixed    TRUE if already current, FALSE if failed, string if upgraded
     */
    
public function current()
    {
        return 
$this->version($this->_migration_version);
    }

    
// --------------------------------------------------------------------

    /**
     * Error string
     *
     * @return    string    Error message returned as a string
     */
    
public function error_string()
    {
        return 
$this->_error_string;
    }

    
// --------------------------------------------------------------------

    /**
     * Retrieves list of available migration scripts
     *
     * @return    array    list of migration file paths sorted by version
     */
    
public function find_migrations()
    {
        
$migrations = array();

        
// Load all *_*.php files in the migrations path
        
foreach (glob($this->_migration_path.'*_*.php') as $file)
        {
            
$name basename($file'.php');

            
// Filter out non-migration files
            
if (preg_match($this->_migration_regex$name))
            {
                
$number $this->_get_migration_number($name);

                
// There cannot be duplicate migration numbers
                
if (isset($migrations[$number]))
                {
                    
$this->_error_string sprintf($this->lang->line('migration_multiple_version'), $number);
                    
show_error($this->_error_string);
                }

                
$migrations[$number] = $file;
            }
        }

        
ksort($migrations);
        return 
$migrations;
    }

    
// --------------------------------------------------------------------

    /**
     * Extracts the migration number from a filename
     *
     * @param    string    $migration
     * @return    string    Numeric portion of a migration filename
     */
    
protected function _get_migration_number($migration)
    {
        return 
sscanf($migration'%[0-9]+'$number)
            ? 
$number '0';
    }

    
// --------------------------------------------------------------------

    /**
     * Extracts the migration class name from a filename
     *
     * @param    string    $migration
     * @return    string    text portion of a migration filename
     */
    
protected function _get_migration_name($migration)
    {
        
$parts explode('_'$migration);
        
array_shift($parts);
        return 
implode('_'$parts);
    }

    
// --------------------------------------------------------------------

    /**
     * Retrieves current schema version
     *
     * @return    string    Current migration version
     */
    
protected function _get_version()
    {
        
$row $this->db->select('version')->get($this->_migration_table)->row();
        return 
$row $row->version '0';
    }

    
// --------------------------------------------------------------------

    /**
     * Stores the current schema version
     *
     * @param    string    $migration    Migration reached
     * @return    void
     */
    
protected function _update_version($migration)
    {
        
$this->db->update($this->_migration_table, array(
            
'version' => $migration
        
));
    }

    
// --------------------------------------------------------------------

    /**
     * Enable the use of CI super-global
     *
     * @param    string    $var
     * @return    mixed
     */
    
public function __get($var)
    {
        return 
get_instance()->$var;
    }

}
Онлайн: 0
Реклама