Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Db/SchemaManager.php
<?php

namespace XF\Db;

use
XF\Db\Schema\AbstractDdl;

class
SchemaManager
{
    protected
$db;

    public function
__construct(AbstractAdapter $db)
    {
       
$this->db = $db;
    }

    public function
getTableCharacterSet($table)
    {
       
$table = $this->db->fetchRow("SHOW TABLE STATUS LIKE " . $this->db->quote($table));
        if (!
$table)
        {
            return
null;
        }

       
$collation = $table['Collation'];
        if (
preg_match('/^([^_]+)_/', $collation, $match))
        {
            return
$match[1];
        }
        else
        {
            return
$collation;
        }
    }

    public function
getTableEngine($table)
    {
       
$table = $this->db->fetchRow("SHOW TABLE STATUS LIKE " . $this->db->quote($table));
        if (!
$table)
        {
            return
null;
        }

        return
$table['Engine'];
    }

    public function
hasUnicodeMismatch(&$errorType = null, $checkTable = null)
    {
       
$tableCharset = $this->getTableCharacterSet($checkTable ?: 'xf_post');
       
$config = $this->db->getDefaultTableConfig();
       
$expectedCharset = $config['charset'];

        if (
$tableCharset == $expectedCharset)
        {
            return
false;
        }

        if (
$tableCharset == 'utf8mb4')
        {
           
// table is utf8mb4, only allowing utf8
           
$errorType = 'tight'; // our restrictions are too tight; won't allow valid characters
       
}
        else
        {
           
// table is utf8, allowing utf8mb4
           
$errorType = 'loose'; // our restrictions are too loose; allowing invalid characters
       
}

        return
true;
    }

    public function
getTableConfigSql($forceEngine = null)
    {
       
$tableConfig = $this->db->getDefaultTableConfig();
       
$engine = strtoupper($forceEngine ?: $tableConfig['engine']);
       
$charset = $tableConfig['charset'];
       
$collation = $tableConfig['collation'];

        return
"ENGINE = {$engine} CHARACTER SET {$charset} COLLATE {$collation}";
    }

    public function
getTableStatus($tableName)
    {
        return
$this->db->fetchRow('
            SHOW TABLE STATUS WHERE Name = ?
        '
, $tableName);
    }

    public function
getTableColumnDefinitions($tableName)
    {
        return
$this->db->fetchAllKeyed('
            SHOW FULL COLUMNS FROM `'
. $tableName . '`
        '
, 'Field');
    }

    public function
getTableIndexDefinitions($tableName)
    {
       
$indexes = $this->db->fetchAllKeyed('
            SHOW INDEXES FROM `'
. $tableName . '`
        '
, 'Field');

       
$grouped = [];
        foreach (
$indexes AS $index)
        {
           
$grouped[$index['Key_name']][$index['Seq_in_index']] = $index;
        }

        return
$grouped;
    }

    public function
tableExists($tableName)
    {
       
$status = $this->getTableStatus($tableName);

        return
$status ? true : false;
    }

    public function
columnExists($tableName, $column, &$definition = null)
    {
        if (!
$this->tableExists($tableName))
        {
            return
false;
        }

       
$columns = $this->getTableColumnDefinitions($tableName);
        if (isset(
$columns[$column]))
        {
           
$definition = $columns[$column];

            return
true;
        }
        else
        {
            return
false;
        }
    }

   
/**
     * @param $tableName
     * @param \Closure $toApply
     */
   
public function alterTable($tableName, \Closure $toApply)
    {
       
$alter = $this->newAlter($tableName);

        try
        {
           
$toApply($alter);
           
$alter->apply();
        }
        catch (\
Exception $e)
        {
           
$this->handleException($e, $tableName, $alter);
        }
    }

   
/**
     * @param $oldTableName
     * @param $newTableName
     */
   
public function renameTable($oldTableName, $newTableName)
    {
       
$alter = $this->newAlter($oldTableName)->renameTo($newTableName);

        try
        {
           
$alter->apply();
        }
        catch (\
Exception $e)
        {
           
$this->handleException($e, $oldTableName, $alter);
        }
    }

   
/**
     * @param $tableName
     * @param \Closure $toApply
     */
   
public function createTable($tableName, \Closure $toApply)
    {
       
$create = $this->newTable($tableName);

        try
        {
           
$toApply($create);
           
$create->apply();
        }
        catch (\
Exception $e)
        {
           
$this->handleException($e, $tableName, $create);
        }
    }

   
/**
     * @param $tableName
     * @param \Closure|null $toApply
     */
   
public function dropTable($tableName, \Closure $toApply = null)
    {
       
$drop = $this->newDrop($tableName);

        try
        {
            if (
$toApply)
            {
               
$toApply($drop);
            }
           
$drop->apply();
        }
        catch (\
Exception $e)
        {
           
$this->handleException($e, $tableName, $drop);
        }
    }

   
/**
     * @param $tableName
     *
     * @return Schema\Alter
     */
   
public function newAlter($tableName)
    {
        return new
Schema\Alter($this->db, $this, $tableName);
    }

   
/**
     * @param $tableName
     *
     * @return Schema\Create
     */
   
public function newTable($tableName)
    {
        return new
Schema\Create($this->db, $this, $tableName);
    }

   
/**
     * @param $tableName
     *
     * @return Schema\Drop
     */
   
public function newDrop($tableName)
    {
        return new
Schema\Drop($this->db, $this, $tableName);
    }

    protected function
handleException($exception, $tableName, AbstractDdl $ddl)
    {
       
// The exception might have some extra useful stuff in it, so include attempt to modify the message directly.

       
try
        {
           
$reflectionClass = new \ReflectionClass($exception);
           
$messageProperty = $reflectionClass->getProperty('message');
           
$messageProperty->setAccessible(true);
           
$messageProperty->setValue($exception, $tableName . ': ' . $messageProperty->getValue($exception));
        }
        catch (\
ReflectionException $ignored)
        {
        }

        throw
$exception;
    }
}