1<?php 2 3namespace JMS\SerializerBundle\Tests\DependencyInjection; 4 5use JMS\Serializer\Exception\RuntimeException; 6use JMS\SerializerBundle\DependencyInjection\Compiler\CustomHandlersPass; 7use JMS\SerializerBundle\DependencyInjection\JMSSerializerExtension; 8use PHPUnit\Framework\TestCase; 9use Symfony\Component\DependencyInjection\ContainerBuilder; 10use Symfony\Component\DependencyInjection\Definition; 11use Symfony\Component\DependencyInjection\Reference; 12 13class CustomHandlerPassTest extends TestCase 14{ 15 /** 16 * @param array $configs 17 * @return ContainerBuilder 18 */ 19 private function getContainer(array $configs = array()) 20 { 21 $loader = new JMSSerializerExtension(); 22 $container = new ContainerBuilder(); 23 24 $container->setParameter('kernel.debug', true); 25 $container->setParameter('kernel.cache_dir', sys_get_temp_dir() . '/serializer'); 26 $container->setParameter('kernel.bundles', array()); 27 $container->setParameter('kernel.bundles', array()); 28 29 $loader->load(['jms_serializer' => $configs], $container); 30 31 // remove other subscribers 32 foreach (array_keys($container->findTaggedServiceIds('jms_serializer.handler')) as $id) { 33 $container->removeDefinition($id); 34 } 35 foreach (array_keys($container->findTaggedServiceIds('jms_serializer.subscribing_handler')) as $id) { 36 $container->removeDefinition($id); 37 } 38 39 return $container; 40 } 41 42 public function testHandler() 43 { 44 $container = $this->getContainer(); 45 46 $def = new Definition('Foo'); 47 $def->addTag('jms_serializer.handler', [ 48 'type' => 'DateTime', 49 'format' => 'json', 50 ]); 51 $container->setDefinition('my_service', $def); 52 53 $pass = new CustomHandlersPass(); 54 $pass->process($container); 55 56 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 57 58 $this->assertSame([ 59 2 => ['DateTime' => ['json' => ['my_service', 'deserializeDateTimeFromjson']]], 60 1 => ['DateTime' => ['json' => ['my_service', 'serializeDateTimeTojson']]] 61 ], $args[1]); 62 } 63 64 public function testHandlerCanBePrivate() 65 { 66 $container = $this->getContainer(); 67 68 $def = new Definition('Foo'); 69 $def->setPublic(false); 70 $def->addTag('jms_serializer.handler', [ 71 'type' => 'DateTime', 72 'format' => 'json', 73 ]); 74 $container->setDefinition('my_service', $def); 75 76 $pass = new CustomHandlersPass(); 77 $pass->process($container); 78 79 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 80 81 $this->assertEquals([ 82 2 => ['DateTime' => ['json' => [new Reference('my_service'), 'deserializeDateTimeFromjson']]], 83 1 => ['DateTime' => ['json' => [new Reference('my_service'), 'serializeDateTimeTojson']]] 84 ], $args[1]); 85 } 86 87 public function testHandlerDirection() 88 { 89 $container = $this->getContainer(); 90 91 $def = new Definition('Foo'); 92 $def->addTag('jms_serializer.handler', [ 93 'type' => 'DateTime', 94 'format' => 'json', 95 'direction' => 'SERIALIZATION', 96 ]); 97 $container->setDefinition('my_service', $def); 98 99 $pass = new CustomHandlersPass(); 100 $pass->process($container); 101 102 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 103 104 $this->assertSame([ 105 1 => ['DateTime' => ['json' => ['my_service', 'serializeDateTimeTojson']]] 106 ], $args[1]); 107 } 108 109 /** 110 * @expectedException RuntimeException 111 * @expectedExceptionMessage The direction "bar" of tag "jms_serializer.handler" of service "my_service" does not exist 112 */ 113 public function testHandlerIncorrectDirection() 114 { 115 $container = $this->getContainer(); 116 117 $def = new Definition('Foo'); 118 $def->addTag('jms_serializer.handler', [ 119 'type' => 'DateTime', 120 'format' => 'json', 121 'direction' => 'bar', 122 ]); 123 $container->setDefinition('my_service', $def); 124 125 $pass = new CustomHandlersPass(); 126 $pass->process($container); 127 } 128 129 /** 130 * @expectedException RuntimeException 131 * @expectedExceptionMessage Each tag named "jms_serializer.handler" of service "my_service" must have at least two attributes: "type" and "format" 132 */ 133 public function testHandlerMustHaveTypeAndFormat() 134 { 135 $container = $this->getContainer(); 136 137 $def = new Definition('Foo'); 138 $def->addTag('jms_serializer.handler'); 139 $container->setDefinition('my_service', $def); 140 141 $pass = new CustomHandlersPass(); 142 $pass->process($container); 143 } 144 145 public function testHandlerMustPrioritizeUserDefined() 146 { 147 $container = $this->getContainer(); 148 149 $def = new Definition('JMS\Serializer\Foo'); 150 $def->addTag('jms_serializer.handler', [ 151 'type' => 'DateTime', 152 'format' => 'json', 153 ]); 154 $container->setDefinition('my_service', $def); 155 156 $userDef = new Definition('Bar'); 157 $userDef->addTag('jms_serializer.handler', [ 158 'type' => 'DateTime', 159 'format' => 'json', 160 ]); 161 $container->setDefinition('my_custom_service', $userDef); 162 163 $pass = new CustomHandlersPass(); 164 $pass->process($container); 165 166 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 167 168 $this->assertSame([ 169 2 => ['DateTime' => ['json' => ['my_custom_service', 'deserializeDateTimeFromjson']]], 170 1 => ['DateTime' => ['json' => ['my_custom_service', 'serializeDateTimeTojson']]] 171 ], $args[1]); 172 } 173 174 public function testHandlerMustRespectPriorities() 175 { 176 $container = $this->getContainer(); 177 178 $def = new Definition('JMS\Serializer\Foo'); 179 $def->addTag('jms_serializer.handler', [ 180 'type' => 'DateTime', 181 'format' => 'json', 182 ]); 183 $container->setDefinition('my_service', $def); 184 185 $userDef = new Definition('Bar'); 186 $userDef->addTag('jms_serializer.handler', [ 187 'type' => 'DateTime', 188 'format' => 'json', 189 ]); 190 $container->setDefinition('my_custom_service', $userDef); 191 192 $userExplicitDef = new Definition('Baz'); 193 $userExplicitDef->addTag('jms_serializer.handler', [ 194 'type' => 'DateTime', 195 'format' => 'json', 196 'priority' => -100 197 ]); 198 $container->setDefinition('my_custom_explicit_service', $userExplicitDef); 199 200 $pass = new CustomHandlersPass(); 201 $pass->process($container); 202 203 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 204 205 $this->assertSame([ 206 2 => ['DateTime' => ['json' => ['my_custom_explicit_service', 'deserializeDateTimeFromjson']]], 207 1 => ['DateTime' => ['json' => ['my_custom_explicit_service', 'serializeDateTimeTojson']]] 208 ], $args[1]); 209 } 210 211 public function testHandlerCanBeRegisteredForMultipleTypesOrDirections() 212 { 213 $container = $this->getContainer(); 214 215 $def = new Definition('JMS\Serializer\Foo'); 216 $def->addTag('jms_serializer.handler', [ 217 'type' => 'Custom', 218 'direction' => 'serialization', 219 'format' => 'json', 220 'method' => 'serialize', 221 ]); 222 $def->addTag('jms_serializer.handler', [ 223 'type' => 'Custom', 224 'direction' => 'deserialization', 225 'format' => 'json', 226 'method' => 'deserialize', 227 ]); 228 $def->addTag('jms_serializer.handler', [ 229 'type' => 'Custom<?>', 230 'direction' => 'serialization', 231 'format' => 'json', 232 'method' => 'serialize', 233 ]); 234 $def->addTag('jms_serializer.handler', [ 235 'type' => 'Custom<?>', 236 'direction' => 'deserialization', 237 'format' => 'json', 238 'method' => 'deserialize', 239 ]); 240 $container->setDefinition('my_service', $def); 241 242 $pass = new CustomHandlersPass(); 243 $pass->process($container); 244 245 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 246 247 $this->assertSame([ 248 1 => [ 249 'Custom' => ['json' => ['my_service', 'serialize']], 250 'Custom<?>' => ['json' => ['my_service', 'serialize']], 251 ], 252 2 => [ 253 'Custom' => ['json' => ['my_service', 'deserialize']], 254 'Custom<?>' => ['json' => ['my_service', 'deserialize']], 255 ] 256 ], $args[1]); 257 } 258 259 public function testSubscribingHandler() 260 { 261 $container = $this->getContainer(); 262 263 $def = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\SubscribingHandler'); 264 $def->addTag('jms_serializer.subscribing_handler'); 265 $container->setDefinition('my_service', $def); 266 267 $pass = new CustomHandlersPass(); 268 $pass->process($container); 269 270 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 271 272 $this->assertSame([ 273 1 => ['DateTime' => ['json' => ['my_service', 'onDateTime']]] 274 ], $args[1]); 275 } 276 277 public function testSubscribingHandlerCanBePrivate() 278 { 279 $container = $this->getContainer(); 280 281 $def = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\SubscribingHandler'); 282 $def->addTag('jms_serializer.subscribing_handler'); 283 $def->setPublic(false); 284 $container->setDefinition('my_service', $def); 285 286 $pass = new CustomHandlersPass(); 287 $pass->process($container); 288 289 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 290 291 $this->assertEquals([ 292 1 => ['DateTime' => ['json' => [new Reference('my_service'), 'onDateTime']]] 293 ], $args[1]); 294 } 295 296 /** 297 * @expectedException RuntimeException 298 * @expectedExceptionMessage The service "my_service" must implement the SubscribingHandlerInterface 299 */ 300 public function testSubscribingHandlerInterface() 301 { 302 $container = $this->getContainer(); 303 304 $def = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\SimpleObject'); 305 $def->addTag('jms_serializer.subscribing_handler'); 306 $container->setDefinition('my_service', $def); 307 308 $pass = new CustomHandlersPass(); 309 $pass->process($container); 310 } 311 312 public function testSubscribingHandlerMustPrioritizeUserDefined() 313 { 314 $container = $this->getContainer(); 315 316 $def = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\SubscribingHandler'); 317 $def->addTag('jms_serializer.subscribing_handler'); 318 $container->setDefinition('my_service', $def); 319 320 $userDef = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\UserDefined\UserDefinedSubscribingHandler'); 321 $userDef->addTag('jms_serializer.subscribing_handler'); 322 $container->setDefinition('my_custom_service', $userDef); 323 324 $pass = new CustomHandlersPass(); 325 $pass->process($container); 326 327 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 328 329 $this->assertSame([ 330 1 => ['DateTime' => ['json' => ['my_custom_service', 'onDateTime']]] 331 ], $args[1]); 332 } 333 334 public function testSubscribingHandlerMustRespectPriorities() 335 { 336 $container = $this->getContainer(); 337 338 $def = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\SubscribingHandler'); 339 $def->addTag('jms_serializer.subscribing_handler'); 340 $container->setDefinition('my_service', $def); 341 342 $userDef = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\UserDefined\UserDefinedSubscribingHandler'); 343 $userDef->addTag('jms_serializer.subscribing_handler'); 344 $container->setDefinition('my_custom_service', $userDef); 345 346 $userExplicitDef = new Definition('JMS\SerializerBundle\Tests\DependencyInjection\Fixture\UserDefined\UserDefinedSubscribingHandler'); 347 $userExplicitDef->addTag('jms_serializer.subscribing_handler', ['priority' => -100]); 348 $container->setDefinition('my_custom_explicit_service', $userExplicitDef); 349 350 $pass = new CustomHandlersPass(); 351 $pass->process($container); 352 353 $args = $container->getDefinition('jms_serializer.handler_registry')->getArguments(); 354 355 $this->assertSame([ 356 1 => ['DateTime' => ['json' => ['my_custom_explicit_service', 'onDateTime']]] 357 ], $args[1]); 358 } 359 360} 361