Passed
Pull Request — master (#19)
by
unknown
02:43
created

resolveIntegrationsFromUserConfig()   B

Complexity

Conditions 11
Paths 32

Size

Total Lines 72
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 26.125

Importance

Changes 0
Metric Value
cc 11
eloc 45
nc 32
nop 0
dl 0
loc 72
ccs 15
cts 30
cp 0.5
crap 26.125
rs 7.3166
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Sentry;
6
7
use Yiisoft\Yii\Sentry\Http\YiiRequestFetcher;
8
use Psr\Container\ContainerInterface;
9
use Psr\Log\LoggerInterface;
10
use RuntimeException;
11
use Sentry\ClientBuilder;
12
use Sentry\Integration as SdkIntegration;
13
use Sentry\Integration\IntegrationInterface;
14
use Sentry\Options;
15
use Sentry\SentrySdk;
16
use Sentry\State\HubInterface;
17
use Sentry\Transport\TransportFactoryInterface;
18
19
use function is_string;
20
21
final class HubBootstrapper
22
{
23
    public const DEFAULT_INTEGRATIONS = [];
24
25 13
    public function __construct(
26
        private Options $options,
27
        private YiiSentryConfig $configuration,
28
        private TransportFactoryInterface $transportFactory,
29
        private LoggerInterface $logger,
30
        private HubInterface $hub,
31
        private ContainerInterface $container,
32
    ) {
33
    }
34
35 13
    public function bootstrap(): void
36
    {
37 13
        $this->options->setIntegrations(fn (array $integrations) => $this->prepareIntegrations($integrations));
38
39 13
        $clientBuilder = new ClientBuilder($this->options);
40
        $clientBuilder
41 13
            ->setTransportFactory($this->transportFactory)
42 13
            ->setLogger($this->logger);
43
44 13
        $client = $clientBuilder->getClient();
45
46 13
        $hub = $this->hub;
47 13
        $hub->bindClient($client);
48 13
        SentrySdk::setCurrentHub($hub);
49
    }
50
51
    /**
52
     * @param IntegrationInterface[] $integrations
53
     *
54
     * @return IntegrationInterface[]
55
     */
56 13
    public function prepareIntegrations(array $integrations)
57
    {
58 13
        $userIntegrations = $this->resolveIntegrationsFromUserConfig();
59 13
        if ($this->options->hasDefaultIntegrations()) {
60 13
            $integrations = array_filter(
61
                $integrations,
62 13
                static function (
63
                    SdkIntegration\IntegrationInterface $integration
64
                ): bool {
65
                    if (
66
                        $integration instanceof
67
                        SdkIntegration\ErrorListenerIntegration
68
                    ) {
69 1
                        return false;
70
                    }
71
72
                    if (
73
                        $integration instanceof
74
                        SdkIntegration\ExceptionListenerIntegration
75
                    ) {
76 1
                        return false;
77
                    }
78
79
                    if (
80
                        $integration instanceof
81
                        SdkIntegration\FatalErrorListenerIntegration
82
                    ) {
83 1
                        return false;
84
                    }
85
86
                    // We also remove the default request integration so it can be readded
87
                    // after with a Yii3 specific request fetcher. This way we can resolve
88
                    // the request from Yii3 instead of constructing it from the global state
89 13
                    return ! ($integration instanceof
90
                        SdkIntegration\RequestIntegration);
91
                }
92
            );
93
94 13
            $integrations[] = new SdkIntegration\RequestIntegration(
95 13
                new YiiRequestFetcher($this->container)
96
            );
97
        }
98
99 13
        return array_merge($integrations, $userIntegrations);
100
    }
101
102
    /**
103
     * Resolve the integrations from the user configuration with the container.
104
     *
105
     * @return SdkIntegration\IntegrationInterface[]
106
     */
107 13
    private function resolveIntegrationsFromUserConfig(): array
108
    {
109
        // Default Sentry SDK integrations
110 13
        $integrations = [
111 13
            new Integration(),
112 13
            new Integration\ExceptionContextIntegration(),
113
        ];
114
115 13
        $integrationsToResolve = $this->configuration->getIntegrations();
116
117 13
        $enableDefaultTracingIntegrations = isset(
118 13
            $this->configuration
119 13
                ->getTracing()['default_integrations']
120
        )
121 11
            ? (bool)$this->configuration->getTracing()['default_integrations']
122 2
            : true;
123
124
        if (
125 13
            $enableDefaultTracingIntegrations
126 13
            && $this->configuration->couldHavePerformanceTracingEnabled()
127
        ) {
128 1
            $integrationsToResolve = array_merge(
129
                $integrationsToResolve,
130
                self::DEFAULT_INTEGRATIONS
131
            );
132
        }
133
        /** @psalm-suppress MixedAssignment */
134 13
        foreach ($integrationsToResolve as $userIntegration) {
135
            if (
136
                $userIntegration instanceof
137
                SdkIntegration\IntegrationInterface
138
            ) {
139
                $integrations[] = $userIntegration;
140
            } elseif (is_string($userIntegration)) {
141
                /** @psalm-suppress MixedAssignment */
142
                $resolvedIntegration = $this->container->get($userIntegration);
143
144
                if (
145
                    !$resolvedIntegration instanceof
146
                        SdkIntegration\IntegrationInterface
147
                ) {
148
                    if (is_array($resolvedIntegration)) {
149
                        $value = 'array';
150
                    } elseif (is_object($resolvedIntegration)) {
151
                        $value = $resolvedIntegration::class;
152
                    } elseif (null === $resolvedIntegration) {
153
                        $value = 'null';
154
                    } else {
155
                        $value = (string)$resolvedIntegration;
156
                    }
157
158
                    throw new RuntimeException(
159
                        sprintf(
160
                            'Sentry integrations must be an instance of `%s` got `%s`.',
161
                            SdkIntegration\IntegrationInterface::class,
162
                            $value
163
                        )
164
                    );
165
                }
166
167
                $integrations[] = $resolvedIntegration;
168
            } else {
169
                throw new RuntimeException(
170
                    sprintf(
171
                        'Sentry integrations must either be a valid container reference or an instance of `%s`.',
172
                        SdkIntegration\IntegrationInterface::class
173
                    )
174
                );
175
            }
176
        }
177
178 13
        return $integrations;
179
    }
180
}
181