1000.php (10078B)
1 <?php 2 class ModelUpgrade1000 extends Model { 3 public function upgrade() { 4 // This is a generic upgrade script. 5 // It makes mass changes to the DB by creating tables that are not in the current db, changes the charset and DB engine to the SQL schema. 6 // The uprade script is not coherent because of the changes over time to the upgrades so im grouping the changes into different files 7 // Future version should have a upgrade file name that matches the version number being changed to 8 9 // Load the sql file 10 $file = DIR_APPLICATION . 'opencart.sql'; 11 12 if (!file_exists($file)) { 13 exit('Could not load sql file: ' . $file); 14 } 15 16 $string = ''; 17 18 $lines = file($file); 19 20 $status = false; 21 22 // Get only the create statements 23 foreach($lines as $line) { 24 // Set any prefix 25 $line = str_replace("DROP TABLE IF EXISTS `oc_", "DROP TABLE IF EXISTS `" . DB_PREFIX, $line); 26 27 $line = str_replace("CREATE TABLE IF NOT EXISTS `oc_", "CREATE TABLE `" . DB_PREFIX, $line); 28 29 $line = str_replace("CREATE TABLE `oc_", "CREATE TABLE `" . DB_PREFIX, $line); 30 31 // If line begins with create table we want to start recording 32 if (substr($line, 0, 12) == 'CREATE TABLE') { 33 $status = true; 34 } 35 36 if ($status) { 37 $string .= $line; 38 } 39 40 // If line contains with ; we want to stop recording 41 if (preg_match('/;/', $line)) { 42 $status = false; 43 } 44 } 45 46 $table_new_data = array(); 47 48 // Trim any spaces 49 $string = trim($string); 50 51 // Trim any ; 52 $string = trim($string, ';'); 53 54 // Start reading each create statement 55 $statements = explode(';', $string); 56 57 foreach ($statements as $sql) { 58 // Get all fields 59 $field_data = array(); 60 61 preg_match_all('#`(\w[\w\d]*)`\s+((tinyint|smallint|mediumint|bigint|int|tinytext|text|mediumtext|longtext|tinyblob|blob|mediumblob|longblob|varchar|char|datetime|date|float|double|decimal|timestamp|time|year|enum|set|binary|varbinary)(\((.*)\))?){1}\s*(collate (\w+)\s*)?(unsigned\s*)?((NOT\s*NULL\s*)|(NULL\s*))?(auto_increment\s*)?(default \'([^\']*)\'\s*)?#i', $sql, $match); 62 63 foreach(array_keys($match[0]) as $key) { 64 $field_data[] = array( 65 'name' => trim($match[1][$key]), 66 'type' => strtoupper(trim($match[3][$key])), 67 'size' => str_replace(array('(', ')'), '', trim($match[4][$key])), 68 'sizeext' => trim($match[6][$key]), 69 'collation' => trim($match[7][$key]), 70 'unsigned' => trim($match[8][$key]), 71 'notnull' => trim($match[9][$key]), 72 'autoincrement' => trim($match[12][$key]), 73 'default' => trim($match[14][$key]) 74 ); 75 } 76 77 // Get primary keys 78 $primary_data = array(); 79 80 preg_match('#primary\s*key\s*\([^)]+\)#i', $sql, $match); 81 82 if (isset($match[0])) { 83 preg_match_all('#`(\w[\w\d]*)`#', $match[0], $match); 84 } else{ 85 $match = array(); 86 } 87 88 if ($match) { 89 foreach($match[1] as $primary) { 90 $primary_data[] = $primary; 91 } 92 } 93 94 // Get indexes 95 $index_data = array(); 96 97 $indexes = array(); 98 99 preg_match_all('#key\s*`\w[\w\d]*`\s*\(.*\)#i', $sql, $match); 100 101 foreach($match[0] as $key) { 102 preg_match_all('#`(\w[\w\d]*)`#', $key, $match); 103 104 $indexes[] = $match; 105 } 106 107 foreach($indexes as $index) { 108 $key = ''; 109 110 foreach($index[1] as $field) { 111 if ($key == '') { 112 $key = $field; 113 } else{ 114 $index_data[$key][] = $field; 115 } 116 } 117 } 118 119 // Table options 120 $option_data = array(); 121 122 preg_match_all('#(\w+)=\'?(\w+\~?\w+)\'?#', $sql, $option); 123 124 foreach(array_keys($option[0]) as $key) { 125 $option_data[$option[1][$key]] = $option[2][$key]; 126 } 127 128 // Get Table Name 129 preg_match_all('#create\s*table\s*`(\w[\w\d]*)`#i', $sql, $table); 130 131 if (isset($table[1][0])) { 132 $table_new_data[] = array( 133 'sql' => $sql, 134 'name' => $table[1][0], 135 'field' => $field_data, 136 'primary' => $primary_data, 137 'index' => $index_data, 138 'option' => $option_data 139 ); 140 } 141 } 142 143 // Get all current tables, fields, type, size, etc.. 144 $table_old_data = array(); 145 146 $table_query = $this->db->query("SHOW TABLES FROM `" . DB_DATABASE . "`"); 147 148 foreach ($table_query->rows as $table) { 149 if (utf8_substr($table['Tables_in_' . DB_DATABASE], 0, strlen(DB_PREFIX)) == DB_PREFIX) { 150 $field_data = array(); 151 $extended_field_data = array(); 152 153 $field_query = $this->db->query("SHOW COLUMNS FROM `" . $table['Tables_in_' . DB_DATABASE] . "`"); 154 155 foreach ($field_query->rows as $field) { 156 $field_data[] = $field['Field']; 157 $extended_field_data[] = $field; 158 } 159 160 $table_old_data[$table['Tables_in_' . DB_DATABASE]]['field_list'] = $field_data; 161 $table_old_data[$table['Tables_in_' . DB_DATABASE]]['extended_field_data'] = $extended_field_data; 162 } 163 } 164 165 foreach ($table_new_data as $table) { 166 // If table is not found create it 167 if (!isset($table_old_data[$table['name']])) { 168 $this->db->query($table['sql']); 169 } else { 170 // DB Engine 171 if (isset($table['option']['ENGINE'])) { 172 $this->db->query("ALTER TABLE `" . $table['name'] . "` ENGINE = `" . $table['option']['ENGINE'] . "`"); 173 } 174 175 // Charset 176 if (isset($table['option']['CHARSET']) && isset($table['option']['COLLATE'])) { 177 $this->db->query("ALTER TABLE `" . $table['name'] . "` DEFAULT CHARACTER SET `" . $table['option']['CHARSET'] . "` COLLATE `" . $table['option']['COLLATE'] . "`"); 178 } 179 180 // Loop through all tables and adjust based on opencart.sql file 181 $i = 0; 182 183 foreach ($table['field'] as $field) { 184 185 // If field is not found create it 186 if (!in_array($field['name'], $table_old_data[$table['name']]['field_list'])) { 187 188 $status = true; 189 foreach ($table_old_data[$table['name']]['extended_field_data'] as $oldfield) { 190 if ($oldfield['Extra'] == 'auto_increment' && $field['autoincrement']) { 191 $sql = "ALTER TABLE `" . $table['name'] . "` CHANGE `" . $oldfield['Field'] . "` `" . $field['name'] . "` " . strtoupper($field['type']); 192 $status = false; 193 break; 194 } 195 } 196 197 if ($status) { 198 $sql = "ALTER TABLE `" . $table['name'] . "` ADD `" . $field['name'] . "` " . $field['type']; 199 } 200 201 if ($field['size']) { 202 $sql .= "(" . $field['size'] . ")"; 203 } 204 205 if ($field['collation']) { 206 $sql .= " " . $field['collation']; 207 } 208 209 if ($field['unsigned']) { 210 $sql .= " " . $field['unsigned']; 211 } 212 213 if ($field['notnull']) { 214 $sql .= " " . $field['notnull']; 215 } 216 217 if ($field['default'] != '') { 218 $sql .= " DEFAULT '" . $field['default'] . "'"; 219 } 220 221 if (isset($table['field'][$i - 1])) { 222 $sql .= " AFTER `" . $table['field'][$i - 1]['name'] . "`"; 223 } else { 224 $sql .= " FIRST"; 225 } 226 227 $this->db->query($sql); 228 } else { 229 // Remove auto increment from all fields 230 $sql = "ALTER TABLE `" . $table['name'] . "` CHANGE `" . $field['name'] . "` `" . $field['name'] . "` " . strtoupper($field['type']); 231 232 if ($field['size']) { 233 $sql .= "(" . $field['size'] . ")"; 234 } 235 236 if ($field['collation']) { 237 $sql .= " " . $field['collation']; 238 } 239 240 if ($field['unsigned']) { 241 $sql .= " " . $field['unsigned']; 242 } 243 244 if ($field['notnull']) { 245 $sql .= " " . $field['notnull']; 246 } 247 248 if ($field['default'] != '') { 249 $sql .= " DEFAULT '" . $field['default'] . "'"; 250 } 251 252 if (isset($table['field'][$i - 1])) { 253 $sql .= " AFTER `" . $table['field'][$i - 1]['name'] . "`"; 254 } else { 255 $sql .= " FIRST"; 256 } 257 258 $this->db->query($sql); 259 } 260 261 $i++; 262 } 263 264 $status = false; 265 266 // Drop primary keys and indexes. 267 $query = $this->db->query("SHOW INDEXES FROM `" . $table['name'] . "`"); 268 269 $last_key_name = ''; 270 if ($query->num_rows) { 271 foreach ($query->rows as $result) { 272 if ($result['Key_name'] != 'PRIMARY' && $result['Key_name'] != $last_key_name) { 273 $last_key_name = $result['Key_name']; 274 $this->db->query("ALTER TABLE `" . $table['name'] . "` DROP INDEX `" . $result['Key_name'] . "`"); 275 } else { 276 $status = true; 277 } 278 } 279 } 280 281 if ($status) { 282 $this->db->query("ALTER TABLE `" . $table['name'] . "` DROP PRIMARY KEY"); 283 } 284 285 // Add a new primary key. 286 $primary_data = array(); 287 288 foreach ($table['primary'] as $primary) { 289 $primary_data[] = "`" . $primary . "`"; 290 } 291 292 if ($primary_data) { 293 $this->db->query("ALTER TABLE `" . $table['name'] . "` ADD PRIMARY KEY(" . implode(',', $primary_data) . ")"); 294 } 295 296 // Add the new indexes 297 foreach ($table['index'] as $name => $index) { 298 $index_data = array(); 299 300 foreach ($index as $key) { 301 $index_data[] = '`' . $key . '`'; 302 } 303 304 if ($index_data) { 305 $this->db->query("ALTER TABLE `" . $table['name'] . "` ADD INDEX `$name` (" . implode(',', $index_data) . ")"); 306 } 307 } 308 309 // Add auto increment to primary keys again 310 foreach ($table['field'] as $field) { 311 if ($field['autoincrement']) { 312 $sql = "ALTER TABLE `" . $table['name'] . "` CHANGE `" . $field['name'] . "` `" . $field['name'] . "` " . strtoupper($field['type']); 313 314 if ($field['size']) { 315 $sql .= "(" . $field['size'] . ")"; 316 } 317 318 if ($field['collation']) { 319 $sql .= " " . $field['collation']; 320 } 321 322 if ($field['unsigned']) { 323 $sql .= " " . $field['unsigned']; 324 } 325 326 if ($field['notnull']) { 327 $sql .= " " . $field['notnull']; 328 } 329 330 if ($field['default'] != '') { 331 $sql .= " DEFAULT '" . $field['default'] . "'"; 332 } 333 334 if ($field['autoincrement']) { 335 $sql .= " AUTO_INCREMENT"; 336 } 337 338 $this->db->query($sql); 339 } 340 } 341 } 342 } 343 } 344 }