Skip to content

Commit

Permalink
Merge pull request #3501 from morozov/extract-type-from-comment
Browse files Browse the repository at this point in the history
Reworked AbstractSchemaManager::extractDoctrineTypeFromComment(), removed ::removeDoctrineTypeFromComment()
  • Loading branch information
morozov committed May 23, 2019
2 parents af11239 + 6029aeb commit 3ed2f25
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 75 deletions.
4 changes: 4 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Upgrade to 3.0

## BC BREAK `AbstractSchemaManager::extractDoctrineTypeFromComment()` changed, `::removeDoctrineTypeFromComment()` removed

`AbstractSchemaManager::extractDoctrineTypeFromComment()` made `protected`. It takes the comment by reference, removes the type annotation from it and returns the extracted Doctrine type.

## BC BREAK `::errorCode()` and `::errorInfo()` removed from `Connection` and `Statement` APIs

The error information is available in `DriverException` trown in case of an error.
Expand Down
33 changes: 8 additions & 25 deletions lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use function is_array;
use function is_callable;
use function preg_match;
use function str_replace;
use function strtolower;

/**
Expand Down Expand Up @@ -1099,35 +1098,19 @@ public function getSchemaSearchPaths()
}

/**
* Given a table comment this method tries to extract a typehint for Doctrine Type, or returns
* the type given as default.
* Given a table comment this method tries to extract a type hint for Doctrine Type. If the type hint is found,
* it's removed from the comment.
*
* @param string|null $comment
* @param string $currentType
*
* @return string
*/
public function extractDoctrineTypeFromComment($comment, $currentType)
{
if ($comment !== null && preg_match('(\(DC2Type:(((?!\)).)+)\))', $comment, $match)) {
return $match[1];
}

return $currentType;
}

/**
* @param string|null $comment
* @param string|null $type
*
* @return string|null
* @return string|null The extracted Doctrine type or NULL of the type hint was not found.
*/
public function removeDoctrineTypeFromComment($comment, $type)
final protected function extractDoctrineTypeFromComment(?string &$comment) : ?string
{
if ($comment === null) {
if ($comment === null || ! preg_match('/(.*)\(DC2Type:(((?!\)).)+)\)(.*)/', $comment, $match)) {
return null;
}

return str_replace('(DC2Type:' . $type . ')', '', $comment);
$comment = $match[1] . $match[4];

return $match[2];
}
}
8 changes: 2 additions & 6 deletions lib/Doctrine/DBAL/Schema/DB2SchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,8 @@ protected function _getPortableTableColumnDefinition($tableColumn)
}
}

$type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']);

if (isset($tableColumn['comment'])) {
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
}
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'])
?? $this->_platform->getDoctrineTypeMapping($tableColumn['typename']);

