/lenasys/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/lenasys/trunk

« back to all changes in this revision

Viewing changes to codeigniter/system/libraries/Migration.php

  • Committer: galaxyAbstractor
  • Date: 2013-04-10 15:58:59 UTC
  • mfrom: (20.1.1 lenasys)
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: galaxyabstractor@gmail.com-20130410155859-cih60kaz5es8savt
CodeIgniter implementation of basic CMS system

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php defined('BASEPATH') OR exit('No direct script access allowed');
 
2
/**
 
3
 * CodeIgniter
 
4
 *
 
5
 * An open source application development framework for PHP 5.1.6 or newer
 
6
 *
 
7
 * @package             CodeIgniter
 
8
 * @author              EllisLab Dev Team
 
9
 * @copyright   Copyright (c) 2006 - 2012, EllisLab, Inc.
 
10
 * @license             http://codeigniter.com/user_guide/license.html
 
11
 * @link                http://codeigniter.com
 
12
 * @since               Version 1.0
 
13
 * @filesource
 
14
 */
 
15
 
 
16
// ------------------------------------------------------------------------
 
17
 
 
18
/**
 
19
 * Migration Class
 
20
 *
 
21
 * All migrations should implement this, forces up() and down() and gives
 
22
 * access to the CI super-global.
 
23
 *
 
24
 * @package             CodeIgniter
 
25
 * @subpackage  Libraries
 
26
 * @category    Libraries
 
27
 * @author              Reactor Engineers
 
28
 * @link
 
29
 */
 
30
class CI_Migration {
 
31
 
 
32
        protected $_migration_enabled = FALSE;
 
33
        protected $_migration_path = NULL;
 
34
        protected $_migration_version = 0;
 
35
 
 
36
        protected $_error_string = '';
 
37
 
 
38
        public function __construct($config = array())
 
39
        {
 
40
                # Only run this constructor on main library load
 
41
                if (get_parent_class($this) !== FALSE)
 
42
                {
 
43
                        return;
 
44
                }
 
45
 
 
46
                foreach ($config as $key => $val)
 
47
                {
 
48
                        $this->{'_' . $key} = $val;
 
49
                }
 
50
 
 
51
                log_message('debug', 'Migrations class initialized');
 
52
 
 
53
                // Are they trying to use migrations while it is disabled?
 
54
                if ($this->_migration_enabled !== TRUE)
 
55
                {
 
56
                        show_error('Migrations has been loaded but is disabled or set up incorrectly.');
 
57
                }
 
58
 
 
59
                // If not set, set it
 
60
                $this->_migration_path == '' AND $this->_migration_path = APPPATH . 'migrations/';
 
61
 
 
62
                // Add trailing slash if not set
 
63
                $this->_migration_path = rtrim($this->_migration_path, '/').'/';
 
64
 
 
65
                // Load migration language
 
66
                $this->lang->load('migration');
 
67
 
 
68
                // They'll probably be using dbforge
 
69
                $this->load->dbforge();
 
70
 
 
71
                // If the migrations table is missing, make it
 
72
                if ( ! $this->db->table_exists('migrations'))
 
73
                {
 
74
                        $this->dbforge->add_field(array(
 
75
                                'version' => array('type' => 'INT', 'constraint' => 3),
 
76
                        ));
 
77
 
 
78
                        $this->dbforge->create_table('migrations', TRUE);
 
79
 
 
80
                        $this->db->insert('migrations', array('version' => 0));
 
81
                }
 
82
        }
 
83
 
 
84
        // --------------------------------------------------------------------
 
85
 
 
86
        /**
 
87
         * Migrate to a schema version
 
88
         *
 
89
         * Calls each migration step required to get to the schema version of
 
90
         * choice
 
91
         *
 
92
         * @param       int     Target schema version
 
93
         * @return      mixed   TRUE if already latest, FALSE if failed, int if upgraded
 
94
         */
 
95
        public function version($target_version)
 
96
        {
 
97
                $start = $current_version = $this->_get_version();
 
98
                $stop = $target_version;
 
99
 
 
100
                if ($target_version > $current_version)
 
101
                {
 
102
                        // Moving Up
 
103
                        ++$start;
 
104
                        ++$stop;
 
105
                        $step = 1;
 
106
                }
 
107
                else
 
108
                {
 
109
                        // Moving Down
 
110
                        $step = -1;
 
111
                }
 
112
 
 
113
                $method = ($step === 1) ? 'up' : 'down';
 
114
                $migrations = array();
 
115
 
 
116
                // We now prepare to actually DO the migrations
 
117
                // But first let's make sure that everything is the way it should be
 
118
                for ($i = $start; $i != $stop; $i += $step)
 
119
                {
 
120
                        $f = glob(sprintf($this->_migration_path . '%03d_*.php', $i));
 
121
 
 
122
                        // Only one migration per step is permitted
 
123
                        if (count($f) > 1)
 
124
                        {
 
125
                                $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $i);
 
126
                                return FALSE;
 
127
                        }
 
128
 
 
129
                        // Migration step not found
 
130
                        if (count($f) == 0)
 
131
                        {
 
132
                                // If trying to migrate up to a version greater than the last
 
133
                                // existing one, migrate to the last one.
 
134
                                if ($step == 1)
 
135
                                {
 
136
                                        break;
 
137
                                }
 
138
 
 
139
                                // If trying to migrate down but we're missing a step,
 
140
                                // something must definitely be wrong.
 
141
                                $this->_error_string = sprintf($this->lang->line('migration_not_found'), $i);
 
142
                                return FALSE;
 
143
                        }
 
144
 
 
145
                        $file = basename($f[0]);
 
146
                        $name = basename($f[0], '.php');
 
147
 
 
148
                        // Filename validations
 
149
                        if (preg_match('/^\d{3}_(\w+)$/', $name, $match))
 
150
                        {
 
151
                                $match[1] = strtolower($match[1]);
 
152
 
 
153
                                // Cannot repeat a migration at different steps
 
154
                                if (in_array($match[1], $migrations))
 
155
                                {
 
156
                                        $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $match[1]);
 
157
                                        return FALSE;
 
158
                                }
 
159
 
 
160
                                include $f[0];
 
161
                                $class = 'Migration_' . ucfirst($match[1]);
 
162
 
 
163
                                if ( ! class_exists($class))
 
164
                                {
 
165
                                        $this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
 
166
                                        return FALSE;
 
167
                                }
 
168
 
 
169
                                if ( ! is_callable(array($class, $method)))
 
170
                                {
 
171
                                        $this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
 
172
                                        return FALSE;
 
173
                                }
 
174
 
 
175
                                $migrations[] = $match[1];
 
176
                        }
 
177
                        else
 
178
                        {
 
179
                                $this->_error_string = sprintf($this->lang->line('migration_invalid_filename'), $file);
 
180
                                return FALSE;
 
181
                        }
 
182
                }
 
183
 
 
184
                log_message('debug', 'Current migration: ' . $current_version);
 
185
 
 
186
                $version = $i + ($step == 1 ? -1 : 0);
 
187
 
 
188
                // If there is nothing to do so quit
 
189
                if ($migrations === array())
 
190
                {
 
191
                        return TRUE;
 
192
                }
 
193
 
 
194
                log_message('debug', 'Migrating from ' . $method . ' to version ' . $version);
 
195
 
 
196
                // Loop through the migrations
 
197
                foreach ($migrations AS $migration)
 
198
                {
 
199
                        // Run the migration class
 
200
                        $class = 'Migration_' . ucfirst(strtolower($migration));
 
201
                        call_user_func(array(new $class, $method));
 
202
 
 
203
                        $current_version += $step;
 
204
                        $this->_update_version($current_version);
 
205
                }
 
