v.0.1
This commit is contained in:
247
vendor/illuminate/database/Schema/Grammars/ChangeColumn.php
vendored
Normal file
247
vendor/illuminate/database/Schema/Grammars/ChangeColumn.php
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema\Grammars;
|
||||
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager as SchemaManager;
|
||||
use Doctrine\DBAL\Schema\Comparator;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Fluent;
|
||||
use RuntimeException;
|
||||
|
||||
class ChangeColumn
|
||||
{
|
||||
/**
|
||||
* Compile a change column command into a series of SQL statements.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return array
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function compile($grammar, Blueprint $blueprint, Fluent $command, Connection $connection)
|
||||
{
|
||||
if (! $connection->isDoctrineAvailable()) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'Changing columns for table "%s" requires Doctrine DBAL. Please install the doctrine/dbal package.',
|
||||
$blueprint->getTable()
|
||||
));
|
||||
}
|
||||
|
||||
$schema = $connection->getDoctrineSchemaManager();
|
||||
$databasePlatform = $schema->getDatabasePlatform();
|
||||
$databasePlatform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
$tableDiff = static::getChangedDiff(
|
||||
$grammar, $blueprint, $schema
|
||||
);
|
||||
|
||||
if ($tableDiff !== false) {
|
||||
return (array) $databasePlatform->getAlterTableSQL($tableDiff);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Doctrine table difference for the given changes.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema
|
||||
* @return \Doctrine\DBAL\Schema\TableDiff|bool
|
||||
*/
|
||||
protected static function getChangedDiff($grammar, Blueprint $blueprint, SchemaManager $schema)
|
||||
{
|
||||
$current = $schema->listTableDetails($grammar->getTablePrefix().$blueprint->getTable());
|
||||
|
||||
return (new Comparator)->diffTable(
|
||||
$current, static::getTableWithColumnChanges($blueprint, $current)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of the given Doctrine table after making the column changes.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Doctrine\DBAL\Schema\Table $table
|
||||
* @return \Doctrine\DBAL\Schema\Table
|
||||
*/
|
||||
protected static function getTableWithColumnChanges(Blueprint $blueprint, Table $table)
|
||||
{
|
||||
$table = clone $table;
|
||||
|
||||
foreach ($blueprint->getChangedColumns() as $fluent) {
|
||||
$column = static::getDoctrineColumn($table, $fluent);
|
||||
|
||||
// Here we will spin through each fluent column definition and map it to the proper
|
||||
// Doctrine column definitions - which is necessary because Laravel and Doctrine
|
||||
// use some different terminology for various column attributes on the tables.
|
||||
foreach ($fluent->getAttributes() as $key => $value) {
|
||||
if (! is_null($option = static::mapFluentOptionToDoctrine($key))) {
|
||||
if (method_exists($column, $method = 'set'.ucfirst($option))) {
|
||||
$column->{$method}(static::mapFluentValueToDoctrine($option, $value));
|
||||
continue;
|
||||
}
|
||||
|
||||
$column->setCustomSchemaOption($option, static::mapFluentValueToDoctrine($option, $value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Doctrine column instance for a column change.
|
||||
*
|
||||
* @param \Doctrine\DBAL\Schema\Table $table
|
||||
* @param \Illuminate\Support\Fluent $fluent
|
||||
* @return \Doctrine\DBAL\Schema\Column
|
||||
*/
|
||||
protected static function getDoctrineColumn(Table $table, Fluent $fluent)
|
||||
{
|
||||
return $table->changeColumn(
|
||||
$fluent['name'], static::getDoctrineColumnChangeOptions($fluent)
|
||||
)->getColumn($fluent['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Doctrine column change options.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $fluent
|
||||
* @return array
|
||||
*/
|
||||
protected static function getDoctrineColumnChangeOptions(Fluent $fluent)
|
||||
{
|
||||
$options = ['type' => static::getDoctrineColumnType($fluent['type'])];
|
||||
|
||||
if (in_array($fluent['type'], ['text', 'mediumText', 'longText'])) {
|
||||
$options['length'] = static::calculateDoctrineTextLength($fluent['type']);
|
||||
}
|
||||
|
||||
if (static::doesntNeedCharacterOptions($fluent['type'])) {
|
||||
$options['customSchemaOptions'] = [
|
||||
'collation' => '',
|
||||
'charset' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the doctrine column type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return \Doctrine\DBAL\Types\Type
|
||||
*/
|
||||
protected static function getDoctrineColumnType($type)
|
||||
{
|
||||
$type = strtolower($type);
|
||||
|
||||
switch ($type) {
|
||||
case 'biginteger':
|
||||
$type = 'bigint';
|
||||
break;
|
||||
case 'smallinteger':
|
||||
$type = 'smallint';
|
||||
break;
|
||||
case 'mediumtext':
|
||||
case 'longtext':
|
||||
$type = 'text';
|
||||
break;
|
||||
case 'binary':
|
||||
$type = 'blob';
|
||||
break;
|
||||
case 'uuid':
|
||||
$type = 'guid';
|
||||
break;
|
||||
}
|
||||
|
||||
return Type::getType($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the proper column length to force the Doctrine text type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return int
|
||||
*/
|
||||
protected static function calculateDoctrineTextLength($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'mediumText':
|
||||
return 65535 + 1;
|
||||
case 'longText':
|
||||
return 16777215 + 1;
|
||||
default:
|
||||
return 255 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given type does not need character / collation options.
|
||||
*
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
protected static function doesntNeedCharacterOptions($type)
|
||||
{
|
||||
return in_array($type, [
|
||||
'bigInteger',
|
||||
'binary',
|
||||
'boolean',
|
||||
'date',
|
||||
'decimal',
|
||||
'double',
|
||||
'float',
|
||||
'integer',
|
||||
'json',
|
||||
'mediumInteger',
|
||||
'smallInteger',
|
||||
'time',
|
||||
'tinyInteger',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matching Doctrine option for a given Fluent attribute name.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function mapFluentOptionToDoctrine($attribute)
|
||||
{
|
||||
switch ($attribute) {
|
||||
case 'type':
|
||||
case 'name':
|
||||
return;
|
||||
case 'nullable':
|
||||
return 'notnull';
|
||||
case 'total':
|
||||
return 'precision';
|
||||
case 'places':
|
||||
return 'scale';
|
||||
default:
|
||||
return $attribute;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matching Doctrine value for a given Fluent attribute.
|
||||
*
|
||||
* @param string $option
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected static function mapFluentValueToDoctrine($option, $value)
|
||||
{
|
||||
return $option === 'notnull' ? ! $value : $value;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user