tableList() public static method

public static tableList ( )
 /**
  * Update the database schema as required by this extension
  */
 function augmentDatabase()
 {
     $exist = DB::tableList();
     if (!empty($exist) && array_search('ForumMember', $exist) !== false) {
         DB::query("UPDATE \"Member\", \"ForumMember\" " . "SET \"Member\".\"ClassName\" = 'Member'," . "\"Member\".\"ForumRank\" = \"ForumMember\".\"ForumRank\"," . "\"Member\".\"Occupation\" = \"ForumMember\".\"Occupation\"," . "\"Member\".\"Country\" = \"ForumMember\".\"Country\"," . "\"Member\".\"Nickname\" = \"ForumMember\".\"Nickname\"," . "\"Member\".\"FirstNamePublic\" = \"ForumMember\".\"FirstNamePublic\"," . "\"Member\".\"SurnamePublic\" = \"ForumMember\".\"SurnamePublic\"," . "\"Member\".\"OccupationPublic\" = \"ForumMember\".\"OccupationPublic\"," . "\"Member\".\"CountryPublic\" = \"ForumMember\".\"CountryPublic\"," . "\"Member\".\"EmailPublic\" = \"ForumMember\".\"EmailPublic\"," . "\"Member\".\"AvatarID\" = \"ForumMember\".\"AvatarID\"," . "\"Member\".\"LastViewed\" = \"ForumMember\".\"LastViewed\"" . "WHERE \"Member\".\"ID\" = \"ForumMember\".\"ID\"");
         echo "<div style=\"padding:5px; color:white; background-color:blue;\">" . _t('ForumRole.TRANSFERSUCCEEDED', 'The data transfer has succeeded. However, to complete it, you must delete the ForumMember table. To do this, execute the query \\"DROP TABLE \'ForumMember\'\\".') . "</div>";
     }
 }
 function Tables()
 {
     $tables = new DataObjectSet();
     foreach (DB::tableList() as $table) {
         $tables->push(new DBP_Table($table));
     }
     $tables->sort('LowerCaseName');
     return $tables;
 }
 public function run($request)
 {
     $db = DB::tableList();
     foreach (self::GetVersionedClass() as $class) {
         $table = ClassInfo::table_for_object_field($class, 'ID');
         $vTable = $table . '_versions';
         if (!in_array($vTable, $db)) {
             continue;
         }
         echo "Clear records for class {$class} <br/>";
         // TODO: WE SHOULD CLEAR BY ID TO AVOID INCONSISTENT DB
         // Keep 50 last records
         DB::query("DELETE FROM {$vTable}\n  WHERE id <= (\n    SELECT id\n    FROM (\n      SELECT id\n      FROM {$vTable}\n      ORDER BY id DESC\n      LIMIT 1 OFFSET 50\n    ) selection\n  )");
         $this->vacuumTable($vTable);
     }
 }
 function run($request)
 {
     $ids = array();
     echo "#################################\n";
     echo "# Adding translation groups to existing records" . "\n";
     echo "#################################\n";
     $allSiteTreeIDs = DB::query('SELECT `ID` FROM `SiteTree`')->column();
     if ($allSiteTreeIDs) {
         foreach ($allSiteTreeIDs as $id) {
             $original = DataObject::get_by_id('SiteTree', $id);
             $existingGroupID = $original->getTranslationGroup();
             if (!$existingGroupID) {
                 $original->addTranslationGroup($original->ID);
             }
             $original->destroy();
             unset($original);
         }
     }
     DataObject::flush_and_destroy_cache();
     echo sprintf("Created translation groups for %d records\n", count($allSiteTreeIDs));
     foreach (array('Stage', 'Live') as $stage) {
         echo "\n\n#################################\n";
         echo "# Migrating stage {$stage}" . "\n";
         echo "#################################\n";
         $suffix = $stage == 'Live' ? '_Live' : '';
         // First get all entries in SiteTree_lang
         // This should be all translated pages
         $trans = DB::query(sprintf('SELECT * FROM `_obsolete_SiteTree_lang%s`', $suffix));
         // Iterate over each translated pages
         foreach ($trans as $oldtrans) {
             $newLocale = i18n::get_locale_from_lang($oldtrans['Lang']);
             echo sprintf("Migrating from %s to %s translation of '%s' (#%d)\n", $oldtrans['Lang'], $newLocale, Convert::raw2xml($oldtrans['Title']), $oldtrans['OriginalLangID']);
             // Get the untranslated page
             $original = Versioned::get_one_by_stage($oldtrans['ClassName'], $stage, '`SiteTree`.`ID` = ' . $oldtrans['OriginalLangID']);
             if (!$original) {
                 echo sprintf("Couldn't find original for #%d", $oldtrans['OriginalLangID']);
                 continue;
             }
             // write locale to $original
             $original->Locale = i18n::get_locale_from_lang(Translatable::default_lang());
             $original->writeToStage($stage);
             // Clone the original, and set it up as a translation
             $existingTrans = $original->getTranslation($newLocale, $stage);
             if ($existingTrans) {
                 echo sprintf("Found existing new-style translation for #%d. Already merged? Skipping.\n", $oldtrans['OriginalLangID']);
                 continue;
             }
             // Doesn't work with stage/live split
             //$newtrans = $original->createTranslation($newLocale);
             $newtrans = $original->duplicate(false);
             $newtrans->OriginalID = $original->ID;
             // we have to "guess" a locale based on the language
             $newtrans->Locale = $newLocale;
             if ($stage == 'Live' && array_key_exists($original->ID, $ids)) {
                 $newtrans->ID = $ids[$original->ID];
             }
             // Look at each class in the ancestry, and see if there is a _lang table for it
             foreach (ClassInfo::ancestry($oldtrans['ClassName']) as $classname) {
                 $oldtransitem = false;
                 // If the class is SiteTree, we already have the DB record, else check for the table and get the record
                 if ($classname == 'SiteTree') {
                     $oldtransitem = $oldtrans;
                 } elseif (in_array(strtolower($classname) . '_lang', DB::tableList())) {
                     $oldtransitem = DB::query(sprintf('SELECT * FROM `_obsolete_%s_lang%s` WHERE `OriginalLangID` = %d AND `Lang` = \'%s\'', $classname, $suffix, $original->ID, $oldtrans['Lang']))->first();
                 }
                 // Copy each translated field into the new translation
                 if ($oldtransitem) {
                     foreach ($oldtransitem as $key => $value) {
                         if (!in_array($key, array('ID', 'OriginalLangID'))) {
                             $newtrans->{$key} = $value;
                         }
                     }
                 }
             }
             // Write the new translation to the database
             $sitelang = Translatable::get_current_locale();
             Translatable::set_current_locale($newtrans->Locale);
             $newtrans->writeToStage($stage);
             Translatable::set_current_locale($sitelang);
             $newtrans->addTranslationGroup($original->getTranslationGroup(), true);
             if ($stage == 'Stage') {
                 $ids[$original->ID] = $newtrans->ID;
             }
         }
     }
     echo "\n\n#################################\n";
     echo "Done!\n";
 }
 public function testVersionedWithSingleStage()
 {
     $tables = DB::tableList();
     $this->assertContains('VersionedTest_SingleStage', array_values($tables), 'Contains base table');
     $this->assertContains('VersionedTest_SingleStage_versions', array_values($tables), 'Contains versions table');
     $this->assertNotContains('VersionedTest_SingleStage_Live', array_values($tables), 'Does not contain separate table with _Live suffix');
     $this->assertNotContains('VersionedTest_SingleStage_Stage', array_values($tables), 'Does not contain separate table with _Stage suffix');
     Versioned::reading_stage("Stage");
     $obj = new VersionedTest_SingleStage(array('Name' => 'MyObj'));
     $obj->write();
     $this->assertNotNull(VersionedTest_SingleStage::get()->byID($obj->ID), 'Writes to and reads from default stage if its set explicitly');
     Versioned::reading_stage("Live");
     $obj = new VersionedTest_SingleStage(array('Name' => 'MyObj'));
     $obj->write();
     $this->assertNotNull(VersionedTest_SingleStage::get()->byID($obj->ID), 'Writes to and reads from default stage even if a non-matching stage is set');
 }
 /**
  * Find if this table is obsolete or used
  *
  */
 function findDatabaseTableName($tableName)
 {
     $exist = DB::tableList();
     if (!empty($exist)) {
         if (array_search($tableName, $exist) !== false) {
             return $tableName;
         }
         $tableName = "_obsolete_{$tableName}";
         if (array_search($tableName, $exist) !== false) {
             return $tableName;
         }
     }
     echo '<strong>!! Could Not Find ' . $tableName;
     return;
 }
    public function run($request)
    {
        // Extend time limit
        set_time_limit(100000);
        // we may need some proivileges for this to work
        // without this, running under sake is a problem
        // maybe sake could take care of it ...
        Security::findAnAdministrator()->login();
        $this->checkInstalled();
        $this->withTransaction(function ($task) {
            Versioned::reading_stage('Stage');
            $classes = $task->fluentClasses();
            $tables = DB::tableList();
            $deleteQueue = array();
            foreach ($classes as $class) {
                // Ensure that a translationgroup table exists for this class
                $groupTable = strtolower($class . "_translationgroups");
                if (isset($tables[$groupTable])) {
                    $groupTable = $tables[$groupTable];
                } else {
                    Debug::message("Ignoring class without _translationgroups table {$class}", false);
                    continue;
                }
                // Disable filter
                if ($class::has_extension('FluentFilteredExtension')) {
                    $class::remove_extension('FluentFilteredExtension');
                }
                // Select all instances of this class in the default locale
                $instances = DataObject::get($class, sprintf('"Locale" = \'%s\'', Convert::raw2sql(Fluent::default_locale())));
                foreach ($instances as $instance) {
                    $isPublished = false;
                    if ($instance->hasMethod('isPublished')) {
                        $isPublished = $instance->isPublished();
                    }
                    if ($instance->ObsoleteClassName) {
                        Debug::message("Skipping {$instance->ClassName} with ID {$instanceID} because it from an obsolete class", false);
                        continue;
                    }
                    $instanceID = $instance->ID;
                    $translatedFields = $task->getTranslatedFields($instance->ClassName);
                    Debug::message("Updating {$instance->ClassName} {$instance->MenuTitle} ({$instanceID})", false);
                    $changed = false;
                    // Select all translations for this
                    $translatedItems = DataObject::get($class, sprintf('"Locale" != \'%1$s\' AND "ID" IN (
							SELECT "OriginalID" FROM "%2$s" WHERE "TranslationGroupID" IN (
								SELECT "TranslationGroupID" FROM "%2$s" WHERE "OriginalID" = %3$d
							)
						)', Convert::raw2sql(Fluent::default_locale()), $groupTable, $instanceID));
                    foreach ($translatedItems as $translatedItem) {
                        $locale = DB::query(sprintf('SELECT "Locale" FROM "%s" WHERE "ID" = %d', $class, $translatedItem->ID))->value();
                        // since we are going to delete the stuff
                        // anyway, no need bothering validating it
                        DataObject::config()->validation_enabled = false;
                        // Unpublish and delete translated record
                        if ($translatedItem->hasMethod('doUnpublish')) {
                            Debug::message("  --  Unpublishing {$locale}", false);
                            if ($translatedItem->doUnpublish() === false) {
                                throw new ConvertTranslatableException("Failed to unpublish");
                            }
                        }
                        Debug::message("  --  Adding {$translatedItem->ID} ({$locale})", false);
                        foreach ($translatedFields as $field) {
                            $trField = Fluent::db_field_for_locale($field, $locale);
                            if ($translatedItem->{$field}) {
                                Debug::message("     --  Adding {$trField}", false);
                                $instance->{$trField} = $translatedItem->{$field};
                                $changed = true;
                            }
                        }
                        // for some reason, deleting items here has disruptive effects
                        // as too much stuff gets removed, so lets wait with this until the end of the migration
                        $deleteQueue[] = $translatedItem;
                    }
                    if ($changed) {
                        if (!$isPublished) {
                            $instance->write();
                        } elseif ($instance->doPublish() === false) {
                            Debug::message("  --  Publishing FAILED", false);
                            throw new ConvertTranslatableException("Failed to publish");
                        } else {
                            Debug::message("  --  Published", false);
                        }
                    }
                }
            }
            foreach ($deleteQueue as $delItem) {
                Debug::message("  --  Removing {$delItem->ID}", false);
                $delItem->delete();
            }
        });
    }
Example #8
0
 function test_4_query()
 {
     DB::update('accounts', array('birthday' => new DateTime('10 September 2000 13:13:13')), 'username=%s', 'Charlie\'s Friend');
     $results = DB::query("SELECT * FROM accounts WHERE username=%s AND birthday IN %lt", 'Charlie\'s Friend', array('September 10 2000 13:13:13'));
     $this->assert(count($results) === 1);
     $this->assert($results[0]['age'] === '30' && $results[0]['password'] === 'goodbye');
     $this->assert($results[0]['birthday'] == '2000-09-10 13:13:13');
     $results = DB::query("SELECT * FROM accounts WHERE username!=%s", "Charlie's Friend");
     $this->assert(count($results) === 3);
     $columnlist = DB::columnList('accounts');
     $this->assert(count($columnlist) === 8);
     $this->assert($columnlist[0] === 'id');
     $this->assert($columnlist[5] === 'height');
     $tablelist = DB::tableList();
     $this->assert(count($tablelist) === 2);
     $this->assert($tablelist[0] === 'accounts');
     $tablelist = null;
     $tablelist = DB::tableList(DB::$dbName);
     $this->assert(count($tablelist) === 2);
     $this->assert($tablelist[0] === 'accounts');
 }
 /**
  *	Create a database table to replay the site tree creation, based on the chronological order of the site tree version table.
  */
 protected function setupStructure()
 {
     if (!DB::getConn() instanceof MySQLDatabase) {
         exit('This task currently only supports <strong>MySQL</strong>...');
     }
     $replaceArray = self::$db_columns;
     unset($replaceArray['FullURL']);
     $this->replaceColumnString = implode(',', array_keys($replaceArray));
     $tableList = DB::tableList();
     if (self::$use_temporary_table || !in_array(self::$default_table, $tableList)) {
         $options = self::$use_temporary_table ? array('temporary' => true) : null;
         $this->replayTable = DB::createTable(self::$default_table, self::$db_columns, null, $options);
     } else {
         // Delete all records from the table.
         $query = new SQLQuery('', self::$default_table);
         $query->setDelete(true);
         $query->execute();
     }
 }
Example #10
0
 /**
  * Checks if a table given table exists in the db
  *
  * @param mixed $table Table name
  * @return boolean Returns true if $table exists.
  */
 static function table_exists($table)
 {
     if (!self::$tableList) {
         self::$tableList = DB::tableList();
     }
     return isset(self::$tableList[strtolower($table)]);
 }
 /**
  * Tests to see if the old tables exist
  * @return {bool} Returns boolean true if the old tables are detected and the migration file is not detected
  */
 protected function hasOldTables()
 {
     if (!file_exists(ASSETS_PATH . '/.codeBankMigrated')) {
         $tables = DB::tableList();
         if (array_key_exists('snippits', $tables) && array_key_exists('snippit_search', $tables)) {
             return true;
         } else {
             touch(ASSETS_PATH . '/.codeBankMigrated');
         }
     }
     return false;
 }
 public static function merge($records)
 {
     $all = array();
     $all_but_oldest = array();
     $all_but_latest = array();
     $latest = null;
     $oldest = null;
     foreach ($records as $r) {
         if (!is_object($r)) {
             $r = (object) $r;
         }
         if (!$r instanceof Member) {
             $r = Member::get()->byID($r->ID);
         }
         if (!$latest) {
             $latest = $r;
         } else {
             if (strtotime($r->LastEdited) > strtotime($latest->LastEdited)) {
                 $latest = $r;
             }
         }
         if (!$oldest) {
             $oldest = $r;
         } else {
             if ($r->ID < $oldest->ID) {
                 $oldest = $r->ID;
             }
         }
         $all[] = $r;
     }
     foreach ($all as $a) {
         if ($a->ID == $oldest->ID) {
             continue;
         }
         $all_but_oldest[] = $a;
     }
     foreach ($all as $a) {
         if ($a->ID == $latest->ID) {
             continue;
         }
         $all_but_latest[] = $a;
     }
     if (class_exists('Subsite')) {
         Subsite::$disable_subsite_filter = true;
     }
     Config::inst()->update('DataObject', 'validation_enabled', false);
     // Rewrite all relations so everything is pointing to oldest
     // For some reason, the code in merge fails to do this properly
     $tables = DB::tableList();
     $objects = ClassInfo::subclassesFor('DataObject');
     foreach ($objects as $o) {
         $config = $o::config();
         if ($config->has_one) {
             foreach ($config->has_one as $name => $class) {
                 if ($class == 'Member') {
                     $table = ClassInfo::table_for_object_field($o, $name . 'ID');
                     if ($table && in_array(strtolower($table), $tables)) {
                         foreach ($all_but_oldest as $a) {
                             $sql = "UPDATE {$table} SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID;
                             DB::alteration_message($sql);
                             DB::query($sql);
                         }
                     }
                 }
             }
         }
         if ($config->has_many) {
             foreach ($config->has_many as $name => $class) {
                 if ($class == 'Member') {
                     $table = ClassInfo::table_for_object_field($o, $name . 'ID');
                     if ($table && in_array(strtolower($table), $tables)) {
                         foreach ($all_but_oldest as $a) {
                             $sql = "UPDATE {$table} SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID;
                             DB::alteration_message($sql);
                             DB::query($sql);
                         }
                     }
                 }
             }
         }
         if ($config->many_many) {
             foreach ($config->many_many as $name => $class) {
                 if ($class == 'Member') {
                     $table = ClassInfo::table_for_object_field($o, $name . 'ID');
                     if ($table && in_array(strtolower($table), $tables)) {
                         foreach ($all_but_oldest as $a) {
                             $sql = "UPDATE {$table} SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID;
                             DB::alteration_message($sql);
                             DB::query($sql);
                         }
                     }
                 }
             }
         }
     }
     // Now, we update to oldest record with the latest info
     $orgOldest = $oldest;
     $oldest->merge($latest, 'right', false);
     foreach ($all_but_oldest as $a) {
         $a->delete();
     }
     try {
         $oldest->write();
     } catch (Exception $ex) {
         $orgOldest->write();
     }
 }
 /**
  * Returns true if the table exists in the database
  *
  * @param    string $table
  * @return    boolean
  */
 public static function tableExists($table)
 {
     $tables = DB::tableList();
     return array_key_exists(strtolower($table), $tables);
 }
	/**
	 * Get an array containing all tables in the database.
	 * 
	 * @param boolean $lowercase
	 * 
	 * @return array
	 */
	public static function get_db_tables($lowercase = true) {
		if (!isset(self::$db_tables[$lowercase])) {
			// Build the cache over tables available in the database.
			self::$db_tables[$lowercase] = DB::tableList();
			if ($lowercase) {
				foreach (self::$db_tables[$lowercase] as $key => &$value)
					$value = strtolower($value);
			}
		}
		return self::$db_tables[$lowercase];
	}
Example #15
0
 /**
  * Constructor
  *
  * The constructor will check (once per script execution; with help of a
  * static variable) if the needed tables exist, otherwise it will create
  * them.
  *
  * @param string $associations_table This is an optional parameter to
  *                                   specify the name of the table used
  *                                   for storing associations.
  *                                   The default value is
  *                                   'authentication_openid_associations'.
  * @param string $nonces_table This is an optional parameter to specify
  *                             the name of the table used for storing
  *                             nonces.
  *                             The default value is
  *                             'authentication_openid_nonces'.
  *
  *
  * @todo Should the max. nonce age be configurable?
  * @todo Create the tables during installation, so we can reduce the
  *       number of needed SQL queries.
  */
 function __construct($associations_table = null, $nonces_table = null)
 {
     if (is_null($associations_table)) {
         $associations_table = 'authentication_openid_associations';
     }
     if (is_null($nonces_table)) {
         $nonces_table = 'authentication_openid_nonces';
     }
     $connection = new OpenIDDatabaseConnection();
     //-------------------------------------------------------------------//
     // This part normally resided in the Auth_OpenID_SQLStore class, but
     // due to a name conflict of the DB class we can't simple inherit from
     // it!
     $this->associations_table_name = "oid_associations";
     $this->nonces_table_name = "oid_nonces";
     // Check the connection object type to be sure it's a PEAR compatible
     // database connection.
     if (!(is_object($connection) && (is_subclass_of($connection, 'db_common') || is_subclass_of($connection, 'auth_openid_databaseconnection')))) {
         trigger_error("Auth_OpenID_SQLStore expected PEAR compatible " . "connection  object (got " . get_class($connection) . ")", E_USER_ERROR);
         return;
     }
     $this->connection = $connection;
     if ($associations_table) {
         $this->associations_table_name = $associations_table;
     }
     if ($nonces_table) {
         $this->nonces_table_name = $nonces_table;
     }
     $this->max_nonce_age = 6 * 60 * 60;
     // Be sure to run the database queries with auto-commit mode
     // turned OFF, because we want every function to run in a
     // transaction, implicitly.  As a rule, methods named with a
     // leading underscore will NOT control transaction behavior.
     // Callers of these methods will worry about transactions.
     $this->connection->autoCommit(false);
     // Create an empty SQL strings array.
     $this->sql = array();
     // Call this method (which should be overridden by subclasses)
     // to populate the $this->sql array with SQL strings.
     $this->setSQL();
     // Verify that all required SQL statements have been set, and
     // raise an error if any expected SQL strings were either
     // absent or empty.
     list($missing, $empty) = $this->_verifySQL();
     if ($missing) {
         trigger_error("Expected keys in SQL query list: " . implode(", ", $missing), E_USER_ERROR);
         return;
     }
     if ($empty) {
         trigger_error("SQL list keys have no SQL strings: " . implode(", ", $empty), E_USER_ERROR);
         return;
     }
     // Add table names to queries.
     $this->_fixSQL();
     //--------------------------------------------------------------------------------
     if (self::$S_checkedTableExistence == false) {
         $table_list = !isset(DB::getConn()->tableList) ? $table_list = DB::tableList() : DB::getConn()->tableList;
         $this->connection->autoCommit(true);
         if (!isset($table_list[strtolower($this->associations_table_name)])) {
             $this->create_assoc_table();
         }
         if (!isset($table_list[strtolower($this->nonces_table_name)])) {
             $this->create_nonce_table();
         }
         $this->connection->autoCommit(false);
         DB::tableList();
         self::$S_checkedTableExistence = true;
     }
 }
 /**
  * Performs the migration
  */
 public function run($request)
 {
     //Check for tables
     $tables = DB::tableList();
     if (!array_key_exists('languages', $tables) || !array_key_exists('snippits', $tables) || !array_key_exists('snippit_history', $tables) || !array_key_exists('preferences', $tables) || !array_key_exists('settings', $tables) || !array_key_exists('snippit_search', $tables) || !array_key_exists('users', $tables)) {
         echo '<b>' . _t('CodeBankLegacyMigrate.TABLES_NOT_FOUND', '_Could not find Code Bank 2.2 database tables, cannot migrate') . '</b>';
         exit;
     }
     //Ensure Empty
     if (Snippet::get()->Count() > 0) {
         echo '<b>' . _t('CodeBankLegacyMigrate.SNIPPETS_PRESENT', '_Already appears to be snippets present in the database, please start with a clean database, cannot migrate.') . '</b>';
         exit;
     }
     //Increase Timeout, since 30s probably won't be enough in huge databases
     increase_time_limit_to(600);
     //Find Other language
     $plainTextID = SnippetLanguage::get()->filter('Name', 'Other')->first();
     if (empty($plainTextID) || $plainTextID == false || $plainTextID->ID == 0) {
         echo _t('CodeBankLegacyMigrate.OTHER_NOT_FOUND', '_Could not find the Other Language, cannot migrate, please run dev/build first');
         exit;
     } else {
         $plainTextID = $plainTextID->ID;
     }
     //Check for users group
     $usersGroup = Group::get()->filter('Code', 'code-bank-api')->first();
     if (empty($usersGroup) || $usersGroup == false || $usersGroup->ID == 0) {
         //Rollback Transaction
         if (DB::getConn()->supportsTransactions()) {
             DB::getConn()->transactionRollback();
         }
         echo _t('CodeBankLegacyMigrate.GROUP_NOT_FOUND', '_Could not find users group, cannot migrate, please run dev/build first');
         exit;
     }
     //Start Transaction
     if (DB::getConn()->supportsTransactions()) {
         DB::getConn()->transactionStart();
     }
     //Migrate Languages
     echo '<b>' . _t('CodeBankLegacyMigrate.MIGRATE_USER_LANGUAGES', '_Migrating User Languages') . '</b>... ';
     $results = DB::query('SELECT * FROM "languages" WHERE "user_language"=1');
     if ($results->numRecords() > 0) {
         foreach ($results as $row) {
             DB::query('INSERT INTO "SnippetLanguage" ("ClassName","Created", "LastEdited", "Name", "FileExtension", "HighlightCode", "UserLanguage") ' . "VALUES('SnippetLanguage','" . date('Y-m-d H:i:s') . "','" . date('Y-m-d H:i:s') . "','" . Convert::raw2sql($row['language']) . "','" . Convert::raw2sql($row['file_extension']) . "','" . Convert::raw2sql($row['sjhs_code']) . "',1)");
         }
         echo _t('CodeBankLegacyMigrate.DONE', '_Done') . '<br/>';
     } else {
         echo _t('CodeBankLegacyMigrate.NOT_FOUND', '_None Found') . '<br/>';
     }
     //Migrate Users
     echo '<b>' . _t('CodeBankLegacyMigrate.MIGRATE_USERS', '_Migrating Users') . '</b>...';
     $results = DB::query('SELECT * FROM "users"');
     if ($results->numRecords() > 0) {
         foreach ($results as $row) {
             if ($row['deleted'] == true) {
                 echo '<br/><i>' . _t('CodeBankLegacyMigrate.DELETED_MEMBER_SKIP', '_WARNING: Skipping deleted member {username}, deleted members in Code Bank 3 are not supported', array('username' => $row['username'])) . '</i><br/>';
                 continue;
             }
             //Get user heartbeat preference
             $useHeartbeat = DB::query('SELECT "value" FROM "preferences" WHERE "code"=\'heartbeat\' AND "fkUser"=' . $row['id'])->value();
             //Insert User
             $member = Member::get()->filter('Email', Convert::raw2sql($row['username']))->first();
             if (empty($member) || $member === false || $member->ID == 0) {
                 $member = new Member();
                 $member->FirstName = $row['username'];
                 $member->Email = $row['username'];
                 $member->Password = $row['password'];
                 $member->PasswordEncryption = 'sha1';
                 $member->Locale = 'en_US';
                 $member->DateFormat = 'MMM d, yyyy';
                 $member->TimeFormat = 'h:mm:ss a';
                 $member->UseHeartbeat = intval($useHeartbeat);
                 $member->write();
                 DB::query('UPDATE "Member" ' . 'SET "Password"=\'' . substr(base_convert($row['password'], 16, 36), 0, 64) . '\', ' . '"Salt"=NULL ' . 'WHERE "ID"=' . $member->ID);
                 //Add to security group
                 if ($row['username'] == 'admin') {
                     //For admin add to administrators group
                     $member->addToGroupByCode('administrators');
                 } else {
                     //For all others add to code-bank-api
                     $member->addToGroupByCode('code-bank-api');
                 }
             } else {
                 //Add to code-bank-api if not admin
                 if ($row['username'] != 'admin') {
                     $member->addToGroupByCode('code-bank-api');
                 }
                 $member->UseHeartbeat = intval($useHeartbeat);
                 $member->write();
                 echo '<br/><i>' . _t('CodeBankLegacyMigrate.MEMBER_EXISTS', '_WARNING: Member {username} already exists in the database, no changes have been made to this member. If you are unsure of the password please ask an administrator to have it reset or use the forgot password link', array('username' => $row['username'])) . '</i><br/>';
             }
         }
         echo _t('CodeBankLegacyMigrate.DONE', '_Done') . '<br/>';
     } else {
         //Rollback Transaction
         if (DB::getConn()->supportsTransactions()) {
             DB::getConn()->transactionRollback();
         }
         echo _t('CodeBankLegacyMigrate.NO_USERS_FOUND', '_No users found, Code Bank 2.2 appears to have not been properly setup cannot continue with migration');
         exit;
     }
     //Migrate IP Message
     echo '<b>Migrating IP Message</b>...';
     $ipMessage = DB::query('SELECT "value" FROM "settings" WHERE "code"=\'ipMessage\'')->value();
     $config = CodeBankConfig::CurrentConfig();
     $config->IPMessage = $ipMessage;
     $config->write();
     echo _t('CodeBankLegacyMigrate.DONE', '_Done') . '<br/>';
     //Migrate Snippets
     echo '<b>' . _t('CodeBankLegacyMigrate.MIGRATE_SNIPPETS', '_Migrating Snippets') . '</b>...';
     $results = DB::query('SELECT "snippits".*, "languages"."language", "creator"."username" AS "creatorUsername", "lastEditor"."username" AS "lastEditorUsername" ' . 'FROM "snippits" ' . 'INNER JOIN "languages" ON "snippits"."fkLanguage"="languages"."id" ' . 'LEFT JOIN "users" "creator" ON "snippits"."fkCreatorUser"="creator"."id" ' . 'LEFT JOIN "users" "lastEditor" ON "snippits"."fkLastEditUser"="lastEditor"."id"');
     if ($results->numRecords() > 0) {
         foreach ($results as $row) {
             //Get Creator ID
             $creator = Member::get()->filter('Email', Convert::raw2sql($row['creatorUsername']))->first();
             if (!empty($creator) && $creator !== false && $creator->ID != 0) {
                 $creatorID = $creator->ID;
             } else {
                 $creatorID = 0;
             }
             //Get Last Editor ID
             $lastEditor = Member::get()->filter('Email', Convert::raw2sql($row['lastEditorUsername']))->first();
             if (!empty($lastEditor) && $lastEditor !== false && $lastEditor->ID != 0) {
                 $lastEditorID = $lastEditor->ID;
             } else {
                 $lastEditorID = 0;
             }
             //Get Language ID
             $language = SnippetLanguage::get()->filter('Name', Convert::raw2sql($row['language']))->first();
             if (!empty($language) && $language !== false && $language->ID != 0) {
                 $languageID = $language->ID;
             } else {
                 $languageID = $plainTextID;
             }
             //Insert Snippet Info
             DB::query('INSERT INTO "Snippet" ("ID", "ClassName", "Created", "LastEdited", "Title", "Description", "Tags", "LanguageID", "CreatorID", "LastEditorID") ' . "VALUES(" . $row['id'] . ",'Snippet','" . date('Y-m-d H:i:s') . "','" . date('Y-m-d H:i:s') . "','" . Convert::raw2sql($row['title']) . "','" . Convert::raw2sql($row['description']) . "','" . Convert::raw2sql($row['tags']) . "'," . $languageID . "," . $creatorID . "," . $lastEditorID . ")");
             //Get History
             $versions = DB::query('SELECT * FROM "snippit_history" WHERE "fkSnippit"=' . $row['id']);
             foreach ($versions as $version) {
                 DB::query('INSERT INTO "SnippetVersion" ("ClassName", "Created", "LastEdited", "Text", "ParentID") ' . "VALUES('SnippetVersion','" . date('Y-m-d H:i:s', strtotime($version['date'])) . "','" . date('Y-m-d H:i:s', strtotime($version['date'])) . "','" . Convert::raw2sql($version['text']) . "'," . $row['id'] . ")");
             }
         }
         echo _t('CodeBankLegacyMigrate.DONE', '_Done') . '<br/>';
     } else {
         echo _t('CodeBankLegacyMigrate.NO_SNIPPETS_FOUND', '_No snippets found') . '<br/>';
     }
     //Rename tables
     DB::getConn()->renameTable('snippits', '_obsolete_snippits');
     DB::getConn()->renameTable('snippit_search', '_obsolete_snippit_search');
     DB::getConn()->renameTable('snippit_history', '_obsolete_snippit_history');
     DB::getConn()->renameTable('languages', '_obsolete_languages');
     DB::getConn()->renameTable('settings', '_obsolete_settings');
     DB::getConn()->renameTable('preferences', '_obsolete_preferences');
     DB::getConn()->renameTable('users', '_obsolete_users');
     //Complete Transaction
     if (DB::getConn()->supportsTransactions()) {
         DB::getConn()->transactionEnd();
     }
     //Mark Migrated
     touch(ASSETS_PATH . '/.codeBankMigrated');
     echo '<br/><h4>' . _t('CodeBankLegacyMigrate.MIGRATION_COMPLETE', '_Migration Completed') . '</h4>';
     exit;
 }