Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/cakephp/src/Database/Schema/TableSchema.php
<?php
/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 * @link          https://cakephp.org CakePHP(tm) Project
 * @since         3.0.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Cake\Database\Schema;

use
Cake\Database\Connection;
use
Cake\Database\Exception;
use
Cake\Database\Type;

/**
 * Represents a single table in a database schema.
 *
 * Can either be populated using the reflection API's
 * or by incrementally building an instance using
 * methods.
 *
 * Once created TableSchema instances can be added to
 * Schema\Collection objects. They can also be converted into SQL using the
 * createSql(), dropSql() and truncateSql() methods.
 */
class TableSchema implements TableSchemaInterface, SqlGeneratorInterface
{
   
/**
     * The name of the table
     *
     * @var string
     */
   
protected $_table;

   
/**
     * Columns in the table.
     *
     * @var array
     */
   
protected $_columns = [];

   
/**
     * A map with columns to types
     *
     * @var array
     */
   
protected $_typeMap = [];

   
/**
     * Indexes in the table.
     *
     * @var array
     */
   
protected $_indexes = [];

   
/**
     * Constraints in the table.
     *
     * @var array
     */
   
protected $_constraints = [];

   
/**
     * Options for the table.
     *
     * @var array
     */
   
protected $_options = [];

   
/**
     * Whether or not the table is temporary
     *
     * @var bool
     */
   
protected $_temporary = false;

   
/**
     * Column length when using a `tiny` column type
     *
     * @var int
     */
   
const LENGTH_TINY = 255;

   
/**
     * Column length when using a `medium` column type
     *
     * @var int
     */
   
const LENGTH_MEDIUM = 16777215;

   
/**
     * Column length when using a `long` column type
     *
     * @var int
     */
   
const LENGTH_LONG = 4294967295;

   
/**
     * Valid column length that can be used with text type columns
     *
     * @var array
     */
   
public static $columnLengths = [
       
'tiny' => self::LENGTH_TINY,
       
'medium' => self::LENGTH_MEDIUM,
       
'long' => self::LENGTH_LONG,
    ];

   
/**
     * The valid keys that can be used in a column
     * definition.
     *
     * @var array
     */
   
protected static $_columnKeys = [
       
'type' => null,
       
'baseType' => null,
       
'length' => null,
       
'precision' => null,
       
'null' => null,
       
'default' => null,
       
'comment' => null,
    ];

   
/**
     * Additional type specific properties.
     *
     * @var array
     */
   
protected static $_columnExtras = [
       
'string' => [
           
'fixed' => null,
           
'collate' => null,
        ],
       
'text' => [
           
'collate' => null,
        ],
       
'tinyinteger' => [
           
'unsigned' => null,
        ],
       
'smallinteger' => [
           
'unsigned' => null,
        ],
       
'integer' => [
           
'unsigned' => null,
           
'autoIncrement' => null,
        ],
       
'biginteger' => [
           
'unsigned' => null,
           
'autoIncrement' => null,
        ],
       
'decimal' => [
           
'unsigned' => null,
        ],
       
'float' => [
           
'unsigned' => null,
        ],
    ];

   
/**
     * The valid keys that can be used in an index
     * definition.
     *
     * @var array
     */
   
protected static $_indexKeys = [
       
'type' => null,
       
'columns' => [],
       
'length' => [],
       
'references' => [],
       
'update' => 'restrict',
       
'delete' => 'restrict',
    ];

   
/**
     * Names of the valid index types.
     *
     * @var array
     */
   
protected static $_validIndexTypes = [
       
self::INDEX_INDEX,
       
self::INDEX_FULLTEXT,
    ];

   
/**
     * Names of the valid constraint types.
     *
     * @var array
     */
   
protected static $_validConstraintTypes = [
       
self::CONSTRAINT_PRIMARY,
       
self::CONSTRAINT_UNIQUE,
       
self::CONSTRAINT_FOREIGN,
    ];

   
/**
     * Names of the valid foreign key actions.
     *
     * @var array
     */
   
protected static $_validForeignKeyActions = [
       
self::ACTION_CASCADE,
       
self::ACTION_SET_NULL,
       
self::ACTION_SET_DEFAULT,
       
self::ACTION_NO_ACTION,
       
self::ACTION_RESTRICT,
    ];

   
/**
     * Primary constraint type
     *
     * @var string
     */
   
const CONSTRAINT_PRIMARY = 'primary';

   
/**
     * Unique constraint type
     *
     * @var string
     */
   
const CONSTRAINT_UNIQUE = 'unique';

   
/**
     * Foreign constraint type
     *
     * @var string
     */
   
const CONSTRAINT_FOREIGN = 'foreign';

   
/**
     * Index - index type
     *
     * @var string
     */
   
const INDEX_INDEX = 'index';

   
/**
     * Fulltext index type
     *
     * @var string
     */
   
const INDEX_FULLTEXT = 'fulltext';

   
/**
     * Foreign key cascade action
     *
     * @var string
     */
   
const ACTION_CASCADE = 'cascade';

   
/**
     * Foreign key set null action
     *
     * @var string
     */
   
const ACTION_SET_NULL = 'setNull';

   
/**
     * Foreign key no action
     *
     * @var string
     */
   
const ACTION_NO_ACTION = 'noAction';

   
/**
     * Foreign key restrict action
     *
     * @var string
     */
   
const ACTION_RESTRICT = 'restrict';

   
/**
     * Foreign key restrict default
     *
     * @var string
     */
   
const ACTION_SET_DEFAULT = 'setDefault';

   
/**
     * Constructor.
     *
     * @param string $table The table name.
     * @param array $columns The list of columns for the schema.
     */
   
public function __construct($table, array $columns = [])
    {
       
$this->_table = $table;
        foreach (
$columns as $field => $definition) {
           
$this->addColumn($field, $definition);
        }
    }

   
/**
     * {@inheritDoc}
     */
   
public function name()
    {
        return
$this->_table;
    }

   
/**
     * {@inheritDoc}
     */
   
public function addColumn($name, $attrs)
    {
        if (
is_string($attrs)) {
           
$attrs = ['type' => $attrs];
        }
       
$valid = static::$_columnKeys;
        if (isset(static::
$_columnExtras[$attrs['type']])) {
           
$valid += static::$_columnExtras[$attrs['type']];
        }
       
$attrs = array_intersect_key($attrs, $valid);
       
$this->_columns[$name] = $attrs + $valid;
       
$this->_typeMap[$name] = $this->_columns[$name]['type'];

        return
$this;
    }

   
/**
     * {@inheritDoc}
     */
   
public function removeColumn($name)
    {
        unset(
$this->_columns[$name], $this->_typeMap[$name]);

        return
$this;
    }

   
/**
     * {@inheritDoc}
     */
   
public function columns()
    {
        return
array_keys($this->_columns);
    }

   
/**
     * Get column data in the table.
     *
     * @param string $name The column name.
     * @return array|null Column data or null.
     * @deprecated 3.5.0 Use getColumn() instead.
     */
   
public function column($name)
    {
       
deprecationWarning('TableSchema::column() is deprecated. Use TableSchema::getColumn() instead.');

        return
$this->getColumn($name);
    }

   
/**
     * {@inheritDoc}
     */
   
public function getColumn($name)
    {
        if (!isset(
$this->_columns[$name])) {
            return
null;
        }
       
$column = $this->_columns[$name];
        unset(
$column['baseType']);

        return
$column;
    }

   
/**
     * Sets the type of a column, or returns its current type
     * if none is passed.
     *
     * @param string $name The column to get the type of.
     * @param string|null $type The type to set the column to.
     * @return string|null Either the column type or null.
     * @deprecated 3.5.0 Use setColumnType()/getColumnType() instead.
     */
   
public function columnType($name, $type = null)
    {
       
deprecationWarning('TableSchema::columnType() is deprecated. Use TableSchema::setColumnType() or TableSchema::getColumnType() instead.');

        if (
$type !== null) {
           
$this->setColumnType($name, $type);
        }

        return
$this->getColumnType($name);
    }

   
/**
     * {@inheritDoc}
     */
   
public function getColumnType($name)
    {
        if (!isset(
$this->_columns[$name])) {
            return
null;
        }

        return
$this->_columns[$name]['type'];
    }

   
/**
     * {@inheritDoc}
     */
   
public function setColumnType($name, $type)
    {
        if (!isset(
$this->_columns[$name])) {
            return
$this;
        }

       
$this->_columns[$name]['type'] = $type;
       
$this->_typeMap[$name] = $type;

        return
$this;
    }

   
/**
     * {@inheritDoc}
     */
   
public function hasColumn($name)
    {
        return isset(
$this->_columns[$name]);
    }

   
/**
     * {@inheritDoc}
     */
   
public function baseColumnType($column)
    {
        if (isset(
$this->_columns[$column]['baseType'])) {
            return
$this->_columns[$column]['baseType'];
        }

       
$type = $this->getColumnType($column);

        if (
$type === null) {
            return
null;
        }

        if (
Type::getMap($type)) {
           
$type = Type::build($type)->getBaseType();
        }

        return
$this->_columns[$column]['baseType'] = $type;
    }

   
/**
     * {@inheritDoc}
     */
   
public function typeMap()
    {
        return
$this->_typeMap;
    }

   
/**
     * {@inheritDoc}
     */
   
public function isNullable($name)
    {
        if (!isset(
$this->_columns[$name])) {
            return
true;
        }

        return (
$this->_columns[$name]['null'] === true);
    }

   
/**
     * {@inheritDoc}
     */
   
public function defaultValues()
    {
       
$defaults = [];
        foreach (
$this->_columns as $name => $data) {
            if (!
array_key_exists('default', $data)) {
                continue;
            }
            if (
$data['default'] === null && $data['null'] !== true) {
                continue;
            }
           
$defaults[$name] = $data['default'];
        }

        return
$defaults;
    }

   
/**
     * {@inheritDoc}
     * @throws \Cake\Database\Exception
     */
   
public function addIndex($name, $attrs)
    {
        if (
is_string($attrs)) {
           
$attrs = ['type' => $attrs];
        }
       
$attrs = array_intersect_key($attrs, static::$_indexKeys);
       
$attrs += static::$_indexKeys;
        unset(
$attrs['references'], $attrs['update'], $attrs['delete']);

        if (!
in_array($attrs['type'], static::$_validIndexTypes, true)) {
            throw new
Exception(sprintf('Invalid index type "%s" in index "%s" in table "%s".', $attrs['type'], $name, $this->_table));
        }
        if (empty(
$attrs['columns'])) {
            throw new
Exception(sprintf('Index "%s" in table "%s" must have at least one column.', $name, $this->_table));
        }
       
$attrs['columns'] = (array)$attrs['columns'];
        foreach (
$attrs['columns'] as $field) {
            if (empty(
$this->_columns[$field])) {
               
$msg = sprintf(
                   
'Columns used in index "%s" in table "%s" must be added to the Table schema first. ' .
                   
'The column "%s" was not found.',
                   
$name,
                   
$this->_table,
                   
$field
               
);
                throw new
Exception($msg);
            }
        }
       
$this->_indexes[$name] = $attrs;

        return
$this;
    }

   
/**
     * {@inheritDoc}
     */
   
public function indexes()
    {
        return
array_keys($this->_indexes);
    }

   
/**
     * Read information about an index based on name.
     *
     * @param string $name The name of the index.
     * @return array|null Array of index data, or null
     * @deprecated 3.5.0 Use getIndex() instead.
     */
   
public function index($name)
    {
       
deprecationWarning('TableSchema::index() is deprecated. Use TableSchema::getIndex() instead.');

        return
$this->getIndex($name);
    }

   
/**
     * {@inheritDoc}
     */
   
public function getIndex($name)
    {
        if (!isset(
$this->_indexes[$name])) {
            return
null;
        }

        return
$this->_indexes[$name];
    }

   
/**
     * {@inheritDoc}
     */
   
public function primaryKey()
    {
        foreach (
$this->_constraints as $name => $data) {
            if (
$data['type'] === static::CONSTRAINT_PRIMARY) {
                return
$data['columns'];
            }
        }

        return [];
    }

   
/**
     * {@inheritDoc}
     * @throws \Cake\Database\Exception
     */
   
public function addConstraint($name, $attrs)
    {
        if (
is_string($attrs)) {
           
$attrs = ['type' => $attrs];
        }
       
$attrs = array_intersect_key($attrs, static::$_indexKeys);
       
$attrs += static::$_indexKeys;
        if (!
in_array($attrs['type'], static::$_validConstraintTypes, true)) {
            throw new
Exception(sprintf('Invalid constraint type "%s" in table "%s".', $attrs['type'], $this->_table));
        }
        if (empty(
$attrs['columns'])) {
            throw new
Exception(sprintf('Constraints in table "%s" must have at least one column.', $this->_table));
        }
       
$attrs['columns'] = (array)$attrs['columns'];
        foreach (
$attrs['columns'] as $field) {
            if (empty(
$this->_columns[$field])) {
               
$msg = sprintf(
                   
'Columns used in constraints must be added to the Table schema first. ' .
                   
'The column "%s" was not found in table "%s".',
                   
$field,
                   
$this->_table
               
);
                throw new
Exception($msg);
            }
        }

        if (
$attrs['type'] === static::CONSTRAINT_FOREIGN) {
           
$attrs = $this->_checkForeignKey($attrs);

            if (isset(
$this->_constraints[$name])) {
               
$this->_constraints[$name]['columns'] = array_unique(array_merge(
                   
$this->_constraints[$name]['columns'],
                   
$attrs['columns']
                ));

                if (isset(
$this->_constraints[$name]['references'])) {
                   
$this->_constraints[$name]['references'][1] = array_unique(array_merge(
                        (array)
$this->_constraints[$name]['references'][1],
                        [
$attrs['references'][1]]
                    ));
                }

                return
$this;
            }
        } else {
            unset(
$attrs['references'], $attrs['update'], $attrs['delete']);
        }

       
$this->_constraints[$name] = $attrs;

        return
$this;
    }

   
/**
     * {@inheritDoc}
     */
   
public function dropConstraint($name)
    {
        if (isset(
$this->_constraints[$name])) {
            unset(
$this->_constraints[$name]);
        }

        return
$this;
    }

   
/**
     * Check whether or not a table has an autoIncrement column defined.
     *
     * @return bool
     */
   
public function hasAutoincrement()
    {
        foreach (
$this->_columns as $column) {
            if (isset(
$column['autoIncrement']) && $column['autoIncrement']) {
                return
true;
            }
        }

        return
false;
    }

   
/**
     * Helper method to check/validate foreign keys.
     *
     * @param array $attrs Attributes to set.
     * @return array
     * @throws \Cake\Database\Exception When foreign key definition is not valid.
     */
   
protected function _checkForeignKey($attrs)
    {
        if (
count($attrs['references']) < 2) {
            throw new
Exception('References must contain a table and column.');
        }
        if (!
in_array($attrs['update'], static::$_validForeignKeyActions)) {
            throw new
Exception(sprintf('Update action is invalid. Must be one of %s', implode(',', static::$_validForeignKeyActions)));
        }
        if (!
in_array($attrs['delete'], static::$_validForeignKeyActions)) {
            throw new
Exception(sprintf('Delete action is invalid. Must be one of %s', implode(',', static::$_validForeignKeyActions)));
        }

        return
$attrs;
    }

   
/**
     * {@inheritDoc}
     */
   
public function constraints()
    {
        return
array_keys($this->_constraints);
    }

   
/**
     * Read information about a constraint based on name.
     *
     * @param string $name The name of the constraint.
     * @return array|null Array of constraint data, or null
     * @deprecated 3.5.0 Use getConstraint() instead.
     */
   
public function constraint($name)
    {
       
deprecationWarning('TableSchema::constraint() is deprecated. Use TableSchema::getConstraint() instead.');

        return
$this->getConstraint($name);
    }

   
/**
     * {@inheritDoc}
     */
   
public function getConstraint($name)
    {
        if (!isset(
$this->_constraints[$name])) {
            return
null;
        }

        return
$this->_constraints[$name];
    }

   
/**
     * {@inheritDoc}
     */
   
public function setOptions($options)
    {
       
$this->_options = array_merge($this->_options, $options);

        return
$this;
    }

   
/**
     * {@inheritDoc}
     */
   
public function getOptions()
    {
        return
$this->_options;
    }

   
/**
     * Get/set the options for a table.
     *
     * Table options allow you to set platform specific table level options.
     * For example the engine type in MySQL.
     *
     * @deprecated 3.4.0 Use setOptions()/getOptions() instead.
     * @param array|null $options The options to set, or null to read options.
     * @return $this|array Either the TableSchema instance, or an array of options when reading.
     */
   
public function options($options = null)
    {
       
deprecationWarning('TableSchema::options() is deprecated. Use TableSchema::setOptions() or TableSchema::getOptions() instead.');

        if (
$options !== null) {
            return
$this->setOptions($options);
        }

        return
$this->getOptions();
    }

   
/**
     * {@inheritDoc}
     */
   
public function setTemporary($temporary)
    {
       
$this->_temporary = (bool)$temporary;

        return
$this;
    }

   
/**
     * {@inheritDoc}
     */
   
public function isTemporary()
    {
        return
$this->_temporary;
    }

   
/**
     * Get/Set whether the table is temporary in the database
     *
     * @deprecated 3.4.0 Use setTemporary()/isTemporary() instead.
     * @param bool|null $temporary whether or not the table is to be temporary
     * @return $this|bool Either the TableSchema instance, the current temporary setting
     */
   
public function temporary($temporary = null)
    {
       
deprecationWarning(
           
'TableSchema::temporary() is deprecated. ' .
           
'Use TableSchema::setTemporary()/isTemporary() instead.'
       
);
        if (
$temporary !== null) {
            return
$this->setTemporary($temporary);
        }

        return
$this->isTemporary();
    }

   
/**
     * {@inheritDoc}
     */
   
public function createSql(Connection $connection)
    {
       
$dialect = $connection->getDriver()->schemaDialect();
       
$columns = $constraints = $indexes = [];
        foreach (
array_keys($this->_columns) as $name) {
           
$columns[] = $dialect->columnSql($this, $name);
        }
        foreach (
array_keys($this->_constraints) as $name) {
           
$constraints[] = $dialect->constraintSql($this, $name);
        }
        foreach (
array_keys($this->_indexes) as $name) {
           
$indexes[] = $dialect->indexSql($this, $name);
        }

        return
$dialect->createTableSql($this, $columns, $constraints, $indexes);
    }

   
/**
     * {@inheritDoc}
     */
   
public function dropSql(Connection $connection)
    {
       
$dialect = $connection->getDriver()->schemaDialect();

        return
$dialect->dropTableSql($this);
    }

   
/**
     * {@inheritDoc}
     */
   
public function truncateSql(Connection $connection)
    {
       
$dialect = $connection->getDriver()->schemaDialect();

        return
$dialect->truncateTableSql($this);
    }

   
/**
     * {@inheritDoc}
     */
   
public function addConstraintSql(Connection $connection)
    {
       
$dialect = $connection->getDriver()->schemaDialect();

        return
$dialect->addConstraintSql($this);
    }

   
/**
     * {@inheritDoc}
     */
   
public function dropConstraintSql(Connection $connection)
    {
       
$dialect = $connection->getDriver()->schemaDialect();

        return
$dialect->dropConstraintSql($this);
    }

   
/**
     * Returns an array of the table schema.
     *
     * @return array
     */
   
public function __debugInfo()
    {
        return [
           
'table' => $this->_table,
           
'columns' => $this->_columns,
           
'indexes' => $this->_indexes,
           
'constraints' => $this->_constraints,
           
'options' => $this->_options,
           
'typeMap' => $this->_typeMap,
           
'temporary' => $this->_temporary,
        ];
    }
}

// @deprecated 3.4.0 Add backwards compat alias.
class_alias('Cake\Database\Schema\TableSchema', 'Cake\Database\Schema\Table');