Test Failed
Pull Request — master (#19)
by
unknown
04:55 queued 02:17
created

resolveIntegrationsFromUserConfig()   B

Complexity

Conditions 11
Paths 32

Size

Total Lines 68
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 42
nc 32
nop 0
dl 0
loc 68
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 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
    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
    public function bootstrap(): void
36
    {
37
        $this->options->setIntegrations(fn (array $integrations) => $this->prepareIntegrations($integrations));
38
39
        $clientBuilder = new ClientBuilder($this->options);
40
        $clientBuilder
41
            ->setTransportFactory($this->transportFactory)
42
            ->setLogger($this->logger);
43
44
        $client = $clientBuilder->getClient();
45
46
        $this->hub->bindClient($client);
47
        SentrySdk::setCurrentHub($this->hub);
48
    }
49
50
    /**
51
     * @param IntegrationInterface[] $integrations
52
     *
53
     * @return IntegrationInterface[]
54
     */
55
    public function prepareIntegrations(array $integrations): void
56
    {
57
        $userIntegrations = $this->resolveIntegrationsFromUserConfig();
58
        if ($this->options->hasDefaultIntegrations()) {
59
            $integrations = array_filter(
60
                $integrations,
61
                static function (
62
                    SdkIntegration\IntegrationInterface $integration
63
                ): bool {
64
                    if (
65
                        $integration instanceof SdkIntegration\ErrorListenerIntegration ||
66
                        $integration instanceof SdkIntegration\ExceptionListenerIntegration ||
67
                        $integration instanceof SdkIntegration\FatalErrorListenerIntegration ||
68
                        // We also remove the default request integration so it can be readded after with a Yii3
69
                        // specific request fetcher. This way we can resolve the request from Yii3 instead of
70
                        // constructing it from the global state.
71
                        $integration instanceof SdkIntegration\RequestIntegration
72
                    ) {
73
                        return false;
74
                    }
0 ignored issues
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 65 is false. This is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
75
                }
76
            );
77
78
            $integrations[] = new SdkIntegration\RequestIntegration(
79
                new YiiRequestFetcher($this->container)
80
            );
81
        }
82
83
        return array_merge($integrations, $userIntegrations);
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_merge($inte...ons, $userIntegrations) returns the type array which is incompatible with the type-hinted return void.
Loading history...
84
    }
85
86
    /**
87
     * Resolve the integrations from the user configuration with the container.
88
     *
89
     * @return SdkIntegration\IntegrationInterface[]
90
     */
91
    private function resolveIntegrationsFromUserConfig(): array
92
    {
93
        // Default Sentry SDK integrations
94
        $integrations = [
95
            new Integration(),
96
            new Integration\ExceptionContextIntegration(),
97
        ];
98
99
        $integrationsToResolve = $this->configuration->getIntegrations();
100
101
        $enableDefaultTracingIntegrations = !isset($this->configuration->getTracing()['default_integrations']) ||
102
            (bool)$this->configuration->getTracing()['default_integrations'];
103
104
        if (
105
            $enableDefaultTracingIntegrations
106
            && $this->configuration->couldHavePerformanceTracingEnabled()
107
        ) {
108
            $integrationsToResolve = array_merge(
109
                $integrationsToResolve,
110
                self::DEFAULT_INTEGRATIONS
111
            );
112
        }
113
        /** @psalm-suppress MixedAssignment */
114
        foreach ($integrationsToResolve as $userIntegration) {
115
            if (
116
                $userIntegration instanceof
117
                SdkIntegration\IntegrationInterface
118
            ) {
119
                $integrations[] = $userIntegration;
120
            } elseif (is_string($userIntegration)) {
121
                /** @psalm-suppress MixedAssignment */
122
                $resolvedIntegration = $this->container->get($userIntegration);
123
124
                if (
125
                    !$resolvedIntegration instanceof
126
                        SdkIntegration\IntegrationInterface
127
                ) {
128
                    if (is_array($resolvedIntegration)) {
129
                        $value = 'array';
130
                    } elseif (is_object($resolvedIntegration)) {
131
                        $value = $resolvedIntegration::class;
132
                    } elseif (null === $resolvedIntegration) {
133
                        $value = 'null';
134
                    } else {
135
                        $value = (string)$resolvedIntegration;
136
                    }
137
138
                    throw new RuntimeException(
139
                        sprintf(
140
                            'Sentry integration must be an instance of `%s` got `%s`.',
141
                            SdkIntegration\IntegrationInterface::class,
142
                            $value
143
                        )
144
                    );
145
                }
146
147
                $integrations[] = $resolvedIntegration;
148
            } else {
149
                throw new RuntimeException(
150
                    sprintf(
151
                        'Sentry integration must either be a valid container reference or an instance of `%s`.',
152
                        SdkIntegration\IntegrationInterface::class
153
                    )
154
                );
155
            }
156
        }
157
158
        return $integrations;
159
    }
160
}
161