1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Dolgov_M <[email protected]> |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace SilexDoctrineHydrationProfile; |
7
|
|
|
|
8
|
|
|
use Debesha\DoctrineProfileExtraBundle\ORM\HydrationLogger; |
9
|
|
|
use Doctrine\DBAL\Types\Type; |
10
|
|
|
use Pimple\Container; |
11
|
|
|
use Pimple\ServiceProviderInterface; |
12
|
|
|
use Silex\Application; |
13
|
|
|
use Symfony\Component\HttpKernel\Controller\ControllerReference; |
14
|
|
|
|
15
|
|
|
class SilexDoctrineHydrationProfileProvider implements ServiceProviderInterface |
16
|
|
|
{ |
17
|
|
|
|
18
|
|
|
const ORM_EM_OPTIONS = 'orm.em.options'; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Registers services on the given app. |
22
|
|
|
* |
23
|
|
|
* @param Container $app |
24
|
|
|
*/ |
25
|
|
|
public function register(Container $app) |
26
|
|
|
{ |
27
|
|
|
$app["debesha.doctrine_extra_profiler.logger"] = function () use ($app) { |
28
|
|
|
return new HydrationLogger($app->offsetGet("orm.em")); |
|
|
|
|
29
|
|
|
}; |
30
|
|
|
$app['debesha.class.hydrationDataCollector'] = 'SilexDoctrineHydrationProfile\Fix\DataCollector'; |
31
|
|
|
$app["debesha.doctrine_extra_profiler.data_collector"] = function () use ($app) { |
32
|
|
|
$class = $app['debesha.class.hydrationDataCollector']; |
33
|
|
|
return new $class( |
34
|
|
|
$app->offsetGet("debesha.doctrine_extra_profiler.logger") |
35
|
|
|
); |
36
|
|
|
}; |
37
|
|
|
|
38
|
|
|
if ($app->offsetExists(self::ORM_EM_OPTIONS)) { |
39
|
|
|
$options = $app->offsetGet(self::ORM_EM_OPTIONS); |
40
|
|
|
} else { |
41
|
|
|
$options = array(); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
$overwrite = array( |
45
|
|
|
'class.configuration' => 'SilexDoctrineHydrationProfile\Fix\LoggingConfiguration', |
46
|
|
|
'class.entityManager' => 'Debesha\DoctrineProfileExtraBundle\ORM\LoggingEntityManager', |
47
|
|
|
'class.driver.yml' => 'Doctrine\ORM\Mapping\Driver\YamlDriver', |
48
|
|
|
'class.driver.simple_yml' => 'Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver', |
49
|
|
|
'class.driver.xml' => 'Doctrine\ORM\Mapping\Driver\XmlDriver', |
50
|
|
|
'class.driver.simple_xml' => 'Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver', |
51
|
|
|
'class.driver.php' => 'Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver', |
52
|
|
|
); |
53
|
|
|
|
54
|
|
|
foreach ($overwrite as $key => $className) { |
55
|
|
|
if (!isset($options[$key])) { |
56
|
|
|
$options[$key] = $className; |
57
|
|
|
} |
58
|
|
|
} |
59
|
|
|
$app[self::ORM_EM_OPTIONS] = $options; |
60
|
|
|
|
61
|
|
|
$app['orm.ems'] = function($app) { |
62
|
|
|
/** |
63
|
|
|
* @var Container $app |
64
|
|
|
*/ |
65
|
|
|
$app['orm.ems.options.initializer'](); |
66
|
|
|
|
67
|
|
|
$ems = new Container(); |
68
|
|
|
foreach ($app['orm.ems.options'] as $name => $options) { |
69
|
|
|
if ($app['orm.ems.default'] === $name) { |
70
|
|
|
// we use shortcuts here in case the default has been overridden |
71
|
|
|
$config = $app['orm.em.config']; |
72
|
|
|
} else { |
73
|
|
|
$config = $app['orm.ems.config'][$name]; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
$ems[$name] = function () use ($app, $options, $config) { |
77
|
|
|
/** |
78
|
|
|
* @var $entityManagerClassName \Doctrine\ORM\EntityManager |
79
|
|
|
*/ |
80
|
|
|
$entityManagerClassName = $options['class.entityManager']; |
81
|
|
|
return $entityManagerClassName::create( |
82
|
|
|
$app['dbs'][$options['connection']], |
83
|
|
|
$config, |
84
|
|
|
$app['dbs.event_manager'][$options['connection']] |
85
|
|
|
); |
86
|
|
|
}; |
87
|
|
|
} |
88
|
|
|
return $ems; |
89
|
|
|
}; |
90
|
|
|
|
91
|
|
|
$app['orm.ems.config'] = function(Container $app) { |
92
|
|
|
$app['orm.ems.options.initializer'](); |
93
|
|
|
|
94
|
|
|
$configs = new Container(); |
95
|
|
|
foreach ($app['orm.ems.options'] as $name => $options) { |
96
|
|
|
/** |
97
|
|
|
* @var $config \Doctrine\ORM\Configuration |
98
|
|
|
*/ |
99
|
|
|
$configurationClassName = $options['class.configuration']; |
100
|
|
|
$config = new $configurationClassName; |
101
|
|
|
|
102
|
|
|
$app['orm.cache.configurer']($name, $config, $options); |
103
|
|
|
|
104
|
|
|
$config->setProxyDir($app['orm.proxies_dir']); |
105
|
|
|
$config->setProxyNamespace($app['orm.proxies_namespace']); |
106
|
|
|
$config->setAutoGenerateProxyClasses($app['orm.auto_generate_proxies']); |
107
|
|
|
|
108
|
|
|
$config->setCustomStringFunctions($app['orm.custom.functions.string']); |
109
|
|
|
$config->setCustomNumericFunctions($app['orm.custom.functions.numeric']); |
110
|
|
|
$config->setCustomDatetimeFunctions($app['orm.custom.functions.datetime']); |
111
|
|
|
$config->setCustomHydrationModes($app['orm.custom.hydration_modes']); |
112
|
|
|
|
113
|
|
|
$config->setClassMetadataFactoryName($app['orm.class_metadata_factory_name']); |
114
|
|
|
$config->setDefaultRepositoryClassName($app['orm.default_repository_class']); |
115
|
|
|
|
116
|
|
|
$config->setEntityListenerResolver($app['orm.entity_listener_resolver']); |
117
|
|
|
$config->setRepositoryFactory($app['orm.repository_factory']); |
118
|
|
|
|
119
|
|
|
$config->setNamingStrategy($app['orm.strategy.naming']); |
120
|
|
|
$config->setQuoteStrategy($app['orm.strategy.quote']); |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @var \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain $chain |
124
|
|
|
*/ |
125
|
|
|
$chain = $app['orm.mapping_driver_chain.locator']($name); |
126
|
|
|
foreach ((array) $options['mappings'] as $entity) { |
127
|
|
|
if (!is_array($entity)) { |
128
|
|
|
throw new \InvalidArgumentException( |
129
|
|
|
"The 'orm.em.options' option 'mappings' should be an array of arrays." |
130
|
|
|
); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
if (!empty($entity['resources_namespace'])) { |
134
|
|
|
if($app->offsetExists('psr0_resource_locator')) { |
135
|
|
|
$entity['path'] = $app['psr0_resource_locator']->findFirstDirectory($entity['resources_namespace']); |
136
|
|
|
} else { |
137
|
|
|
throw new \InvalidArgumentException('Not exist psr0_resource_locator'); |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
if (isset($entity['alias'])) { |
142
|
|
|
$config->addEntityNamespace($entity['alias'], $entity['namespace']); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
if('annotation' === $entity['type']){ |
146
|
|
|
$useSimpleAnnotationReader = isset($entity['use_simple_annotation_reader']) |
147
|
|
|
? $entity['use_simple_annotation_reader'] |
148
|
|
|
: true; |
149
|
|
|
$driver = $config->newDefaultAnnotationDriver((array) $entity['path'], $useSimpleAnnotationReader); |
150
|
|
|
} else { |
151
|
|
|
$driver = $app['orm.driver.factory']( $entity, $options ); |
152
|
|
|
} |
153
|
|
|
$chain->addDriver($driver, $entity['namespace']); |
154
|
|
|
} |
155
|
|
|
$config->setMetadataDriverImpl($chain); |
156
|
|
|
|
157
|
|
|
foreach ((array) $options['types'] as $typeName => $typeClass) { |
158
|
|
|
if (Type::hasType($typeName)) { |
159
|
|
|
Type::overrideType($typeName, $typeClass); |
160
|
|
|
} else { |
161
|
|
|
Type::addType($typeName, $typeClass); |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
$configs[$name] = $config; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return $configs; |
169
|
|
|
}; |
170
|
|
|
|
171
|
|
|
|
172
|
|
|
$app['orm.driver.factory'] = function(){ |
173
|
|
|
$simpleList = array( |
174
|
|
|
'simple_yml', |
175
|
|
|
'simple_xml', |
176
|
|
|
); |
177
|
|
|
return function ( $entity, $options ) use ($simpleList) { |
178
|
|
|
if (isset($options[ 'class.driver.' . $entity['type'] ])) { |
179
|
|
|
$className = $options[ 'class.driver.' . $entity['type'] ]; |
180
|
|
|
if( in_array($entity['type'], $simpleList) ) { |
181
|
|
|
$param = array($entity['path'] => $entity['namespace']); |
182
|
|
|
} else { |
183
|
|
|
$param = $entity['path']; |
184
|
|
|
} |
185
|
|
|
return new $className($param); |
186
|
|
|
} |
187
|
|
|
throw new \InvalidArgumentException(sprintf('"%s" is not a recognized driver', $entity['type'])); |
188
|
|
|
}; |
189
|
|
|
}; |
190
|
|
|
|
191
|
|
|
$app->extend('data_collectors', function($collectors) { |
192
|
|
|
$collectors["hydrations"] = function ($app) { |
193
|
|
|
return $app["debesha.doctrine_extra_profiler.data_collector"]; |
194
|
|
|
}; |
195
|
|
|
return $collectors; |
196
|
|
|
}); |
197
|
|
|
$app->extend("data_collector.templates", function ($templates) { |
198
|
|
|
$templates[] = array("hydrations", "@DebeshaDoctrineProfileExtraBundle/Collector/hydrations.html.twig"); |
199
|
|
|
return $templates; |
200
|
|
|
} ); |
201
|
|
|
$app->extend('twig', function ($twig) use($app) { |
202
|
|
|
$options = array('is_safe' => array('html')); |
203
|
|
|
$callable = function ($controller, $attributes = array(), $query = array()) { |
204
|
|
|
return new ControllerReference($controller, $attributes, $query); |
205
|
|
|
}; |
206
|
|
|
$twig->addFunction(new \Twig_SimpleFunction("controller", $callable, $options)); |
207
|
|
|
$app['twig.loader.filesystem']->addPath(dirname(__FILE__) . DIRECTORY_SEPARATOR . "Views", "DebeshaDoctrineProfileExtraBundle"); |
208
|
|
|
return $twig; |
209
|
|
|
}); |
210
|
|
|
} |
211
|
|
|
} |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.