Passed
Pull Request — master (#19)
by
unknown
04:05 queued 01:18
created

resolveIntegrationsFromUserConfig()   B

Complexity

Conditions 11
Paths 32

Size

Total Lines 68
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 31.7525

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 42
c 1
b 0
f 0
nc 32
nop 0
dl 0
loc 68
ccs 12
cts 27
cp 0.4444
crap 31.7525
rs 7.3166

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
        $this->hub->bindClient($client);
47 13
        SentrySdk::setCurrentHub($this->hub);
48
    }
49
50
    /**
51
     * @param IntegrationInterface[] $integrations
52
     *
53
     * @return IntegrationInterface[]
54
     */
55 13
    public function prepareIntegrations(array $integrations)
56
    {
57 13
        $userIntegrations = $this->resolveIntegrationsFromUserConfig();
58 13
        if ($this->options->hasDefaultIntegrations()) {
59 13
            $integrations = array_filter(
60
                $integrations,
61 13
                static function (
62
                    SdkIntegration\IntegrationInterface $integration
63
                ): bool {
64
                    if (
65
                        $integration instanceof
66
                        SdkIntegration\ErrorListenerIntegration
67
                    ) {
68 1
                        return false;
69
                    }
70
71
                    if (
72
                        $integration instanceof
73
                        SdkIntegration\ExceptionListenerIntegration
74
                    ) {
75 1
                        return false;
76
                    }
77
78
                    if (
79
                        $integration instanceof
80
                        SdkIntegration\FatalErrorListenerIntegration
81
                    ) {
82 1
                        return false;
83
                    }
84
85
                    // We also remove the default request integration so it can be readded
86
                    // after with a Yii3 specific request fetcher. This way we can resolve
87
                    // the request from Yii3 instead of constructing it from the global state
88 13
                    return ! ($integration instanceof
89
                        SdkIntegration\RequestIntegration);
90
                }
91
            );
92
93 13
            $integrations[] = new SdkIntegration\RequestIntegration(
94 13
                new YiiRequestFetcher($this->container)
95
            );
96
        }
97
98 13
        return array_merge($integrations, $userIntegrations);
99
    }
100
101
    /**
102
     * Resolve the integrations from the user configuration with the container.
103
     *
104
     * @return SdkIntegration\IntegrationInterface[]
105
     */
106 13
    private function resolveIntegrationsFromUserConfig(): array
107
    {
108
        // Default Sentry SDK integrations
109 13
        $integrations = [
110 13
            new Integration(),
111 13
            new Integration\ExceptionContextIntegration(),
112
        ];
113
114 13
        $integrationsToResolve = $this->configuration->getIntegrations();
115
116 13
        $enableDefaultTracingIntegrations = !isset($this->configuration->getTracing()['default_integrations']) ||
117 11
            (bool)$this->configuration->getTracing()['default_integrations'];
118
119
        if (
120 13
            $enableDefaultTracingIntegrations
121 13
            && $this->configuration->couldHavePerformanceTracingEnabled()
122
        ) {
123 1
            $integrationsToResolve = array_merge(
124
                $integrationsToResolve,
125
                self::DEFAULT_INTEGRATIONS
126
            );
127
        }
128
        /** @psalm-suppress MixedAssignment */
129 13
        foreach ($integrationsToResolve as $userIntegration) {
130
            if (
131
                $userIntegration instanceof
132
                SdkIntegration\IntegrationInterface
133
            ) {
134
                $integrations[] = $userIntegration;
135
            } elseif (is_string($userIntegration)) {
136
                /** @psalm-suppress MixedAssignment */
137
                $resolvedIntegration = $this->container->get($userIntegration);
138
139
                if (
140
                    !$resolvedIntegration instanceof
141
                        SdkIntegration\IntegrationInterface
142
                ) {
143
                    if (is_array($resolvedIntegration)) {
144
                        $value = 'array';
145
                    } elseif (is_object($resolvedIntegration)) {
146
                        $value = $resolvedIntegration::class;
147
                    } elseif (null === $resolvedIntegration) {
148
                        $value = 'null';
149
                    } else {
150
                        $value = (string)$resolvedIntegration;
151
                    }
152
153
                    throw new RuntimeException(
154
                        sprintf(
155
                            'Sentry integration must be an instance of `%s` got `%s`.',
156
                            SdkIntegration\IntegrationInterface::class,
157
                            $value
158
                        )
159
                    );
160
                }
161
162
                $integrations[] = $resolvedIntegration;
163
            } else {
164
                throw new RuntimeException(
165
                    sprintf(
166
                        'Sentry integrations must either be a valid container reference or an instance of `%s`.',
167
                        SdkIntegration\IntegrationInterface::class
168
                    )
169
                );
170
            }
171
        }
172
173 13
        return $integrations;
174
    }
175
}
176