• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FreezyBee / Httplug / 4966200267

pending completion
4966200267

push

github

Jakub Janata
psr 17 + 18

174 of 205 relevant lines covered (84.88%)

0.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.59
/src/DI/HttplugExtension.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace FreezyBee\Httplug\DI;
6

7
use FreezyBee\Httplug\ClientFactory\PluginClientFactory;
8
use FreezyBee\Httplug\DI\Plugin\IPluginServiceDefinitonCreator;
9
use FreezyBee\Httplug\Tracy\MessagePanel;
10
use FreezyBee\Httplug\Tracy\PluginClientDecorator;
11
use Http\Client\Common\PluginClient;
12
use Http\Discovery\Psr17FactoryDiscovery;
13
use Http\Discovery\Psr18ClientDiscovery;
14
use InvalidArgumentException;
15
use Nette\DI\CompilerExtension;
16
use Nette\DI\ContainerBuilder;
17
use Nette\DI\Definitions\Definition;
18
use Nette\DI\Definitions\ServiceDefinition;
19
use Nette\DI\Definitions\Statement;
20
use Nette\DI\Helpers;
21
use Psr\Http\Client\ClientInterface;
22
use Psr\Http\Message\RequestFactoryInterface;
23
use Psr\Http\Message\StreamFactoryInterface;
24
use Psr\Http\Message\UriFactoryInterface;
25

26
/**
27
 * @author Jakub Janata <jakubjanata@gmail.com>
28
 */
29
class HttplugExtension extends CompilerExtension
30
{
31
    private bool $debugMode = false;
32

33
    /** @var array<string, mixed> */
34
    private static array $defaults = [
35
        # uses discovery if not specified
36
        'classes' => [
37
            'client' => null,
38
            'requestFactory' => null,
39
            'uriFactory' => null,
40
            'streamFactory' => null
41
        ],
42
        # default settings for clients
43
        'clientDefaults' => [
44
            'factory' => null
45
        ],
46
        # clients configurations
47
        'clients' => [],
48
        # tracy debug
49
        'tracy' => [
50
            'debugger' => '%debugMode%',
51
            'plugins' => []
52
        ]
53
    ];
54

55
    /** @var array<string, string> */
56
    private array $classes = [
57
        'client' => ClientInterface::class,
58
        'requestFactory' => RequestFactoryInterface::class,
59
        'uriFactory' => UriFactoryInterface::class,
60
        'streamFactory' => StreamFactoryInterface::class,
61
    ];
62

63
    /** @var array<string, mixed> */
64
    private array $factoryClasses = [
65
        'client' => [Psr18ClientDiscovery::class, 'find'],
66
        'requestFactory' => [Psr17FactoryDiscovery::class, 'findRequestFactory'],
67
        'uriFactory' => [Psr17FactoryDiscovery::class, 'findUriFactory'],
68
        'streamFactory' => [Psr17FactoryDiscovery::class, 'findStreamFactory'],
69
    ];
70

71
    /**
72
     * {@inheritdoc}
73
     */
74
    public function loadConfiguration(): void
75
    {
76
        $containerBuilder = $this->getContainerBuilder();
1✔
77

78
        $this->config = $this->validateConfig(Helpers::expand(self::$defaults, $containerBuilder->parameters));
1✔
79
        $config = $this->config;
1✔
80

81
        $factories = $this->loadFromFile(__DIR__ . '/factories.neon');
1✔
82
        $this->loadDefinitionsFromConfig($factories);
1✔
83

84
        $this->debugMode = $config['tracy']['debugger'];
1✔
85

86
        // register default services
87
        foreach ($config['classes'] as $service => $class) {
1✔
88
            $def = $containerBuilder->addDefinition($this->prefix($service));
1✔
89

90
            if ($class !== null) {
1✔
91
                // user defined
92
                $def->setType($class);
×
93
            } else {
94
                $class = $this->classes[$service];
1✔
95
                // discovery
96
                $def->setType($class)
1✔
97
                    ->setFactory($this->factoryClasses[$service]);
1✔
98
            }
99
        }
100

101
        // configure clients
102
        foreach ($config['clients'] as $name => $arguments) {
1✔
103
            $this->configureClient($containerBuilder, $name, $arguments ?? []);
1✔
104
        }
105

106
        // register tracy panel
107
        if ($this->debugMode) {
1✔
108
            /** @var ServiceDefinition $def */
109
            $def = $containerBuilder->getDefinition('tracy.bar');
1✔
110
            $def->addSetup('addPanel', [new Statement(MessagePanel::class)]);
1✔
111
        }
112
    }
1✔
113

114
    /**
115
     * @param ContainerBuilder $containerBuilder
116
     * @param string $clientName
117
     * @param array<mixed> $clientConfig
118
     */
119
    private function configureClient(ContainerBuilder $containerBuilder, string $clientName, array $clientConfig): void
120
    {
121
        $serviceName = $this->prefix("client.$clientName");
1✔
122

123
        /** @var mixed[] $config */
124
        $config = $this->config;
1✔
125
        $factory = $clientConfig['factory'] ?? $config['clientDefaults']['factory'];
1✔
126
        if ($factory === null) {
1✔
127
            throw new InvalidArgumentException('Please specify client factory (or default client factory)');
×
128
        }
129

130
        $plugins = $clientConfig['plugins'] ?? [];
1✔
131
        $pluginServices = [];
1✔
132

133
        foreach ($plugins as $pluginName => $pluginConfig) {
1✔
134
            $pluginServices[] = $this->configurePlugin($containerBuilder, $pluginName, $clientName, $pluginConfig);
1✔
135
        }
136

137
        $pluginClientOptions = [];
1✔
138

139
        $containerBuilder
140
            ->addDefinition($serviceName)
1✔
141
            ->setType($this->debugMode ? PluginClientDecorator::class : PluginClient::class)
1✔
142
            ->setFactory([PluginClientFactory::class, 'createPluginClient'])
1✔
143
            ->setArguments([
1✔
144
                $pluginServices,
1✔
145
                $factory,
1✔
146
                $clientConfig['config'] ?? [],
1✔
147
                $pluginClientOptions,
1✔
148
                $this->debugMode
1✔
149
            ]);
150
    }
1✔
151

152
    /**
153
     * @param array<mixed> $pluginConfig
154
     */
155
    private function configurePlugin(
156
        ContainerBuilder $containerBuilder,
157
        string $pluginName,
158
        string $clientName,
159
        array $pluginConfig
160
    ): Definition {
161

162
        $creator = 'FreezyBee\Httplug\DI\Plugin\\' . ucfirst($pluginName);
1✔
163

164
        if (class_exists($creator)) {
1✔
165
            /** @var IPluginServiceDefinitonCreator $creator */
166
            return $creator::createPluginServiceDefinition($containerBuilder, $this->name, $clientName, $pluginConfig);
1✔
167
        }
168

169
        // user custom plugin
170
        $def = $containerBuilder
1✔
171
            ->addDefinition($this->prefix("client.$clientName.plugin.$pluginName"))
1✔
172
            ->setType($pluginConfig['class']);
1✔
173

174
        if (isset($pluginConfig['arguments'])) {
1✔
175
            $def->setArguments($pluginConfig['arguments']);
1✔
176
        }
177

178
        return $def;
1✔
179
    }
180

181
    /**
182
     * {@inheritdoc}
183
     */
184
    public function beforeCompile(): void
185
    {
186
        $containerBuilder = $this->getContainerBuilder();
1✔
187

188
        // configure clients from another extensions
189
        foreach ($this->compiler->getExtensions() as $extension) {
1✔
190
            if ($extension instanceof IClientProvider) {
1✔
191
                foreach ($extension->getClientConfigs() as $name => $arguments) {
×
192
                    $this->configureClient($containerBuilder, $name, $arguments ?? []);
×
193
                }
194
            }
195
        }
196
    }
1✔
197
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc