Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
089f32e6
Unverified
Commit
089f32e6
authored
Aug 18, 2018
by
Michael Moravec
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extract type factory and registry from Type into TypeRegistry
parent
773275d1
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
398 additions
and
73 deletions
+398
-73
DBALException.php
lib/Doctrine/DBAL/DBALException.php
+14
-0
Type.php
lib/Doctrine/DBAL/Types/Type.php
+78
-73
TypeRegistry.php
lib/Doctrine/DBAL/Types/TypeRegistry.php
+118
-0
TypeRegistryTest.php
tests/Doctrine/Tests/DBAL/Types/TypeRegistryTest.php
+154
-0
TypeTest.php
tests/Doctrine/Tests/DBAL/Types/TypeTest.php
+34
-0
No files found.
lib/Doctrine/DBAL/DBALException.php
View file @
089f32e6
...
...
@@ -6,6 +6,7 @@ use Doctrine\DBAL\Driver\DriverException as DriverExceptionInterface;
use
Doctrine\DBAL\Driver\ExceptionConverterDriver
;
use
Doctrine\DBAL\Exception\DriverException
;
use
Doctrine\DBAL\Platforms\AbstractPlatform
;
use
Doctrine\DBAL\Types\Type
;
use
Exception
;
use
Throwable
;
use
function
array_map
;
...
...
@@ -18,6 +19,7 @@ use function is_resource;
use
function
is_string
;
use
function
json_encode
;
use
function
preg_replace
;
use
function
spl_object_hash
;
use
function
sprintf
;
class
DBALException
extends
Exception
...
...
@@ -277,4 +279,16 @@ class DBALException extends Exception
{
return
new
self
(
'Type to be overwritten '
.
$name
.
' does not exist.'
);
}
public
static
function
typeNotRegistered
(
Type
$type
)
:
self
{
return
new
self
(
sprintf
(
'Type of the class %s@%s is not registered.'
,
get_class
(
$type
),
spl_object_hash
(
$type
)));
}
public
static
function
typeAlreadyRegistered
(
Type
$type
)
:
self
{
return
new
self
(
sprintf
(
'Type of the class %s@%s is already registered.'
,
get_class
(
$type
),
spl_object_hash
(
$type
))
);
}
}
lib/Doctrine/DBAL/Types/Type.php
View file @
089f32e6
...
...
@@ -5,6 +5,8 @@ namespace Doctrine\DBAL\Types;
use
Doctrine\DBAL\DBALException
;
use
Doctrine\DBAL\ParameterType
;
use
Doctrine\DBAL\Platforms\AbstractPlatform
;
use
function
array_map
;
use
function
get_class
;
use
function
str_replace
;
use
function
strrpos
;
use
function
substr
;
...
...
@@ -16,76 +18,70 @@ use function substr;
*/
abstract
class
Type
{
public
const
TARRAY
=
'array'
;
public
const
SIMPLE_ARRAY
=
'simple_array'
;
public
const
JSON_ARRAY
=
'json_array'
;
public
const
JSON
=
'json'
;
public
const
BIGINT
=
'bigint'
;
public
const
BINARY
=
'binary'
;
public
const
BLOB
=
'blob'
;
public
const
BOOLEAN
=
'boolean'
;
public
const
DATE
=
'date'
;
public
const
DATE_IMMUTABLE
=
'date_immutable'
;
public
const
DATEINTERVAL
=
'dateinterval'
;
public
const
DATETIME
=
'datetime'
;
public
const
DATETIME_IMMUTABLE
=
'datetime_immutable'
;
public
const
DATETIMETZ
=
'datetimetz'
;
public
const
DATETIMETZ_IMMUTABLE
=
'datetimetz_immutable'
;
public
const
DATE
=
'date'
;
public
const
DATE_IMMUTABLE
=
'date_immutable'
;
public
const
TIME
=
'time'
;
public
const
TIME_IMMUTABLE
=
'time_immutable'
;
public
const
DECIMAL
=
'decimal'
;
public
const
FLOAT
=
'float'
;
public
const
GUID
=
'guid'
;
public
const
INTEGER
=
'integer'
;
public
const
JSON
=
'json'
;
public
const
JSON_ARRAY
=
'json_array'
;
public
const
OBJECT
=
'object'
;
public
const
SIMPLE_ARRAY
=
'simple_array'
;
public
const
SMALLINT
=
'smallint'
;
public
const
STRING
=
'string'
;
public
const
TARRAY
=
'array'
;
public
const
TEXT
=
'text'
;
public
const
BINARY
=
'binary'
;
public
const
BLOB
=
'blob'
;
public
const
FLOAT
=
'float'
;
public
const
GUID
=
'guid'
;
public
const
DATEINTERVAL
=
'dateinterval'
;
/**
* Map of already instantiated type objects. One instance per type (flyweight).
*
* @var self[]
*/
private
static
$_typeObjects
=
[];
public
const
TIME
=
'time'
;
public
const
TIME_IMMUTABLE
=
'time_immutable'
;
/**
* The map of supported doctrine mapping types.
*
* @var string[]
*/
private
static
$_typesMap
=
[
self
::
TARRAY
=>
ArrayType
::
class
,
self
::
SIMPLE_ARRAY
=>
SimpleArrayType
::
class
,
self
::
JSON_ARRAY
=>
JsonArrayType
::
class
,
self
::
JSON
=>
JsonType
::
class
,
self
::
OBJECT
=>
ObjectType
::
class
,
self
::
BOOLEAN
=>
BooleanType
::
class
,
self
::
INTEGER
=>
IntegerType
::
class
,
self
::
SMALLINT
=>
SmallIntType
::
class
,
self
::
BIGINT
=>
BigIntType
::
class
,
self
::
STRING
=>
StringType
::
class
,
self
::
TEXT
=>
TextType
::
class
,
self
::
DATETIME
=>
DateTimeType
::
class
,
self
::
DATETIME_IMMUTABLE
=>
DateTimeImmutableType
::
class
,
self
::
DATETIMETZ
=>
DateTimeTzType
::
class
,
private
const
BUILTIN_TYPES_MAP
=
[
self
::
BIGINT
=>
BigIntType
::
class
,
self
::
BINARY
=>
BinaryType
::
class
,
self
::
BLOB
=>
BlobType
::
class
,
self
::
BOOLEAN
=>
BooleanType
::
class
,
self
::
DATE
=>
DateType
::
class
,
self
::
DATE_IMMUTABLE
=>
DateImmutableType
::
class
,
self
::
DATEINTERVAL
=>
DateIntervalType
::
class
,
self
::
DATETIME
=>
DateTimeType
::
class
,
self
::
DATETIME_IMMUTABLE
=>
DateTimeImmutableType
::
class
,
self
::
DATETIMETZ
=>
DateTimeTzType
::
class
,
self
::
DATETIMETZ_IMMUTABLE
=>
DateTimeTzImmutableType
::
class
,
self
::
DATE
=>
DateType
::
class
,
self
::
DATE_IMMUTABLE
=>
DateImmutableType
::
class
,
self
::
TIME
=>
TimeType
::
class
,
self
::
TIME_IMMUTABLE
=>
TimeImmutableType
::
class
,
self
::
DECIMAL
=>
DecimalType
::
class
,
self
::
FLOAT
=>
FloatType
::
class
,
self
::
BINARY
=>
BinaryType
::
class
,
self
::
BLOB
=>
BlobType
::
class
,
self
::
GUID
=>
GuidType
::
class
,
self
::
DATEINTERVAL
=>
DateIntervalType
::
class
,
self
::
DECIMAL
=>
DecimalType
::
class
,
self
::
FLOAT
=>
FloatType
::
class
,
self
::
GUID
=>
GuidType
::
class
,
self
::
INTEGER
=>
IntegerType
::
class
,
self
::
JSON
=>
JsonType
::
class
,
self
::
JSON_ARRAY
=>
JsonArrayType
::
class
,
self
::
OBJECT
=>
ObjectType
::
class
,
self
::
SIMPLE_ARRAY
=>
SimpleArrayType
::
class
,
self
::
SMALLINT
=>
SmallIntType
::
class
,
self
::
STRING
=>
StringType
::
class
,
self
::
TARRAY
=>
ArrayType
::
class
,
self
::
TEXT
=>
TextType
::
class
,
self
::
TIME
=>
TimeType
::
class
,
self
::
TIME_IMMUTABLE
=>
TimeImmutableType
::
class
,
];
/** @var TypeRegistry|null */
private
static
$typeRegistry
;
/**
*
Prevents instantiation and forces use of the factory metho
d.
*
@internal Do not instantiate directly - use {@see Type::addType()} method instea
d.
*/
final
p
rivate
function
__construct
()
final
p
ublic
function
__construct
()
{
}
...
...
@@ -148,6 +144,29 @@ abstract class Type
*/
abstract
public
function
getName
();
/**
* @internal This method is only to be used within DBAL for forward compatibility purposes. Do not use directly.
*/
final
public
static
function
getTypeRegistry
()
:
TypeRegistry
{
if
(
self
::
$typeRegistry
===
null
)
{
self
::
$typeRegistry
=
self
::
createTypeRegistry
();
}
return
self
::
$typeRegistry
;
}
private
static
function
createTypeRegistry
()
:
TypeRegistry
{
$registry
=
new
TypeRegistry
();
foreach
(
self
::
BUILTIN_TYPES_MAP
as
$name
=>
$class
)
{
$registry
->
register
(
$name
,
new
$class
());
}
return
$registry
;
}
/**
* Factory method to create type instances.
* Type instances are implemented as flyweights.
...
...
@@ -160,14 +179,7 @@ abstract class Type
*/
public
static
function
getType
(
$name
)
{
if
(
!
isset
(
self
::
$_typeObjects
[
$name
]))
{
if
(
!
isset
(
self
::
$_typesMap
[
$name
]))
{
throw
DBALException
::
unknownColumnType
(
$name
);
}
self
::
$_typeObjects
[
$name
]
=
new
self
::
$_typesMap
[
$name
]();
}
return
self
::
$_typeObjects
[
$name
];
return
self
::
getTypeRegistry
()
->
get
(
$name
);
}
/**
...
...
@@ -182,11 +194,7 @@ abstract class Type
*/
public
static
function
addType
(
$name
,
$className
)
{
if
(
isset
(
self
::
$_typesMap
[
$name
]))
{
throw
DBALException
::
typeExists
(
$name
);
}
self
::
$_typesMap
[
$name
]
=
$className
;
self
::
getTypeRegistry
()
->
register
(
$name
,
new
$className
());
}
/**
...
...
@@ -198,7 +206,7 @@ abstract class Type
*/
public
static
function
hasType
(
$name
)
{
return
isset
(
self
::
$_typesMap
[
$name
]
);
return
self
::
getTypeRegistry
()
->
has
(
$name
);
}
/**
...
...
@@ -213,15 +221,7 @@ abstract class Type
*/
public
static
function
overrideType
(
$name
,
$className
)
{
if
(
!
isset
(
self
::
$_typesMap
[
$name
]))
{
throw
DBALException
::
typeNotFound
(
$name
);
}
if
(
isset
(
self
::
$_typeObjects
[
$name
]))
{
unset
(
self
::
$_typeObjects
[
$name
]);
}
self
::
$_typesMap
[
$name
]
=
$className
;
self
::
getTypeRegistry
()
->
override
(
$name
,
new
$className
());
}
/**
...
...
@@ -245,7 +245,12 @@ abstract class Type
*/
public
static
function
getTypesMap
()
{
return
self
::
$_typesMap
;
return
array_map
(
static
function
(
Type
$type
)
:
string
{
return
get_class
(
$type
);
},
self
::
getTypeRegistry
()
->
getMap
()
);
}
/**
...
...
lib/Doctrine/DBAL/Types/TypeRegistry.php
0 → 100644
View file @
089f32e6
<?php
declare
(
strict_types
=
1
);
namespace
Doctrine\DBAL\Types
;
use
Doctrine\DBAL\DBALException
;
use
function
array_search
;
use
function
in_array
;
/**
* The type registry is responsible for holding a map of all known DBAL types.
* The types are stored using the flyweight pattern so that one type only exists as exactly one instance.
*
* @internal TypeRegistry exists for forward compatibility, its API should not be considered stable.
*/
final
class
TypeRegistry
{
/** @var array<string, Type> Map of type names and their corresponding flyweight objects. */
private
$instances
=
[];
/**
* Finds a type by the given name.
*
* @throws DBALException
*/
public
function
get
(
string
$name
)
:
Type
{
if
(
!
isset
(
$this
->
instances
[
$name
]))
{
throw
DBALException
::
unknownColumnType
(
$name
);
}
return
$this
->
instances
[
$name
];
}
/**
* Finds a name for the given type.
*
* @throws DBALException
*/
public
function
lookupName
(
Type
$type
)
:
string
{
$name
=
$this
->
findTypeName
(
$type
);
if
(
$name
===
null
)
{
throw
DBALException
::
typeNotRegistered
(
$type
);
}
return
$name
;
}
/**
* Checks if there is a type of the given name.
*/
public
function
has
(
string
$name
)
:
bool
{
return
isset
(
$this
->
instances
[
$name
]);
}
/**
* Registers a custom type to the type map.
*
* @throws DBALException
*/
public
function
register
(
string
$name
,
Type
$type
)
:
void
{
if
(
isset
(
$this
->
instances
[
$name
]))
{
throw
DBALException
::
typeExists
(
$name
);
}
if
(
$this
->
findTypeName
(
$type
)
!==
null
)
{
throw
DBALException
::
typeAlreadyRegistered
(
$type
);
}
$this
->
instances
[
$name
]
=
$type
;
}
/**
* Overrides an already defined type to use a different implementation.
*
* @throws DBALException
*/
public
function
override
(
string
$name
,
Type
$type
)
:
void
{
if
(
!
isset
(
$this
->
instances
[
$name
]))
{
throw
DBALException
::
typeNotFound
(
$name
);
}
if
(
!
in_array
(
$this
->
findTypeName
(
$type
),
[
$name
,
null
],
true
))
{
throw
DBALException
::
typeAlreadyRegistered
(
$type
);
}
$this
->
instances
[
$name
]
=
$type
;
}
/**
* Gets the map of all registered types and their corresponding type instances.
*
* @internal
*
* @return array<string, Type>
*/
public
function
getMap
()
:
array
{
return
$this
->
instances
;
}
private
function
findTypeName
(
Type
$type
)
:
?
string
{
$name
=
array_search
(
$type
,
$this
->
instances
,
true
);
if
(
$name
===
false
)
{
return
null
;
}
return
$name
;
}
}
tests/Doctrine/Tests/DBAL/Types/TypeRegistryTest.php
0 → 100644
View file @
089f32e6
<?php
declare
(
strict_types
=
1
);
namespace
Doctrine\Tests\DBAL\Types
;
use
Doctrine\DBAL\DBALException
;
use
Doctrine\DBAL\Types\BinaryType
;
use
Doctrine\DBAL\Types\BlobType
;
use
Doctrine\DBAL\Types\StringType
;
use
Doctrine\DBAL\Types\TextType
;
use
Doctrine\DBAL\Types\TypeRegistry
;
use
PHPUnit\Framework\TestCase
;
class
TypeRegistryTest
extends
TestCase
{
private
const
TEST_TYPE_NAME
=
'test'
;
private
const
OTHER_TEST_TYPE_NAME
=
'other'
;
/** @var TypeRegistry */
private
$registry
;
/** @var BlobType */
private
$testType
;
/** @var BinaryType */
private
$otherTestType
;
protected
function
setUp
()
:
void
{
$this
->
testType
=
new
BlobType
();
$this
->
otherTestType
=
new
BinaryType
();
$this
->
registry
=
new
TypeRegistry
();
$this
->
registry
->
register
(
self
::
TEST_TYPE_NAME
,
$this
->
testType
);
$this
->
registry
->
register
(
self
::
OTHER_TEST_TYPE_NAME
,
$this
->
otherTestType
);
}
public
function
testGet
()
:
void
{
self
::
assertSame
(
$this
->
testType
,
$this
->
registry
->
get
(
self
::
TEST_TYPE_NAME
));
self
::
assertSame
(
$this
->
otherTestType
,
$this
->
registry
->
get
(
self
::
OTHER_TEST_TYPE_NAME
));
$this
->
expectException
(
DBALException
::
class
);
$this
->
registry
->
get
(
'unknown'
);
}
public
function
testGetReturnsSameInstances
()
:
void
{
self
::
assertSame
(
$this
->
registry
->
get
(
self
::
TEST_TYPE_NAME
),
$this
->
registry
->
get
(
self
::
TEST_TYPE_NAME
)
);
}
public
function
testLookupName
()
:
void
{
self
::
assertSame
(
self
::
TEST_TYPE_NAME
,
$this
->
registry
->
lookupName
(
$this
->
testType
)
);
self
::
assertSame
(
self
::
OTHER_TEST_TYPE_NAME
,
$this
->
registry
->
lookupName
(
$this
->
otherTestType
)
);
$this
->
expectException
(
DBALException
::
class
);
$this
->
registry
->
lookupName
(
new
TextType
());
}
public
function
testHas
()
:
void
{
self
::
assertTrue
(
$this
->
registry
->
has
(
self
::
TEST_TYPE_NAME
));
self
::
assertTrue
(
$this
->
registry
->
has
(
self
::
OTHER_TEST_TYPE_NAME
));
self
::
assertFalse
(
$this
->
registry
->
has
(
'unknown'
));
}
public
function
testRegister
()
:
void
{
$newType
=
new
TextType
();
$this
->
registry
->
register
(
'some'
,
$newType
);
self
::
assertTrue
(
$this
->
registry
->
has
(
'some'
));
self
::
assertSame
(
$newType
,
$this
->
registry
->
get
(
'some'
));
}
public
function
testRegisterWithAlradyRegisteredName
()
:
void
{
$this
->
registry
->
register
(
'some'
,
new
TextType
());
$this
->
expectException
(
DBALException
::
class
);
$this
->
registry
->
register
(
'some'
,
new
TextType
());
}
public
function
testRegisterWithAlreadyRegisteredInstance
()
:
void
{
$newType
=
new
TextType
();
$this
->
registry
->
register
(
'some'
,
$newType
);
$this
->
expectException
(
DBALException
::
class
);
$this
->
registry
->
register
(
'other'
,
$newType
);
}
public
function
testOverride
()
:
void
{
$baseType
=
new
TextType
();
$overrideType
=
new
StringType
();
$this
->
registry
->
register
(
'some'
,
$baseType
);
$this
->
registry
->
override
(
'some'
,
$overrideType
);
self
::
assertSame
(
$overrideType
,
$this
->
registry
->
get
(
'some'
));
}
public
function
testOverrideAllowsExistingInstance
()
:
void
{
$type
=
new
TextType
();
$this
->
registry
->
register
(
'some'
,
$type
);
$this
->
registry
->
override
(
'some'
,
$type
);
self
::
assertSame
(
$type
,
$this
->
registry
->
get
(
'some'
));
}
public
function
testOverrideWithAlreadyRegisteredInstance
()
:
void
{
$newType
=
new
TextType
();
$this
->
registry
->
register
(
'first'
,
$newType
);
$this
->
registry
->
register
(
'second'
,
new
StringType
());
$this
->
expectException
(
DBALException
::
class
);
$this
->
registry
->
override
(
'second'
,
$newType
);
}
public
function
testOverrideWithUnknownType
()
:
void
{
$this
->
expectException
(
DBALException
::
class
);
$this
->
registry
->
override
(
'unknown'
,
new
TextType
());
}
public
function
testGetMap
()
:
void
{
$registeredTypes
=
$this
->
registry
->
getMap
();
self
::
assertCount
(
2
,
$registeredTypes
);
self
::
assertArrayHasKey
(
self
::
TEST_TYPE_NAME
,
$registeredTypes
);
self
::
assertArrayHasKey
(
self
::
OTHER_TEST_TYPE_NAME
,
$registeredTypes
);
self
::
assertSame
(
$this
->
testType
,
$registeredTypes
[
self
::
TEST_TYPE_NAME
]);
self
::
assertSame
(
$this
->
otherTestType
,
$registeredTypes
[
self
::
OTHER_TEST_TYPE_NAME
]);
}
}
tests/Doctrine/Tests/DBAL/Types/TypeTest.php
0 → 100644
View file @
089f32e6
<?php
declare
(
strict_types
=
1
);
namespace
Doctrine\Tests\DBAL\Types
;
use
Doctrine\DBAL\Types\Type
;
use
PHPUnit\Framework\TestCase
;
use
ReflectionClass
;
class
TypeTest
extends
TestCase
{
/**
* @dataProvider defaultTypesProvider()
*/
public
function
testDefaultTypesAreRegistered
(
string
$name
)
:
void
{
self
::
assertTrue
(
Type
::
hasType
(
$name
));
}
/**
* @return string[][]
*/
public
function
defaultTypesProvider
()
:
iterable
{
foreach
((
new
ReflectionClass
(
Type
::
class
))
->
getReflectionConstants
()
as
$constant
)
{
if
(
!
$constant
->
isPublic
())
{
continue
;
}
yield
[
$constant
->
getValue
()];
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment