|
12 | 12 | use Http\Client\Common\PluginClientFactory; |
13 | 13 | use Http\Client\HttpAsyncClient; |
14 | 14 | use Http\Client\HttpClient; |
| 15 | +use Http\Client\Plugin\Vcr\RecordPlugin; |
| 16 | +use Http\Client\Plugin\Vcr\ReplayPlugin; |
15 | 17 | use Http\Message\Authentication\BasicAuth; |
16 | 18 | use Http\Message\Authentication\Bearer; |
17 | 19 | use Http\Message\Authentication\QueryParam; |
|
35 | 37 | */ |
36 | 38 | class HttplugExtension extends Extension |
37 | 39 | { |
| 40 | + /** |
| 41 | + * Used to check is the VCR plugin is installed. |
| 42 | + * |
| 43 | + * @var bool |
| 44 | + */ |
| 45 | + private $useVcrPlugin = false; |
| 46 | + |
38 | 47 | /** |
39 | 48 | * {@inheritdoc} |
40 | 49 | */ |
@@ -94,6 +103,14 @@ public function load(array $configs, ContainerBuilder $container) |
94 | 103 | $container->removeAlias(HttpAsyncClient::class); |
95 | 104 | $container->removeAlias(HttpClient::class); |
96 | 105 | } |
| 106 | + |
| 107 | + if ($this->useVcrPlugin) { |
| 108 | + if (!\class_exists(RecordPlugin::class)) { |
| 109 | + throw new \Exception('You need to require the VCR plugin to be able to use it: "composer require --dev php-http/vcr-plugin".'); |
| 110 | + } |
| 111 | + |
| 112 | + $loader->load('vcr-plugin.xml'); |
| 113 | + } |
97 | 114 | } |
98 | 115 |
|
99 | 116 | /** |
@@ -359,12 +376,20 @@ private function configureClient(ContainerBuilder $container, $clientName, array |
359 | 376 | foreach ($arguments['plugins'] as $plugin) { |
360 | 377 | $pluginName = key($plugin); |
361 | 378 | $pluginConfig = current($plugin); |
362 | | - if ('reference' === $pluginName) { |
363 | | - $plugins[] = $pluginConfig['id']; |
364 | | - } elseif ('authentication' === $pluginName) { |
365 | | - $plugins = array_merge($plugins, $this->configureAuthentication($container, $pluginConfig, $serviceId.'.authentication')); |
366 | | - } else { |
367 | | - $plugins[] = $this->configurePlugin($container, $serviceId, $pluginName, $pluginConfig); |
| 379 | + |
| 380 | + switch ($pluginName) { |
| 381 | + case 'reference': |
| 382 | + $plugins[] = $pluginConfig['id']; |
| 383 | + break; |
| 384 | + case 'authentication': |
| 385 | + $plugins = array_merge($plugins, $this->configureAuthentication($container, $pluginConfig, $serviceId.'.authentication')); |
| 386 | + break; |
| 387 | + case 'vcr': |
| 388 | + $this->useVcrPlugin = true; |
| 389 | + $plugins = array_merge($plugins, $this->configureVcrPlugin($container, $pluginConfig, $serviceId.'.vcr')); |
| 390 | + break; |
| 391 | + default: |
| 392 | + $plugins[] = $this->configurePlugin($container, $serviceId, $pluginName, $pluginConfig); |
368 | 393 | } |
369 | 394 | } |
370 | 395 |
|
@@ -508,13 +533,81 @@ private function configurePlugin(ContainerBuilder $container, $serviceId, $plugi |
508 | 533 | { |
509 | 534 | $pluginServiceId = $serviceId.'.plugin.'.$pluginName; |
510 | 535 |
|
511 | | - $definition = class_exists(ChildDefinition::class) |
512 | | - ? new ChildDefinition('httplug.plugin.'.$pluginName) |
513 | | - : new DefinitionDecorator('httplug.plugin.'.$pluginName); |
| 536 | + $definition = $this->createChildDefinition('httplug.plugin.'.$pluginName); |
514 | 537 |
|
515 | 538 | $this->configurePluginByName($pluginName, $definition, $pluginConfig, $container, $pluginServiceId); |
516 | 539 | $container->setDefinition($pluginServiceId, $definition); |
517 | 540 |
|
518 | 541 | return $pluginServiceId; |
519 | 542 | } |
| 543 | + |
| 544 | + private function configureVcrPlugin(ContainerBuilder $container, array $config, $prefix) |
| 545 | + { |
| 546 | + $recorder = $config['recorder']; |
| 547 | + $recorderId = in_array($recorder, ['filesystem', 'in_memory']) ? 'httplug.plugin.vcr.recorder.'.$recorder : $recorder; |
| 548 | + $namingStrategyId = $config['naming_strategy']; |
| 549 | + $replayId = $prefix.'.replay'; |
| 550 | + $recordId = $prefix.'.record'; |
| 551 | + |
| 552 | + if ('filesystem' === $recorder) { |
| 553 | + $recorderDefinition = $this->createChildDefinition('httplug.plugin.vcr.recorder.filesystem'); |
| 554 | + $recorderDefinition->replaceArgument(0, $config['fixtures_directory']); |
| 555 | + $recorderId = $prefix.'.recorder'; |
| 556 | + |
| 557 | + $container->setDefinition($recorderId, $recorderDefinition); |
| 558 | + } |
| 559 | + |
| 560 | + if ('default' === $config['naming_strategy']) { |
| 561 | + $namingStrategyId = $prefix.'.naming_strategy'; |
| 562 | + $namingStrategy = $this->createChildDefinition('httplug.plugin.vcr.naming_strategy.path'); |
| 563 | + |
| 564 | + if (!empty($config['naming_strategy_options'])) { |
| 565 | + $namingStrategy->setArguments([$config['naming_strategy_options']]); |
| 566 | + } |
| 567 | + |
| 568 | + $container->setDefinition($namingStrategyId, $namingStrategy); |
| 569 | + } |
| 570 | + |
| 571 | + $arguments = [ |
| 572 | + new Reference($namingStrategyId), |
| 573 | + new Reference($recorderId), |
| 574 | + ]; |
| 575 | + $record = new Definition(RecordPlugin::class, $arguments); |
| 576 | + $replay = new Definition(ReplayPlugin::class, $arguments); |
| 577 | + $plugins = []; |
| 578 | + |
| 579 | + switch ($config['mode']) { |
| 580 | + case 'replay': |
| 581 | + $container->setDefinition($replayId, $replay); |
| 582 | + $plugins[] = $replayId; |
| 583 | + break; |
| 584 | + case 'replay_or_record': |
| 585 | + $replay->setArgument(2, false); |
| 586 | + $container->setDefinition($replayId, $replay); |
| 587 | + $container->setDefinition($recordId, $record); |
| 588 | + $plugins[] = $replayId; |
| 589 | + $plugins[] = $recordId; |
| 590 | + break; |
| 591 | + case 'record': |
| 592 | + $container->setDefinition($recordId, $record); |
| 593 | + $plugins[] = $recordId; |
| 594 | + break; |
| 595 | + } |
| 596 | + |
| 597 | + return $plugins; |
| 598 | + } |
| 599 | + |
| 600 | + /** |
| 601 | + * BC for old Symfony versions. Remove this method and use new ChildDefinition directly when we drop support for Symfony 2. |
| 602 | + * |
| 603 | + * @param string $parent the parent service id |
| 604 | + * |
| 605 | + * @return ChildDefinition|DefinitionDecorator |
| 606 | + */ |
| 607 | + private function createChildDefinition($parent) |
| 608 | + { |
| 609 | + $definitionClass = class_exists(ChildDefinition::class) ? ChildDefinition::class : DefinitionDecorator::class; |
| 610 | + |
| 611 | + return new $definitionClass($parent); |
| 612 | + } |
520 | 613 | } |
0 commit comments