Commit 28c7e09d authored by Benjamin Eberlei's avatar Benjamin Eberlei

[DBAL-42] Added support for marking doctrine types as to be commented, added support for MySQL

parent 4c4c778d
......@@ -25,7 +25,8 @@ use Doctrine\DBAL\DBALException,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Index,
Doctrine\DBAL\Schema\ForeignKeyConstraint,
Doctrine\DBAL\Schema\TableDiff;
Doctrine\DBAL\Schema\TableDiff,
Doctrine\DBAL\Types\Type;
/**
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central
......@@ -80,6 +81,14 @@ abstract class AbstractPlatform
*/
protected $doctrineTypeMapping = null;
/**
* Contains a list of all columns that should generate parseable column comments for type-detection
* in reverse engineering scenarios.
*
* @var array
*/
protected $doctrineTypeComments = null;
/**
* Constructor.
*/
......@@ -209,6 +218,56 @@ abstract class AbstractPlatform
return isset($this->doctrineTypeMapping[$dbType]);
}
/**
* Initialize the Doctrine Type comments instance variable for in_array() checks.
*
* @return void
*/
protected function initializeCommentedDoctrineTypes()
{
$this->doctrineTypeComments = array(Type::TARRAY, Type::OBJECT);
}
/**
* Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type?
*
* @param Type $doctrineType
* @return bool
*/
public function isCommentedDoctrineType(Type $doctrineType)
{
if ($this->doctrineTypeComments === null) {
$this->initializeCommentedDoctrineTypes();
}
return in_array($doctrineType->getName(), $this->doctrineTypeComments);
}
/**
* Mark this type as to be commented in ALTER TABLE and CREATE TABLE statements.
*
* @param Type $doctrineType
* @return void
*/
public function markDoctrineTypeCommented(Type $doctrineType)
{
if ($this->doctrineTypeComments === null) {
$this->initializeCommentedDoctrineTypes();
}
$this->doctrineTypeComments[] = $doctrineType->getName();
}
/**
* Get the comment to append to a column comment that helps parsing this type in reverse engineering.
*
* @param Type $doctrineType
* @return string
*/
public function getDoctrineTypeComment(Type $doctrineType)
{
return '(DC2Type:' . $doctrineType->getName() . ')';
}
/**
* Gets the character used for identifier quoting.
*
......@@ -798,6 +857,9 @@ abstract class AbstractPlatform
$columnData['columnDefinition'] = $column->getColumnDefinition();
$columnData['autoincrement'] = $column->getAutoincrement();
$columnData['comment'] = $column->getComment();
if ($this->isCommentedDoctrineType($column->getType())) {
$columnData['comment'] .= $this->getDoctrineTypeComment($column->getType());
}
if(in_array($column->getName(), $options['primary'])) {
$columnData['primary'] = true;
......
......@@ -779,4 +779,25 @@ abstract class AbstractSchemaManager
return $schemaConfig;
}
/**
* Given a table comment this method tries to extract a typehint for Doctrine Type, or returns
* the type given as default.
*
* @param string $comment
* @param string $currentType
* @return string
*/
public function extractDoctrineTypeFromComment($comment, $currentType)
{
if (preg_match("(\(DC2Type:([a-zA-Z0-9]+)\))", $comment, $match)) {
$currentType = $match[1];
}
return $currentType;
}
public function removeDoctrineTypeFromComment($comment, $type)
{
return str_replace('(DC2Type:'.$type.')', '', $comment);
}
}
\ No newline at end of file
......@@ -107,6 +107,9 @@ class MySqlSchemaManager extends AbstractSchemaManager
$precision = null;
$type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
switch ($dbType) {
case 'char':
$fixed = true;
......
......@@ -408,17 +408,43 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->markTestSkipped('Database does not support column comments.');
}
$table = new \Doctrine\DBAL\Schema\Table('test');
$table = new \Doctrine\DBAL\Schema\Table('column_comment_test');
$table->addColumn('id', 'integer', array('comment' => 'This is a comment'));
$table->setPrimaryKey(array('id'));
$this->_sm->createTable($table);
$columns = $this->_sm->listTableColumns("test");
$columns = $this->_sm->listTableColumns("column_comment_test");
$this->assertEquals(1, count($columns));
$this->assertEquals('This is a comment', $columns['id']->getComment());
}
/**
* @group DBAL-42
*/
public function testAutomaticallyAppendCommentOnMarkedColumns()
{
if (!$this->_conn->getDatabasePlatform()->supportsInlineColumnComments() && !$this->_conn->getDatabasePlatform()->supportsCommentOnStatement()) {
$this->markTestSkipped('Database does not support column comments.');
}
$table = new \Doctrine\DBAL\Schema\Table('column_comment_test2');
$table->addColumn('id', 'integer', array('comment' => 'This is a comment'));
$table->addColumn('obj', 'object', array('comment' => 'This is a comment'));
$table->addColumn('arr', 'array', array('comment' => 'This is a comment'));
$table->setPrimaryKey(array('id'));
$this->_sm->createTable($table);
$columns = $this->_sm->listTableColumns("column_comment_test2");
$this->assertEquals(3, count($columns));
$this->assertEquals('This is a comment', $columns['id']->getComment());
$this->assertEquals('This is a comment', $columns['obj']->getComment(), "The Doctrine2 Typehint should be stripped from comment.");
$this->assertInstanceOf('Doctrine\DBAL\Types\ObjectType', $columns['obj']->getType(), "The Doctrine2 should be detected from comment hint.");
$this->assertEquals('This is a comment', $columns['arr']->getComment(), "The Doctrine2 Typehint should be stripped from comment.");
$this->assertInstanceOf('Doctrine\DBAL\Types\ArrayType', $columns['arr']->getType(), "The Doctrine2 should be detected from comment hint.");
}
/**
* @param string $name
* @param array $data
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment