Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CWD
CwdDataDoctrineORMBundle
Commits
4a5bb42e
Commit
4a5bb42e
authored
Sep 08, 2018
by
Bernhard Schussek
Browse files
Initial commit
parents
Changes
55
Hide whitespace changes
Inline
Side-by-side
Auditing/ORMChangeTimeRecorder.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\Auditing
;
use
Cwd\DataBundle\Auditing\RecordsChangeTime
;
use
Cwd\DataBundle\Auditing\RecordsCreationTime
;
use
DateTimeImmutable
;
use
DateTimeZone
;
use
Doctrine\ORM\Event\LifecycleEventArgs
;
class
ORMChangeTimeRecorder
{
public
function
prePersist
(
LifecycleEventArgs
$args
)
{
$entity
=
$args
->
getEntity
();
$now
=
self
::
nowWithMilliseconds
();
if
(
$entity
instanceof
RecordsCreationTime
)
{
$entity
->
setCreatedAt
(
$now
,
$override
=
false
);
}
if
(
$entity
instanceof
RecordsChangeTime
)
{
$entity
->
setUpdatedAt
(
$now
,
$override
=
false
);
}
}
public
function
preUpdate
(
LifecycleEventArgs
$args
)
{
$entity
=
$args
->
getEntity
();
if
(
$entity
instanceof
RecordsChangeTime
)
{
$entity
->
setUpdatedAt
(
self
::
nowWithMilliseconds
(),
$override
=
false
);
}
}
private
static
function
nowWithMilliseconds
():
DateTimeImmutable
{
$time
=
sprintf
(
'%.6f'
,
microtime
(
true
));
return
DateTimeImmutable
::
createFromFormat
(
'U.u'
,
$time
)
->
setTimezone
(
new
DateTimeZone
(
date_default_timezone_get
()));
}
}
CwdDataDoctrineORMBundle.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle
;
use
Cwd\DataBundle\DependencyInjection\Compiler\AutoDiscoverRepositoryImplementationsPass
;
use
Cwd\DataBundle\DependencyInjection\Compiler\GenerateRepositoryClassesPass
;
use
Cwd\DataDoctrineORMBundle\DependencyInjection\Compiler\RegisterFunctionsPass
;
use
Cwd\DataDoctrineORMBundle\DependencyInjection\Compiler\RegisterTypesPass
;
use
Cwd\DataDoctrineORMBundle\DependencyInjection\CwdDataDoctrineORMExtension
;
use
Cwd\DataDoctrineORMBundle\DependencyInjection\ORMRepositoryServiceDefinitionFactory
;
use
Cwd\DataDoctrineORMBundle\Generator\ORMRepositoryClassGenerator
;
use
Symfony\Component\DependencyInjection\ContainerBuilder
;
use
Symfony\Component\HttpKernel\Bundle\Bundle
;
class
CwdDataDoctrineORMBundle
extends
Bundle
{
public
function
getContainerExtension
()
{
return
new
CwdDataDoctrineORMExtension
(
'cwd_data_doctrine_orm'
);
}
public
function
build
(
ContainerBuilder
$container
)
{
$container
->
addCompilerPass
(
new
GenerateRepositoryClassesPass
(
ORMRepositoryClassGenerator
::
class
));
$container
->
addCompilerPass
(
new
AutoDiscoverRepositoryImplementationsPass
(
'cwd_data_doctrine_orm.implementation_dirs'
,
ORMRepositoryServiceDefinitionFactory
::
class
));
$container
->
addCompilerPass
(
new
RegisterTypesPass
());
$container
->
addCompilerPass
(
new
RegisterFunctionsPass
());
}
}
DependencyInjection/Compiler/RegisterFunctionsPass.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\DependencyInjection\Compiler
;
use
Cwd\DataBundle\Util\StringUtil
;
use
Doctrine\Common\Util\Inflector
;
use
Doctrine\DBAL\Types\Type
;
use
Symfony\Component\Config\Resource\FileResource
;
use
Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface
;
use
Symfony\Component\DependencyInjection\ContainerBuilder
;
use
Symfony\Component\Finder\Finder
;
use
Symfony\Component\Finder\SplFileInfo
;
use
Webmozart\Assert\Assert
;
final
class
RegisterFunctionsPass
implements
CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public
function
process
(
ContainerBuilder
$containerBuilder
):
void
{
if
(
!
$containerBuilder
->
hasParameter
(
'cwd_data_doctrine_orm.string_function_dirs'
)
||
!
$containerBuilder
->
hasParameter
(
'cwd_data_doctrine_orm.numeric_function_dirs'
))
{
return
;
}
$entityManager
=
$containerBuilder
->
getParameter
(
'cwd_data_doctrine_orm.entity_manager'
);
$ormConfigDef
=
$containerBuilder
->
getDefinition
(
sprintf
(
'doctrine.orm.%s_configuration'
,
$entityManager
));
$stringFunctionDirs
=
$containerBuilder
->
getParameter
(
'cwd_data_doctrine_orm.string_function_dirs'
);
$numericFunctionDirs
=
$containerBuilder
->
getParameter
(
'cwd_data_doctrine_orm.numeric_function_dirs'
);
$stringFunctionFiles
=
Finder
::
create
()
->
files
()
->
in
(
array_merge
([
__DIR__
.
'/../../Func/Postgresql/String'
,
],
$stringFunctionDirs
));
$numericFunctionFiles
=
Finder
::
create
()
->
files
()
->
in
(
array_merge
([
__DIR__
.
'/../../Func/Postgresql/Numeric'
,
],
$numericFunctionDirs
));
$processFunction
=
function
(
string
$addFunctionMethod
)
use
(
$ormConfigDef
,
$containerBuilder
)
{
return
function
(
SplFileInfo
$file
)
use
(
$addFunctionMethod
,
$ormConfigDef
,
$containerBuilder
)
{
/** @var SplFileInfo $file */
$className
=
$this
->
getFunctionClassName
(
$file
);
if
(
null
===
$className
)
{
return
;
}
$containerBuilder
->
addResource
(
new
FileResource
(
$file
->
getPathname
()));
$name
=
Inflector
::
tableize
(
StringUtil
::
getShortClassName
(
$className
));
$ormConfigDef
->
addMethodCall
(
$addFunctionMethod
,
[
$name
,
$className
]);
};
};
foreach
(
$stringFunctionFiles
as
$file
)
{
$processFunction
(
'addCustomStringFunction'
)(
$file
);
}
foreach
(
$numericFunctionFiles
as
$file
)
{
$processFunction
(
'addCustomNumericFunction'
)(
$file
);
}
}
/**
* Retrieves the type class name without loading the file.
*/
private
function
getFunctionClassName
(
SplFileInfo
$file
):
?string
{
$fileContents
=
$file
->
getContents
();
Assert
::
same
(
preg_match
(
'/^namespace (?<namespace>[\p{L}\\\\u\_]+);\s*$/mu'
,
$fileContents
,
$matches
),
1
);
$namespace
=
$matches
[
'namespace'
];
if
(
1
!==
preg_match
(
'/^(?:final )?class (?<class>[\p{L}\\\\_]+) ?.*$/mu'
,
$fileContents
,
$matches
))
{
// May be an interface or an abstract class
return
null
;
}
$shortClassName
=
$matches
[
'class'
];
return
$namespace
.
'\\'
.
$shortClassName
;
}
}
DependencyInjection/Compiler/RegisterTypesPass.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\DependencyInjection\Compiler
;
use
Doctrine\DBAL\Types\Type
;
use
ReflectionClass
;
use
Symfony\Component\Config\Resource\FileResource
;
use
Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface
;
use
Symfony\Component\DependencyInjection\ContainerBuilder
;
use
Symfony\Component\Finder\Finder
;
use
Symfony\Component\Finder\SplFileInfo
;
use
Webmozart\Assert\Assert
;
final
class
RegisterTypesPass
implements
CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public
function
process
(
ContainerBuilder
$containerBuilder
):
void
{
if
(
!
$containerBuilder
->
hasParameter
(
'cwd_data_doctrine_orm.type_dirs'
))
{
return
;
}
$typeDirs
=
$containerBuilder
->
getParameter
(
'cwd_data_doctrine_orm.type_dirs'
);
$files
=
Finder
::
create
()
->
files
()
->
in
(
array_merge
([
__DIR__
.
'/../../Type'
,
],
$typeDirs
));
$typeClasses
=
[];
foreach
(
$files
as
$file
)
{
/** @var SplFileInfo $file */
$className
=
$this
->
getTypeClassName
(
$file
);
if
(
null
===
$className
)
{
continue
;
}
$containerBuilder
->
addResource
(
new
FileResource
(
$file
->
getPathname
()));
$typeClasses
[]
=
$className
;
}
$doctrineTypes
=
$this
->
createDoctrineTypes
(
...
$typeClasses
);
$containerBuilder
->
setParameter
(
'doctrine.dbal.connection_factory.types'
,
// Merge the result: if a type is registered manually then it takes precedence over the auto-discovered type
array_merge
(
$doctrineTypes
,
$containerBuilder
->
getParameter
(
'doctrine.dbal.connection_factory.types'
)
)
);
}
private
function
createDoctrineTypes
(
?string
...
$typeClasses
):
array
{
$doctrineTypes
=
[];
$typeClasses
=
array_unique
(
array_filter
(
$typeClasses
));
foreach
(
$typeClasses
as
$typeClass
)
{
/** @var Type $type */
$type
=
(
new
ReflectionClass
(
$typeClass
))
->
newInstanceWithoutConstructor
();
Assert
::
isInstanceOf
(
$type
,
Type
::
class
);
$doctrineTypes
[
$type
->
getName
()]
=
[
'class'
=>
$typeClass
,
'commented'
=>
true
,
];
}
Assert
::
same
(
count
(
$typeClasses
),
count
(
$doctrineTypes
),
'Expected to have as many doctrine types registered as doctrine type classes. Check that two types'
.
' do not have the same name.'
);
return
$doctrineTypes
;
}
/**
* Retrieves the type class name without loading the file.
*/
private
function
getTypeClassName
(
SplFileInfo
$file
):
?string
{
$fileContents
=
$file
->
getContents
();
Assert
::
same
(
preg_match
(
'/^namespace (?<namespace>[\p{L}\\\\u\_]+);\s*$/mu'
,
$fileContents
,
$matches
),
1
);
$namespace
=
$matches
[
'namespace'
];
if
(
1
!==
preg_match
(
'/^(?:final )?class (?<class>[\p{L}\\\\_]+) ?.*$/mu'
,
$fileContents
,
$matches
))
{
// May be an interface or an abstract class
return
null
;
}
$shortClassName
=
$matches
[
'class'
];
return
$namespace
.
'\\'
.
$shortClassName
;
}
}
DependencyInjection/Configuration.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\DependencyInjection
;
use
Symfony\Component\Config\Definition\Builder\TreeBuilder
;
use
Symfony\Component\Config\Definition\ConfigurationInterface
;
class
Configuration
implements
ConfigurationInterface
{
private
$alias
;
public
function
__construct
(
$alias
)
{
$this
->
alias
=
$alias
;
}
public
function
getConfigTreeBuilder
()
{
$treeBuilder
=
new
TreeBuilder
();
$rootNode
=
$treeBuilder
->
root
(
$this
->
alias
);
$rootNode
->
addDefaultsIfNotSet
()
->
children
()
->
booleanNode
(
'enabled'
)
->
defaultFalse
()
->
end
()
->
scalarNode
(
'entity_manager'
)
->
defaultValue
(
'default'
)
->
end
()
->
arrayNode
(
'implementation_dirs'
)
->
scalarPrototype
()
->
end
()
->
end
()
->
arrayNode
(
'type_dirs'
)
->
scalarPrototype
()
->
end
()
->
end
()
->
arrayNode
(
'string_function_dirs'
)
->
scalarPrototype
()
->
end
()
->
end
()
->
arrayNode
(
'numeric_function_dirs'
)
->
scalarPrototype
()
->
end
()
->
end
()
->
end
()
;
return
$treeBuilder
;
}
}
DependencyInjection/CwdDataDoctrineORMExtension.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\DependencyInjection
;
use
Symfony\Component\Config\FileLocator
;
use
Symfony\Component\DependencyInjection\ContainerBuilder
;
use
Symfony\Component\DependencyInjection\Loader\YamlFileLoader
;
use
Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension
;
class
CwdDataDoctrineORMExtension
extends
ConfigurableExtension
{
/**
* @var string
*/
private
$alias
;
public
function
__construct
(
$alias
)
{
$this
->
alias
=
$alias
;
}
public
function
getAlias
()
{
return
$this
->
alias
;
}
public
function
getConfiguration
(
array
$config
,
ContainerBuilder
$container
)
{
return
new
Configuration
(
$this
->
alias
);
}
protected
function
loadInternal
(
array
$mergedConfig
,
ContainerBuilder
$container
)
{
if
(
!
$mergedConfig
[
'enabled'
])
{
return
;
}
$container
->
setParameter
(
'cwd_data_doctrine_orm.entity_manager'
,
$mergedConfig
[
'entity_manager'
]
);
$container
->
setParameter
(
'cwd_data_doctrine_orm.implementation_dirs'
,
$mergedConfig
[
'implementation_dirs'
]
);
$container
->
setParameter
(
'cwd_data_doctrine_orm.type_dirs'
,
$mergedConfig
[
'type_dirs'
]
);
$container
->
setParameter
(
'cwd_data_doctrine_orm.string_function_dirs'
,
$mergedConfig
[
'string_function_dirs'
]
);
$container
->
setParameter
(
'cwd_data_doctrine_orm.numeric_function_dirs'
,
$mergedConfig
[
'numeric_function_dirs'
]
);
$loader
=
new
YamlFileLoader
(
$container
,
new
FileLocator
(
__DIR__
.
'/../Resources/config'
));
$loader
->
load
(
'services.yml'
);
}
}
DependencyInjection/ORMRepositoryServiceDefinitionFactory.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\DependencyInjection
;
use
Cwd\DataBundle\DependencyInjection\ServiceDefinitionFactory
;
use
Symfony\Component\DependencyInjection\Definition
;
use
Symfony\Component\ExpressionLanguage\Expression
;
class
ORMRepositoryServiceDefinitionFactory
implements
ServiceDefinitionFactory
{
public
function
createServiceDefinition
(
string
$className
,
string
$interfaceName
,
string
$aggregateClass
,
string
$aggregateId
):
Definition
{
$definition
=
new
Definition
(
$className
,
[
$aggregateClass
]);
$definition
->
setFactory
([
new
Expression
(
sprintf
(
'service("doctrine").getManagerForClass("%s")'
,
addslashes
(
$aggregateClass
)
)),
'getRepository'
,
]);
return
$definition
;
}
}
Driver/SharedPDOPgSqlDriver.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\Driver
;
use
Doctrine\DBAL\Driver\PDOPgSql\Driver
;
/**
* Reuses a PDO connection as long as the process is running.
*
* This driver is used for testing. An alternative could have been to use a
* persistent PDO, but PDO::ATTR_PERSISTENT cannot be used in combination with
* PDO::ATTR_STATEMENT_CLASS, which is automatically set by Doctrine in
* PDOConnection (the result is an exception).
*
* Since we don't need "real" persistent connections (a connection that is
* reused between processes) this solution suffices.
*/
class
SharedPDOPgSqlDriver
extends
Driver
{
private
static
$pdo
;
public
function
connect
(
array
$params
,
$username
=
null
,
$password
=
null
,
array
$driverOptions
=
[])
{
if
(
null
===
static
::
$pdo
)
{
static
::
$pdo
=
parent
::
connect
(
$params
,
$username
,
$password
,
$driverOptions
);
}
return
static
::
$pdo
;
}
}
Func/Postgresql/Numeric/ArrayLength.php
0 → 100644
View file @
4a5bb42e
<?php
/*
* This file is part of the ÖWM API.
*
* (c) 2016-2018 cwd.at GmbH <office@cwd.at>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare
(
strict_types
=
1
);
namespace
Cwd\DataDoctrineORMBundle\Func\Postgresql\Numeric
;
use
Doctrine\ORM\Query\AST\Functions\FunctionNode
;
use
Doctrine\ORM\Query\AST\PathExpression
;
use
Doctrine\ORM\Query\Lexer
;
use
Doctrine\ORM\Query\Parser
;
use
Doctrine\ORM\Query\SqlWalker
;
/**
* Implements PosgreSQL's array_length() function for DQL.
*/
class
ArrayLength
extends
FunctionNode
{
/**
* @var PathExpression
*/
public
$stringPrimary
;
/**
* @var PathExpression
*/
public
$arithmeticPrimary
;
/**
* {@inheritdoc}
*/
public
function
parse
(
Parser
$parser
)
{
$parser
->
match
(
Lexer
::
T_IDENTIFIER
);
$parser
->
match
(
Lexer
::
T_OPEN_PARENTHESIS
);
$this
->
stringPrimary
=
$parser
->
StringPrimary
();
$parser
->
match
(
Lexer
::
T_COMMA
);
$this
->
arithmeticPrimary
=
$parser
->
ArithmeticPrimary
();
$parser
->
match
(
Lexer
::
T_CLOSE_PARENTHESIS
);
}
/**
* {@inheritdoc}
*/
public
function
getSql
(
SqlWalker
$sqlWalker
)
{
return
sprintf
(
'array_length(%s, %s)'
,
$this
->
stringPrimary
->
dispatch
(
$sqlWalker
),
$this
->
arithmeticPrimary
->
dispatch
(
$sqlWalker
)
);
}
}
Func/Postgresql/Numeric/Distance.php
0 → 100644
View file @
4a5bb42e
<?php