function up() { Migrator::message('inform', 'This migration enables support for uploading files as short URLs.'); $prefix = DB_PREFIX; $t = $this->createTable(DB_PREFIX . 'files'); $t->column('id', 'serial', array('primary_key' => true, 'null' => false)); $t->column('title', 'string', array('null' => false)); $t->column('filepath', 'string', array('null' => false)); $t->column('type', 'string', array('null' => false, 'default' => 'other')); $t->save(); $this->createIndex(DB_PREFIX . 'files', 'type', 'index_' . DB_PREFIX . 'files_type'); $this->addColumn(DB_PREFIX . 'urls', 'file_id', 'integer', array('default' => null)); $this->createIndex(DB_PREFIX . 'urls', 'file_id', 'index_' . DB_PREFIX . 'urls_file_id'); }
function up() { Migrator::message('inform', 'This migration enables an efficient method of generating automatic slugs.'); $prefix = DB_PREFIX; $t = $this->createTable(DB_PREFIX . 'autoslug'); $t->column('id', 'serial', array('primary_key' => true, 'null' => false)); $t->column('method', 'string', array('null' => false, 'size' => '31')); $t->column('base10', 'string', array('null' => false, 'size' => '100')); $t->save(); $this->createIndex(DB_PREFIX . 'autoslug', 'method', 'method_index', 'unique'); // Populate // SQLite/PostgreSQL don't support compound(?) inserts. // migration could possibly provide an insert function $add_methods_sql = array(); $add_methods_sql[] = <<<EOSQL INSERT INTO {$prefix}autoslug (method ,base10) VALUES ('base36', '1'); EOSQL; $add_methods_sql[] = <<<EOSQL INSERT INTO {$prefix}autoslug (method ,base10) VALUES ('base62', '1'); EOSQL; $add_methods_sql[] = <<<EOSQL INSERT INTO {$prefix}autoslug (method ,base10) VALUES ('mixed-smart', '1'); EOSQL; $add_methods_sql[] = <<<EOSQL INSERT INTO {$prefix}autoslug (method ,base10) VALUES ('smart', '1'); EOSQL; foreach ($add_methods_sql as $sql) { $ins = $this->db->prepare($sql); if (!$ins->execute()) { throw new Exception('Failed to add rows for autoslug methods.'); } } }
function up() { Migrator::message('inform', 'This migration will attempt to assign each non-custom/legacy redirection an ' . 'explicit slug (short URL path) equal ' . 'to its id in base 36 (as in the original Lessn).'); //Set up / mini config $batch = 25; $prefix = DB_PREFIX; $mark_custom = TRUE; $db =& $this->db; // Queries $update_sql = "UPDATE {$prefix}urls SET redir_type = 'custom' WHERE custom_url IS NOT NULL"; $select_sql = "SELECT * FROM {$prefix}urls " . 'WHERE custom_url IS NULL ' . 'AND id > :min_id ' . 'ORDER BY id ' . 'LIMIT ' . $batch; $check_sql = 'SELECT * FROM ' . DB_PREFIX . 'urls WHERE ' . (DB_DRIVER === 'sqlite' ? '' : 'BINARY') . ' custom_url = ' . (DB_DRIVER === 'sqlite' ? '' : 'BINARY') . ' :custom_url'; $explicit_sql = 'UPDATE ' . DB_PREFIX . 'urls SET custom_url = :custom_url WHERE id=:id LIMIT 1'; // --- STEP ONE --- // Add column to keep track of what kind of migration it is try { $this->addColumn(DB_PREFIX . 'urls', 'redir_type', 'string', array('default' => 'auto', 'size' => 6, 'null' => false, 'index' => true)); $this->createIndex(DB_PREFIX . 'urls', 'redir_type', 'redir_type_index'); Migrator::message('success', 'Added "redir_type" column'); } catch (Exception $e) { Migrator::message('failure', '"redir_type" column already exists… continuing…'); $mark_custom = FALSE; } // --- STEP TWO --- // SET type to 'custom' when it was really custom if ($mark_custom) { $updt = $db->prepare($update_sql); if (!$updt->execute()) { throw new Exception('Update failed!'); } $affected = $updt->rowCount(); Migrator::message($affected ? 'success' : 'inform', $affected . ' redirection(s) with custom slugs were explicitly marked as \'custom\'.'); } // --- STEP THREE --- // Give each id-based redirection an explicit slug // Avoid doing failed migration rows over and over $min_id = -1; while (TRUE) { set_time_limit(60); $slct = $db->prepare($select_sql); $slct->execute(array('min_id' => $min_id)); $rows = $slct->fetchAll(PDO::FETCH_ASSOC); $returned = count($rows); $errors = 0; // Migrate each of these foreach ($rows as $row) { $id = $row['id']; // For next batch if ($id > $min_id) { $min_id = $id; } // Explicit redirection $slug = base_convert($id, 10, 36); $chk = $db->prepare($check_sql); $chk->execute(array('custom_url' => $slug)); // Check to make sure one doesn't aready exist $conflict = $chk->fetch(PDO::FETCH_ASSOC); if ($conflict === FALSE) { $expl = $db->prepare($explicit_sql); $expl->execute(array('custom_url' => $slug, 'id' => $id)); } elseif (is_array($conflict) && isset($conflict['id'])) { Migrator::message('failure', 'Could not give redirect an explicit slug (already in use!). ' . "\nID: " . $id . ". \nAlready-in-use slug: " . $slug . ". \nID of (custom) redirection already using slug: " . $conflict['id']); $errors++; } else { throw new Exception('Unexpected database result when checking for pre-existing rows'); } } if ($returned - $errors > 0) { Migrator::message('success', 'Gave ' . ($returned - $errors) . ' redirections explicit slugs.'); } if ($returned < $batch) { // Complete! break; } } }
function up() { Migrator::message('inform', 'This migration allows you to set a custom short URL. ' . 'Make sure to get the <strong>NEW</strong> bookmarklets that support this feature!', false); $this->addColumn(DB_PREFIX . 'urls', 'custom_url', 'string', array('default' => null, 'size' => 255)); }
function migrate($start = null) { $this->html_begin(); if ($start === null) { $start = $this->current_version + 1; } $files = glob($this->migrations_dir . "/*.php"); $this->db->beginTransaction(); $highest_version_seen = 0; echo '<dl>'; foreach ($files as $file) { include $file; $file = basename($file, '.php'); $class = substr($file, strpos($file, '_') + 1); $v = intval(substr($file, 0, strpos($file, '_'))); if ($highest_version_seen < $v) { $highest_version_seen = $v; } if (!class_exists($class)) { echo '</dl>'; Migrator::message('failure', 'Could not find class: \'' . $class . '\' in migration \'' . $file . "'"); //no need to escape for html $this->html_end(); exit; } if ($v < $start || $v <= $this->currentVersion()) { continue; } $m = new $class($this->db); try { echo '<dt>Running migration ' . htmlspecialchars($class) . '::up to version ' . $v . '</dt><dd>'; $m->up(); Migrator::message('success', 'Migration complete. Current schema version: ' . $v); $this->updateInfoToVersion($v); $this->db->commit(); $this->db->beginTransaction(); echo '</dd>'; } catch (Exception $e) { Migrator::message('failure', 'Failed to migrate, rolling back.' . "\n" . (string) $e); $this->db->rollBack(); echo '</dd></dl>'; $this->html_end(); exit; } //$last_version = $v; } echo '</dl>'; if ($this->currentVersion() == $highest_version_seen) { Migrator::message('inform', 'Your schema is up-to-date! Schema version: ' . $this->currentVersion()); } $this->html_end(); }