206
 
 
207
                log_message('debug', 'Finished migrating to '.$current_version);
 
208
 
 
209
                return $current_version;
 
210
        }
 
211
 
 
212
        // --------------------------------------------------------------------
 
213
 
 
214
        /**
 
215
         * Set's the schema to the latest migration
 
216
         *
 
217
         * @return      mixed   true if already latest, false if failed, int if upgraded
 
218
         */
 
219
        public function latest()
 
220
        {
 
221
                if ( ! $migrations = $this->find_migrations())
 
222
                {
 
223
                        $this->_error_string = $this->line->lang('migration_none_found');
 
224
                        return false;
 
225
                }
 
226
 
 
227
                $last_migration = basename(end($migrations));
 
228
 
 
229
                // Calculate the last migration step from existing migration
 
230
                // filenames and procceed to the standard version migration
 
231
                return $this->version((int) substr($last_migration, 0, 3));
 
232
        }
 
233
 
 
234
        // --------------------------------------------------------------------
 
235
 
 
236
        /**
 
237
         * Set's the schema to the migration version set in config
 
238
         *
 
239
         * @return      mixed   true if already current, false if failed, int if upgraded
 
240
         */
 
241
        public function current()
 
242
        {
 
243
                return $this->version($this->_migration_version);
 
244
        }
 
245
 
 
246
        // --------------------------------------------------------------------
 
247
 
 
248
        /**
 
249
         * Error string
 
250
         *
 
251
         * @return      string  Error message returned as a string
 
252
         */
 
253
        public function error_string()
 
254
        {
 
255
                return $this->_error_string;
 
256
        }
 
257
 
 
258
        // --------------------------------------------------------------------
 
259
 
 
260
        /**
 
261
         * Set's the schema to the latest migration
 
262
         *
 
263
         * @return      mixed   true if already latest, false if failed, int if upgraded
 
264
         */
 
265
        protected function find_migrations()
 
266
        {
 
267
                // Load all *_*.php files in the migrations path
 
268
                $files = glob($this->_migration_path . '*_*.php');
 
269
                $file_count = count($files);
 
270
 
 
271
                for ($i = 0; $i < $file_count; $i++)
 
272
                {
 
273
                        // Mark wrongly formatted files as false for later filtering
 
274
                        $name = basename($files[$i], '.php');
 
275
                        if ( ! preg_match('/^\d{3}_(\w+)$/', $name))
 
276
                        {
 
277
                                $files[$i] = FALSE;
 
278
                        }
 
279
                }
 
280
 
 
281
                sort($files);
 
282
                return $files;
 
283
        }
 
284
 
 
285
        // --------------------------------------------------------------------
 
286
 
 
287
        /**
 
288
         * Retrieves current schema version
 
289
         *
 
290
         * @return      int     Current Migration
 
291
         */
 
292
        protected function _get_version()
 
293
        {
 
294
                $row = $this->db->get('migrations')->row();
 
295
                return $row ? $row->version : 0;
 
296
        }
 
297
 
 
298
        // --------------------------------------------------------------------
 
299
 
 
300
        /**
 
301
         * Stores the current schema version
 
302
         *
 
303
         * @param       int     Migration reached
 
304
         * @return      bool
 
305
         */
 
306
        protected function _update_version($migrations)
 
307
        {
 
308
                return $this->db->update('migrations', array(
 
309
                        'version' => $migrations
 
310
                ));
 
311
        }
 
312
 
 
313
        // --------------------------------------------------------------------
 
314
 
 
315
        /**
 
316
         * Enable the use of CI super-global
 
317
         *
 
318
         * @param       mixed   $var
 
319
         * @return      mixed
 
320
         */
 
321
        public function __get($var)
 
322
        {
 
323
                return get_instance()->$var;
 
324
        }
 
325
}
 
326
 
 
327
/* End of file Migration.php */
 
328
/* Location: ./system/libraries/Migration.php */
 
 
b'\\ No newline at end of file'