Passed
Pull Request — master (#19)
by
unknown
03:00
created

resolveIntegrationsFromUserConfig()   B

Complexity

Conditions 11
Paths 32

Size

Total Lines 68
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 22.8932

Importance

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