switch (strtolower($tableColumn['typename'])) {
case 'varchar':
Expand Down
9 changes: 2 additions & 7 deletions lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,8 @@ protected function _getPortableTableColumnDefinition($tableColumn)
$scale = null;
$precision = null;

$type = $this->_platform->getDoctrineTypeMapping($dbType);

// In cases where not connected to a database DESCRIBE $table does not return 'Comment'
if (isset($tableColumn['comment'])) {
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
}
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'])
?? $this->_platform->getDoctrineTypeMapping($dbType);

switch ($dbType) {
case 'char':
Expand Down
5 changes: 2 additions & 3 deletions lib/Doctrine/DBAL/Schema/OracleSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,8 @@ protected function _getPortableTableColumnDefinition($tableColumn)
$scale = (int) $tableColumn['data_scale'];
}

$type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comments'], $type);
$tableColumn['comments'] = $this->removeDoctrineTypeFromComment($tableColumn['comments'], $type);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comments'])
?? $this->_platform->getDoctrineTypeMapping($dbType);

switch ($dbType) {
case 'number':
Expand Down
5 changes: 2 additions & 3 deletions lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,8 @@ protected function _getPortableTableColumnDefinition($tableColumn)
$tableColumn['complete_type'] = $tableColumn['domain_complete_type'];
}

$type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'])
?? $this->_platform->getDoctrineTypeMapping($dbType);

switch ($dbType) {
case 'smallint':
Expand Down
14 changes: 7 additions & 7 deletions lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ protected function _getPortableSequenceDefinition($sequence)
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$type = $this->_platform->getDoctrineTypeMapping($tableColumn['type']);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
$precision = null;
$scale = null;
$fixed = false;
$default = null;
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'])
?? $this->_platform->getDoctrineTypeMapping($tableColumn['type']);

$precision = null;
$scale = null;
$fixed = false;
$default = null;

if ($tableColumn['default'] !== null) {
// Strip quotes from default value.
Expand Down
5 changes: 2 additions & 3 deletions lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,8 @@ protected function _getPortableTableColumnDefinition($tableColumn)
$fixed = true;
}

$type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'])
?? $this->_platform->getDoctrineTypeMapping($dbType);

$options = [
'length' => $length === 0 || ! in_array($type, ['text', 'string']) ? null : $length,
Expand Down
10 changes: 2 additions & 8 deletions lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,16 +281,10 @@ protected function _getPortableTableColumnList($table, $database, $tableColumns)

$comment = $this->parseColumnCommentFromSQL($columnName, $createSql);

if ($comment === null) {
continue;
}
$type = $this->extractDoctrineTypeFromComment($comment);

$type = $this->extractDoctrineTypeFromComment($comment, '');

if ($type !== '') {
if ($type !== null) {
$column->setType(Type::getType($type));

$comment = $this->removeDoctrineTypeFromComment($comment, $type);
}

$column->setComment($comment);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use Doctrine\DBAL\Types\TextType;
use Doctrine\DBAL\Types\Type;
use Doctrine\Tests\DbalFunctionalTestCase;
use ReflectionMethod;
use function array_filter;
use function array_keys;
use function array_map;
Expand Down Expand Up @@ -1440,27 +1441,26 @@ public function testComparatorShouldNotAddCommentToJsonTypeSinceItIsTheDefaultNo
* @dataProvider commentsProvider
* @group 2596
*/
public function testExtractDoctrineTypeFromComment(string $comment, string $expected, string $currentType) : void
public function testExtractDoctrineTypeFromComment(?string $comment, ?string $expectedType) : void
{
$result = $this->schemaManager->extractDoctrineTypeFromComment($comment, $currentType);
$re = new ReflectionMethod($this->schemaManager, 'extractDoctrineTypeFromComment');
$re->setAccessible(true);

self::assertSame($expected, $result);
self::assertSame($expectedType, $re->invokeArgs($this->schemaManager, [&$comment]));
}

/**
* @return string[][]
* @return mixed[][]
*/
public function commentsProvider() : array
public static function commentsProvider() : iterable
{
$currentType = 'current type';

return [
'invalid custom type comments' => ['should.return.current.type', $currentType, $currentType],
'valid doctrine type' => ['(DC2Type:guid)', 'guid', $currentType],
'valid with dots' => ['(DC2Type:type.should.return)', 'type.should.return', $currentType],
'valid with namespace' => ['(DC2Type:Namespace\Class)', 'Namespace\Class', $currentType],
'valid with extra closing bracket' => ['(DC2Type:should.stop)).before)', 'should.stop', $currentType],
'valid with extra opening brackets' => ['(DC2Type:should((.stop)).before)', 'should((.stop', $currentType],
'invalid custom type comments' => ['should.return.null', null],
'valid doctrine type' => ['(DC2Type:guid)', 'guid'],
'valid with dots' => ['(DC2Type:type.should.return)', 'type.should.return'],
'valid with namespace' => ['(DC2Type:Namespace\Class)', 'Namespace\Class'],
'valid with extra closing bracket' => ['(DC2Type:should.stop)).before)', 'should.stop'],
'valid with extra opening brackets' => ['(DC2Type:should((.stop)).before)', 'should((.stop'],
];
}

Expand Down

0 comments on commit 3ed2f25

Please sign in to comment.