Вход Регистрация
Файл: gapps/vendor/laravel/framework/src/Illuminate/Database/Schema/Grammars/Grammar.php
Строк: 680
<?php

namespace IlluminateDatabaseSchemaGrammars;

use 
RuntimeException;
use 
DoctrineDBALTypesType;
use 
IlluminateSupportFluent;
use 
DoctrineDBALSchemaTable;
use 
DoctrineDBALSchemaColumn;
use 
DoctrineDBALSchemaTableDiff;
use 
IlluminateDatabaseConnection;
use 
DoctrineDBALSchemaComparator;
use 
IlluminateDatabaseQueryExpression;
use 
IlluminateDatabaseSchemaBlueprint;
use 
IlluminateDatabaseGrammar as BaseGrammar;
use 
DoctrineDBALSchemaAbstractSchemaManager as SchemaManager;

abstract class 
Grammar extends BaseGrammar
{
    
/**
     * Compile a rename column command.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  IlluminateSupportFluent  $command
     * @param  IlluminateDatabaseConnection  $connection
     * @return array
     */
    
public function compileRenameColumn(Blueprint $blueprintFluent $commandConnection $connection)
    {
        
$schema $connection->getDoctrineSchemaManager();

        
$table $this->getTablePrefix().$blueprint->getTable();

        
$column $connection->getDoctrineColumn($table$command->from);

        
$tableDiff $this->getRenamedDiff($blueprint$command$column$schema);

        return (array) 
$schema->getDatabasePlatform()->getAlterTableSQL($tableDiff);
    }

    
/**
     * Get a new column instance with the new column name.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  IlluminateSupportFluent  $command
     * @param  DoctrineDBALSchemaColumn  $column
     * @param  DoctrineDBALSchemaAbstractSchemaManager  $schema
     * @return DoctrineDBALSchemaTableDiff
     */
    
protected function getRenamedDiff(Blueprint $blueprintFluent $commandColumn $columnSchemaManager $schema)
    {
        
$tableDiff $this->getDoctrineTableDiff($blueprint$schema);

        return 
$this->setRenamedColumns($tableDiff$command$column);
    }

    
/**
     * Set the renamed columns on the table diff.
     *
     * @param  DoctrineDBALSchemaTableDiff  $tableDiff
     * @param  IlluminateSupportFluent  $command
     * @param  DoctrineDBALSchemaColumn  $column
     * @return DoctrineDBALSchemaTableDiff
     */
    
protected function setRenamedColumns(TableDiff $tableDiffFluent $commandColumn $column)
    {
        
$newColumn = new Column($command->to$column->getType(), $column->toArray());

        
$tableDiff->renamedColumns = [$command->from => $newColumn];

        return 
$tableDiff;
    }

    
/**
     * Compile a foreign key command.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  IlluminateSupportFluent  $command
     * @return string
     */
    
public function compileForeign(Blueprint $blueprintFluent $command)
    {
        
$table $this->wrapTable($blueprint);

        
$index $this->wrap($command->index);

        
$on $this->wrapTable($command->on);

        
// We need to prepare several of the elements of the foreign key definition
        // before we can create the SQL, such as wrapping the tables and convert
        // an array of columns to comma-delimited strings for the SQL queries.
        
$columns $this->columnize($command->columns);

        
$onColumns $this->columnize((array) $command->references);

        
$sql "alter table {$table} add constraint {$index} ";

        
$sql .= "foreign key ({$columns}) references {$on} ({$onColumns})";

        
// Once we have the basic foreign key creation statement constructed we can
        // build out the syntax for what should happen on an update or delete of
        // the affected columns, which will get something like "cascade", etc.
        
if (! is_null($command->onDelete)) {
            
$sql .= " on delete {$command->onDelete}";
        }

        if (! 
is_null($command->onUpdate)) {
            
$sql .= " on update {$command->onUpdate}";
        }

        return 
$sql;
    }

    
/**
     * Compile the blueprint's column definitions.
     *
     * @param  IlluminateDatabaseSchemaBlueprint $blueprint
     * @return array
     */
    
protected function getColumns(Blueprint $blueprint)
    {
        
$columns = [];

        foreach (
$blueprint->getAddedColumns() as $column) {
            
// Each of the column types have their own compiler functions which are tasked
            // with turning the column definition into its SQL format for this platform
            // used by the connection. The column's modifiers are compiled and added.
            
$sql $this->wrap($column).' '.$this->getType($column);

            
$columns[] = $this->addModifiers($sql$blueprint$column);
        }

        return 
$columns;
    }

    
/**
     * Add the column modifiers to the definition.
     *
     * @param  string  $sql
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  IlluminateSupportFluent  $column
     * @return string
     */
    
protected function addModifiers($sqlBlueprint $blueprintFluent $column)
    {
        foreach (
$this->modifiers as $modifier) {
            if (
method_exists($this$method "modify{$modifier}")) {
                
$sql .= $this->{$method}($blueprint$column);
            }
        }

        return 
$sql;
    }

    
/**
     * Get the primary key command if it exists on the blueprint.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  string  $name
     * @return IlluminateSupportFluent|null
     */
    
protected function getCommandByName(Blueprint $blueprint$name)
    {
        
$commands $this->getCommandsByName($blueprint$name);

        if (
count($commands) > 0) {
            return 
reset($commands);
        }
    }

    
/**
     * Get all of the commands with a given name.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  string  $name
     * @return array
     */
    
protected function getCommandsByName(Blueprint $blueprint$name)
    {
        return 
array_filter($blueprint->getCommands(), function ($value) use ($name) {
            return 
$value->name == $name;
        });
    }

    
/**
     * Get the SQL for the column data type.
     *
     * @param  IlluminateSupportFluent  $column
     * @return string
     */
    
protected function getType(Fluent $column)
    {
        return 
$this->{'type'.ucfirst($column->type)}($column);
    }

    
/**
     * Add a prefix to an array of values.
     *
     * @param  string  $prefix
     * @param  array   $values
     * @return array
     */
    
public function prefixArray($prefix, array $values)
    {
        return 
array_map(function ($value) use ($prefix) {
            return 
$prefix.' '.$value;
        }, 
$values);
    }

    
/**
     * Wrap a table in keyword identifiers.
     *
     * @param  mixed   $table
     * @return string
     */
    
public function wrapTable($table)
    {
        if (
$table instanceof Blueprint) {
            
$table $table->getTable();
        }

        return 
parent::wrapTable($table);
    }

    
/**
     * {@inheritdoc}
     */
    
public function wrap($value$prefixAlias false)
    {
        if (
$value instanceof Fluent) {
            
$value $value->name;
        }

        return 
parent::wrap($value$prefixAlias);
    }

    
/**
     * Format a value so that it can be used in "default" clauses.
     *
     * @param  mixed   $value
     * @return string
     */
    
protected function getDefaultValue($value)
    {
        if (
$value instanceof Expression) {
            return 
$value;
        }

        if (
is_bool($value)) {
            return 
"'".(int) $value."'";
        }

        return 
"'".strval($value)."'";
    }

    
/**
     * Create an empty Doctrine DBAL TableDiff from the Blueprint.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  DoctrineDBALSchemaAbstractSchemaManager  $schema
     * @return DoctrineDBALSchemaTableDiff
     */
    
protected function getDoctrineTableDiff(Blueprint $blueprintSchemaManager $schema)
    {
        
$table $this->getTablePrefix().$blueprint->getTable();

        
$tableDiff = new TableDiff($table);

        
$tableDiff->fromTable $schema->listTableDetails($table);

        return 
$tableDiff;
    }

    
/**
     * Compile a change column command into a series of SQL statements.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  IlluminateSupportFluent  $command
     * @param  IlluminateDatabaseConnection $connection
     * @return array
     *
     * @throws RuntimeException
     */
    
public function compileChange(Blueprint $blueprintFluent $commandConnection $connection)
    {
        if (! 
$connection->isDoctrineAvailable()) {
            throw new 
RuntimeException(sprintf(
                
'Changing columns for table "%s" requires Doctrine DBAL; install "doctrine/dbal".',
                
$blueprint->getTable()
            ));
        }

        
$schema $connection->getDoctrineSchemaManager();

        
$tableDiff $this->getChangedDiff($blueprint$schema);

        if (
$tableDiff !== false) {
            return (array) 
$schema->getDatabasePlatform()->getAlterTableSQL($tableDiff);
        }

        return [];
    }

    
/**
     * Get the Doctrine table difference for the given changes.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  DoctrineDBALSchemaAbstractSchemaManager  $schema
     * @return DoctrineDBALSchemaTableDiff|bool
     */
    
protected function getChangedDiff(Blueprint $blueprintSchemaManager $schema)
    {
        
$table $schema->listTableDetails($this->getTablePrefix().$blueprint->getTable());

        return (new 
Comparator)->diffTable($table$this->getTableWithColumnChanges($blueprint$table));
    }

    
/**
     * Get a copy of the given Doctrine table after making the column changes.
     *
     * @param  IlluminateDatabaseSchemaBlueprint  $blueprint
     * @param  DoctrineDBALSchemaTable  $table
     * @return DoctrineDBALSchemaTableDiff
     */
    
protected function getTableWithColumnChanges(Blueprint $blueprintTable $table)
    {
        
$table = clone $table;

        foreach (
$blueprint->getChangedColumns() as $fluent) {
            
$column $this->getDoctrineColumnForChange($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 $this->mapFluentOptionToDoctrine($key))) {
                    if (
method_exists($column$method 'set'.ucfirst($option))) {
                        
$column->{$method}($this->mapFluentValueToDoctrine($option$value));
                    }
                }
            }
        }

        return 
$table;
    }

    
/**
     * Get the Doctrine column instance for a column change.
     *
     * @param  DoctrineDBALSchemaTable  $table
     * @param  IlluminateSupportFluent  $fluent
     * @return DoctrineDBALSchemaColumn
     */
    
protected function getDoctrineColumnForChange(Table $tableFluent $fluent)
    {
        return 
$table->changeColumn(
            
$fluent['name'], $this->getDoctrineColumnChangeOptions($fluent)
        )->
getColumn($fluent['name']);
    }

    
/**
     * Get the Doctrine column change options.
     *
     * @param  IlluminateSupportFluent  $fluent
     * @return array
     */
    
protected function getDoctrineColumnChangeOptions(Fluent $fluent)
    {
        
$options = ['type' => $this->getDoctrineColumnType($fluent['type'])];

        if (
in_array($fluent['type'], ['text''mediumText''longText'])) {
            
$options['length'] = $this->calculateDoctrineTextLength($fluent['type']);
        }

        return 
$options;
    }

    
/**
     * Get the doctrine column type.
     *
     * @param  string  $type
     * @return DoctrineDBALTypesType
     */
    
protected 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;
        }

        return 
Type::getType($type);
    }

    
/**
     * Calculate the proper column length to force the Doctrine text type.
     *
     * @param  string  $type
     * @return int
     */
    
protected function calculateDoctrineTextLength($type)
    {
        switch (
$type) {
            case 
'mediumText':
                return 
65535 1;
            case 
'longText':
                return 
16777215 1;
            default:
                return 
255 1;
        }
    }

    
/**
     * Get the matching Doctrine option for a given Fluent attribute name.
     *
     * @param  string  $attribute
     * @return string|null
     */
    
protected 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 function mapFluentValueToDoctrine($option$value)
    {
        return 
$option == 'notnull' ? ! $value $value;
    }
}
Онлайн: 1
Реклама