Skip to content
Snippets Groups Projects
Select Git revision
  • b276ede7b7bed2b2a30bfe17ab7fbb510e162985
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

DBSchemaVersion.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    DBSchemaVersion.php 6.28 KiB
    <?php
    /**
     * DBSchemaVersion.php - database backed schema versions
     *
     * Implementation of SchemaVersion interface using a database table.
     *
     * @author    Elmar Ludwig
     * @copyright 2007 Elmar Ludwig
     * @license    GPL2 or any later version
     * @package migrations
     */
    class DBSchemaVersion implements SchemaVersion
    {
        /**
         * domain name of schema version
         *
         * @var string
         */
        private $domain;
    
        /**
         * branch of schema version
         *
         * @var string
         */
        private $branch;
    
        /**
         * current schema version numbers
         *
         * @access private
         * @var array
         */
        private $versions;
    
        /**
         * Initialize a new DBSchemaVersion for a given domain.
         * The default domain name is 'studip'.
         *
         * @param string $domain domain name (optional)
         * @param string $branch schema branch (optional)
         */
        public function __construct($domain = 'studip', $branch = 0)
        {
            $this->domain = $domain;
            $this->branch = $branch;
            $this->versions = [0];
            $this->validateSchemaVersion();
            $this->initSchemaInfo();
        }
    
        /**
         * Retrieve the domain name of this schema.
         *
         * @return string domain name
         */
        public function getDomain()
        {
            return $this->domain;
        }
    
        /**
         * Retrieve the branch of this schema.
         *
         * @return string schema branch
         */
        public function getBranch()
        {
            return $this->branch;
        }
    
        /**
         * Retrieve all branches of this schema.
         *
         * @return array all schema branches
         */
        public function getAllBranches()
        {
            return array_keys($this->versions);
        }
    
        /**
         * Check whether the current schema_version supports branches.
         */
        private function branchSupported()
        {
            $result = DBManager::get()->query("DESCRIBE schema_version 'branch'");
            return $result && $result->rowCount() > 0;
        }
    
        /**
         * Initialize the current schema versions.
         */
        private function initSchemaInfo()
        {
            if (!$this->branchSupported()) {
                $branch = $this->domain === 'studip' ? 1 : 0;
                $query = "SELECT $branch, version FROM schema_version WHERE domain = ?";
            } else {
                $query = "SELECT branch, version FROM schema_version WHERE domain = ? ORDER BY branch";
            }
            $statement = DBManager::get()->prepare($query);
            $statement->execute([$this->domain]);
            $versions = $statement->fetchAll(PDO::FETCH_COLUMN | PDO::FETCH_GROUP | PDO::FETCH_UNIQUE);
    
            foreach ($versions as $branch => $version) {
                $this->versions[$branch] = (int) $version;
            }
        }
    
        /**
         * Retrieve the current schema version.
         *
         * @param string $branch schema branch (optional)
         * @return int schema version
         */
        public function get($branch = 0)
        {
            return $this->versions[$branch];
        }
    
        /**
         * Set the current schema version.
         *
         * @param int $version new schema version
         * @param string $branch schema branch (optional)
         */
        public function set($version, $branch = 0)
        {
            $this->versions[$branch] = (int) $version;
    
            if (!$this->branchSupported()) {
                $query = "INSERT INTO schema_version (domain, version)
                          VALUES (?, ?)
                          ON DUPLICATE KEY UPDATE version = VALUES(version)";
                $statement = DBManager::get()->prepare($query);
                $statement->execute([
                    $this->domain,
                    $version
                ]);
            } else {
                $query = "INSERT INTO schema_version (domain, branch, version)
                          VALUES (?, ?, ?)
                          ON DUPLICATE KEY UPDATE version = VALUES(version)";
                $statement = DBManager::get()->prepare($query);
                $statement->execute([
                    $this->domain,
                    $branch,
                    $version
                ]);
            }
            NotificationCenter::postNotification(
                'SchemaVersionDidUpdate',
                $this->domain,
                $version
            );
        }
    
        /**
         * Validate correct structure of schema_version table. This
         * will upgrade the schema from 4.4 style to 5.1 if necessary.
         */
        private function validateSchemaVersion()
        {
            $db = DBManager::get();
            $result = $db->query("SHOW TABLES LIKE 'schema_versions'");
    
            if ($result && $result->rowCount() > 0) {
                $backported_migrations = [
                    20200306, 20200713, 20200811, 20200909, 20200910,
                    20201002, 20201103, 202011031, 20210317
                ];
    
                // drop backported migrations
                $query = "DELETE FROM schema_versions
                          WHERE domain = 'studip' AND version in (?)";
                $db->execute($query, [$backported_migrations]);
    
                // drop migrations with irregular numbers
                $query = "DELETE FROM schema_versions
                          WHERE domain = 'studip' AND LENGTH(version) > 8";
                $db->exec($query);
    
                $query = "CREATE TABLE schema_version (
                            domain VARCHAR(255) COLLATE latin1_bin NOT NULL,
                            branch VARCHAR(64) COLLATE latin1_bin NOT NULL DEFAULT '0',
                            version INT(11) UNSIGNED NOT NULL,
                            PRIMARY KEY (domain, branch)
                          ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC";
                $db->exec($query);
    
                $query = "INSERT INTO schema_version
                          SELECT domain, '0', MAX(version) FROM schema_versions
                          GROUP BY domain";
                $db->exec($query);
    
                $query = "DROP TABLE schema_versions";
                $db->exec($query);
    
                $schema_mapping = [
                    20190917 => 269,
                    20200307 => 285,
                    20200522 => 290,
                    20210511 => 327,
                    20210603 => 328
                ];
    
                $query = "UPDATE schema_version SET branch = '1' WHERE domain = 'studip'";
                $db->exec($query);
    
                foreach ($schema_mapping as $old_version => $new_version) {
                    $query = "UPDATE schema_version SET version = ?
                              WHERE domain = 'studip' AND version = ?";
                    $db->execute($query, [$new_version, $old_version]);
                }
            }
        }
    }