Discovery::request()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

Changes 0
Metric Value
cc 2
eloc 6
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 12
ccs 6
cts 7
cp 0.8571
crap 2.0116
rs 10
1
<?php
2
3
/**
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types=1);
9
10
namespace ChampsLibres\WopiLib\Service\Discovery;
11
12
use ChampsLibres\WopiLib\Contract\Service\Configuration\ConfigurationInterface;
13
use ChampsLibres\WopiLib\Contract\Service\Discovery\DiscoveryInterface;
14
use Exception;
15
use loophp\psr17\Psr17Interface;
16
use Psr\Http\Client\ClientInterface;
17
use Psr\Http\Message\ResponseInterface;
18
use SimpleXMLElement;
19
20
use const JSON_THROW_ON_ERROR;
21
22
final class Discovery implements DiscoveryInterface
23
{
24
    private ClientInterface $client;
25
26
    private ConfigurationInterface $configuration;
27
28
    private Psr17Interface $psr17;
29
30 6
    public function __construct(
31
        ConfigurationInterface $configuration,
32
        ClientInterface $client,
33
        Psr17Interface $psr17
34
    ) {
35 6
        $this->configuration = $configuration;
36 6
        $this->client = $client;
37 6
        $this->psr17 = $psr17;
38
    }
39
40 1
    public function discoverAction(string $extension, string $name = 'view'): ?array
41
    {
42
        /** @var false|SimpleXMLElement[]|null $apps */
43 1
        $apps = $this->discover()->xpath('//net-zone/app');
44
45 1
        if (false === $apps || null === $apps) {
46
            throw new Exception();
47
        }
48
49 1
        $return = [];
50
51 1
        foreach ($apps as $app) {
52
            /** @var false|SimpleXMLElement[]|null $actions */
53 1
            $actions = $app->xpath(sprintf('action[@ext="%s" and @name="%s"]', $extension, $name));
54
55 1
            if (false === $actions || null === $actions) {
56
                continue;
57
            }
58
59 1
            foreach ($actions as $action) {
60 1
                $actionAttributes = $action->attributes() ?: [];
61
62 1
                $return[] = array_merge(
63 1
                    (array) reset($actionAttributes),
64 1
                    ['app' => (string) $app['name']],
65 1
                    ['favIconUrl' => (string) $app['favIconUrl']]
66 1
                );
67
            }
68
        }
69
70 1
        return (false === $action = current($return)) ? null : $action;
71
    }
72
73 1
    public function discoverExtension(string $extension): array
74
    {
75 1
        $extensions = [];
76
77
        /** @var false|SimpleXMLElement[]|null $apps */
78 1
        $apps = $this->discover()->xpath('//net-zone/app');
79
80 1
        if (false === $apps || null === $apps) {
81
            throw new Exception();
82
        }
83
84 1
        foreach ($apps as $app) {
85
            /** @var false|SimpleXMLElement[]|null $actions */
86 1
            $actions = $app->xpath(sprintf("action[@ext='%s']", $extension));
87
88 1
            if (false === $actions || null === $actions) {
89
                continue;
90
            }
91
92 1
            foreach ($actions as $action) {
93 1
                $actionAttributes = $action->attributes() ?: [];
94
95 1
                $extensions[] = array_merge(
96 1
                    (array) reset($actionAttributes),
97 1
                    ['name' => (string) $app['name']],
98 1
                    ['favIconUrl' => (string) $app['favIconUrl']]
99 1
                );
100
            }
101
        }
102
103 1
        return $extensions;
104
    }
105
106 1
    public function discoverMimeType(string $mimeType): array
107
    {
108 1
        $mimeTypes = [];
109
110
        /** @var false|SimpleXMLElement[]|null $apps */
111 1
        $apps = $this->discover()->xpath(sprintf("//net-zone/app[@name='%s']", $mimeType));
112
113 1
        if (false === $apps || null === $apps) {
114
            throw new Exception();
115
        }
116
117 1
        foreach ($apps as $app) {
118
            /** @var false|SimpleXMLElement[]|null $actions */
119 1
            $actions = $app->xpath('action');
120
121 1
            if (false === $actions || null === $actions) {
122
                continue;
123
            }
124
125 1
            foreach ($actions as $action) {
126 1
                $actionAttributes = $action->attributes() ?: [];
127
128 1
                $mimeTypes[] = array_merge(
129 1
                    (array) reset($actionAttributes),
130 1
                    ['name' => (string) $app['name']],
131 1
                );
132
            }
133
        }
134
135 1
        return $mimeTypes;
136
    }
137
138 1
    public function getCapabilities(): array
139
    {
140 1
        $capabilities = $this->discover()->xpath("//net-zone/app[@name='Capabilities']");
141
142 1
        if (false === $capabilities = reset($capabilities)) {
143
            return [];
144
        }
145
146 1
        return json_decode(
147 1
            (string) $this->request((string) $capabilities->action['urlsrc'])->getBody(),
148 1
            true,
149 1
            512,
150 1
            JSON_THROW_ON_ERROR
151 1
        );
152
    }
153
154 1
    public function getPublicKey(): string
155
    {
156 1
        return (string) $this->discover()->xpath('//proof-key/@value')[0];
157
    }
158
159 1
    public function getPublicKeyOld(): string
160
    {
161 1
        return (string) $this->discover()->xpath('//proof-key/@oldvalue')[0];
162
    }
163
164 5
    private function discover(): SimpleXMLElement
165
    {
166 5
        $simpleXmlElement = simplexml_load_string(
167 5
            (string) $this
168 5
                ->request(
169 5
                    sprintf('%s/%s', $this->configuration['server'], 'hosting/discovery')
170 5
                )
171 5
                ->getBody()
172 5
        );
173
174 5
        if (false === $simpleXmlElement) {
175
            // TODO
176
            throw new Exception('Unable to parse XML.');
177
        }
178
179 5
        return $simpleXmlElement;
180
    }
181
182 5
    private function request(string $url): ResponseInterface
183
    {
184 5
        $response = $this
185 5
            ->client
186 5
            ->sendRequest($this->psr17->createRequest('GET', $url));
187
188 5
        if (200 !== $response->getStatusCode()) {
189
            // TODO
190
            throw new Exception('Invalid status code');
191
        }
192
193 5
        return $response;
194
    }
195
}
196