src/Dbal/Column.php
<?php
namespace ORM\Dbal;
use ORM\Dbal\Error\NotValid;
/**
* Describes a column of a database table
*
* @package ORM\Dbal
* @author Thomas Flori <thflori@gmail.com>
*
* @property string name
* @property Type type
* @property mixed default
* @property bool nullable
*/
class Column
{
/** @var string[] */
protected static $registeredTypes = [];
/**
* Register $type for describe
*
* @param string $type The full qualified class name
*/
public static function registerType($type)
{
if (!in_array($type, static::$registeredTypes)) {
array_unshift(static::$registeredTypes, $type);
}
}
/**
* Get the registered type for $columnDefinition
*
* @param array $columnDefinition
* @return string
*/
protected static function getRegisteredType(array $columnDefinition)
{
foreach (self::$registeredTypes as $class) {
if (call_user_func([ $class, 'fits' ], $columnDefinition)) {
return $class;
}
}
return null;
}
/** @var array */
protected $columnDefinition;
/** @var Dbal */
protected $dbal;
/** @var TypeInterface */
protected $type;
/** @var bool */
protected $hasDefault;
/** @var bool */
protected $isNullable;
/**
* Column constructor.
*
* @param Dbal $dbal
* @param array $columnDefinition
*/
public function __construct(Dbal $dbal, array $columnDefinition)
{
$this->dbal = $dbal;
$this->columnDefinition = $columnDefinition;
}
/**
* Check if $value is valid for this type
*
* @param mixed $value
* @return boolean|Error
*/
public function validate($value)
{
if ($value === null) {
if ($this->nullable || $this->hasDefault()) {
return true;
}
return new Error\NotNullable($this);
}
$valid = $this->getType()->validate($value);
if ($valid === false) {
return new NotValid($this, new Error());
}
if ($valid instanceof Error) {
return new NotValid($this, $valid);
}
return true;
}
/**
* Get attributes from column
*
* @param string $name
* @return mixed
*/
public function __get($name)
{
$method = [$this, 'get' . ucfirst($name)];
return is_callable($method) ? call_user_func($method) :
(isset($this->columnDefinition[$name]) ? $this->columnDefinition[$name] : null);
}
/**
* Get the name of the column
*
* @return string
*/
public function getName()
{
return $this->columnDefinition['column_name'];
}
/**
* Get the default value of the column
*
* @return mixed
*/
public function getDefault()
{
return $this->columnDefinition['column_default'];
}
/**
* Check if the column is nullable
*
* @return bool
*/
public function isNullable()
{
return $this->columnDefinition['is_nullable'] === true ||
$this->columnDefinition['is_nullable'] === 'YES';
}
/**
* Get the nullable status of the column
*
* @return bool
*/
public function getNullable()
{
return $this->isNullable();
}
/**
* Check if default value is given
*
* @return bool
*/
public function hasDefault()
{
return $this->default !== null;
}
/**
* Determine and return the type
*
* @return Type
*/
public function getType()
{
if (!$this->type) {
if (!isset($this->columnDefinition['type'])) {
$class = self::getRegisteredType($this->columnDefinition);
} else {
$class = $this->columnDefinition['type'];
}
if ($class === null || !is_callable([ $class, 'factory' ])) {
$class = Type\Text::class;
}
$this->type = call_user_func([ $class, 'factory' ], $this->dbal, $this->columnDefinition);
}
return $this->type;
}
}