Completed
Push — master ( 2c946b...ead99e )
by Bukashk0zzz
07:40
created

AtlassianRestClient::getClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace AtlassianConnectBundle\Service;
4
5
use AtlassianConnectBundle\Entity\TenantInterface;
6
use GuzzleHttp\Client;
7
use GuzzleHttp\Handler\CurlHandler;
8
use GuzzleHttp\HandlerStack;
9
use Symfony\Component\HttpFoundation\File\UploadedFile;
10
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
11
12
/**
13
 * Class AtlassianRestClient
14
 */
15
class AtlassianRestClient
16
{
17
    /**
18
     * @var TenantInterface
19
     */
20
    private $tenant;
21
22
    /**
23
     * @var Client
24
     */
25
    private $client;
26
27
    /**
28
     * @var string|null
29
     */
30
    private $user;
31
32
    /**
33
     * @param TenantInterface|null       $tenant
34
     * @param TokenStorageInterface|null $tokenStorage
35
     */
36
    public function __construct(?TenantInterface $tenant, ?TokenStorageInterface $tokenStorage = null)
37
    {
38
        $this->setTenant($tenant, $tokenStorage);
39
        $this->client = $this->createClient();
40
    }
41
42
    /**
43
     * @return Client
44
     */
45
    public function getClient(): Client
46
    {
47
        return $this->client;
48
    }
49
50
    /**
51
     * @param UploadedFile $file
52
     * @param string       $restUrl
53
     *
54
     * @return string
55
     */
56
    public function sendFile(UploadedFile $file, string $restUrl): string
57
    {
58
        $options['headers']['X-Atlassian-Token'] = 'nocheck';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.
Loading history...
59
        $savedFile = $file->move('/tmp/', $file->getClientOriginalName());
60
61
        $options['body'] = [
62
            'file' => \fopen($savedFile->getRealPath(), 'r'),
63
        ];
64
65
        \unlink($savedFile->getRealPath());
66
67
        return $this->client->post($this->buildURL($restUrl), $options)->getBody()->getContents();
68
    }
69
70
    /**
71
     * @param string  $restUrl
72
     * @param mixed[] $json
73
     *
74
     * @return string
75
     */
76
    public function put(string $restUrl, array $json): string
77
    {
78
        $options['headers']['Content-Type'] = 'application/json';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.
Loading history...
79
        $options['json'] = $json;
80
81
        return $this->client->put($this->buildURL($restUrl), $options)->getBody()->getContents();
82
    }
83
84
    /**
85
     * @param string  $restUrl
86
     * @param mixed[] $json
87
     *
88
     * @return string
89
     */
90
    public function post(string $restUrl, array $json): string
91
    {
92
        $options['headers']['Content-Type'] = 'application/json';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.
Loading history...
93
        $options['json'] = $json;
94
95
        return $this->client->post($this->buildURL($restUrl), $options)->getBody()->getContents();
96
    }
97
98
    /**
99
     * @param string $restUrl
100
     *
101
     * @return string
102
     */
103
    public function get(string $restUrl): string
104
    {
105
        return $this->client->get($this->buildURL($restUrl))->getBody()->getContents();
106
    }
107
108
    /**
109
     * @param string $restUrl
110
     *
111
     * @return string
112
     */
113
    public function delete(string $restUrl): string
114
    {
115
        return $this->client->delete($this->buildURL($restUrl))->getBody()->getContents();
116
    }
117
118
    /**
119
     * @param string|null $user
120
     *
121
     * @return AtlassianRestClient
122
     */
123
    public function setUser(?string $user): AtlassianRestClient
124
    {
125
        $this->user = $user;
126
        $this->client = $this->createClient();
127
128
        return $this;
129
    }
130
131
    /**
132
     * @param string $restUrl
133
     *
134
     * @return string
135
     */
136
    private function buildURL(string $restUrl): string
137
    {
138
        // Jira return absolute self links, so its more easy to work with get with absolute urls in such cases
139
        if ((\mb_strpos($restUrl, 'http://') !== 0) && (\mb_strpos($restUrl, 'https://') !== 0)) {
140
            return $this->tenant->getBaseUrl().$restUrl;
141
        }
142
143
        return $restUrl;
144
    }
145
146
    /**
147
     * Create a HTTP client
148
     *
149
     * @return Client
150
     */
151
    private function createClient(): Client
152
    {
153
        $stack = new HandlerStack();
154
        $stack->setHandler(new CurlHandler());
155
156
        if ($this->user === null) {
157
            $stack->push(GuzzleJWTMiddleware::authTokenMiddleware(
158
                $this->tenant->getAddonKey(),
0 ignored issues
show
Bug introduced by
It seems like $this->tenant->getAddonKey() can also be of type null; however, parameter $issuer of AtlassianConnectBundle\S...::authTokenMiddleware() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

158
                /** @scrutinizer ignore-type */ $this->tenant->getAddonKey(),
Loading history...
159
                $this->tenant->getSharedSecret()
0 ignored issues
show
Bug introduced by
It seems like $this->tenant->getSharedSecret() can also be of type null; however, parameter $secret of AtlassianConnectBundle\S...::authTokenMiddleware() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

159
                /** @scrutinizer ignore-type */ $this->tenant->getSharedSecret()
Loading history...
160
            ));
161
        } else {
162
            $stack->push(GuzzleJWTMiddleware::authUserTokenMiddleware(
163
                $this->tenant->getOauthClientId(),
0 ignored issues
show
Bug introduced by
It seems like $this->tenant->getOauthClientId() can also be of type null; however, parameter $oauthClientId of AtlassianConnectBundle\S...thUserTokenMiddleware() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

163
                /** @scrutinizer ignore-type */ $this->tenant->getOauthClientId(),
Loading history...
164
                $this->tenant->getSharedSecret(),
0 ignored issues
show
Bug introduced by
It seems like $this->tenant->getSharedSecret() can also be of type null; however, parameter $secret of AtlassianConnectBundle\S...thUserTokenMiddleware() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

164
                /** @scrutinizer ignore-type */ $this->tenant->getSharedSecret(),
Loading history...
165
                $this->tenant->getBaseUrl(),
0 ignored issues
show
Bug introduced by
It seems like $this->tenant->getBaseUrl() can also be of type null; however, parameter $baseUrl of AtlassianConnectBundle\S...thUserTokenMiddleware() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

165
                /** @scrutinizer ignore-type */ $this->tenant->getBaseUrl(),
Loading history...
166
                $this->user
167
            ));
168
        }
169
170
        return new Client(['handler' => $stack]);
171
    }
172
173
    /**
174
     * @param TenantInterface|null       $tenant
175
     * @param TokenStorageInterface|null $tokenStorage
176
     *
177
     * @return void
178
     */
179
    private function setTenant(?TenantInterface $tenant, ?TokenStorageInterface $tokenStorage): void
180
    {
181
        if ($tenant !== null) {
182
            $this->tenant = $tenant;
183
        } elseif ($tokenStorage !== null) {
184
            $token = $tokenStorage->getToken();
185
186
            if ($token !== null) {
187
                $tenant = $token->getUser();
188
189
                if ($tenant instanceof TenantInterface) {
190
                    $this->tenant = $tenant;
191
                }
192
            }
193
        } else {
194
            throw new \RuntimeException('Can\'t get tenant');
195
        }
196
    }
197
}
198