Passed
Push — master ( 2df2dd...fa75b2 )
by Pol
02:00
created

Discovery::discoverExtension()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 31
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 8.125

Importance

Changes 0
Metric Value
cc 8
eloc 15
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 31
ccs 14
cts 16
cp 0.875
crap 8.125
rs 8.4444
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 5
    public function __construct(
31
        ConfigurationInterface $configuration,
32
        ClientInterface $client,
33
        Psr17Interface $psr17
34
    ) {
35 5
        $this->configuration = $configuration;
36 5
        $this->client = $client;
37 5
        $this->psr17 = $psr17;
38 5
    }
39
40 1
    public function discoverExtension(string $extension): array
41
    {
42 1
        $extensions = [];
43
44
        /** @var false|SimpleXMLElement[]|null $apps */
45 1
        $apps = $this->discover()->xpath('//net-zone/app');
46
47 1
        if (false === $apps || null === $apps) {
48
            throw new Exception();
49
        }
50
51 1
        foreach ($apps as $app) {
52
            /** @var false|SimpleXMLElement[]|null $actions */
53 1
            $actions = $app->xpath(sprintf("action[@ext='%s']", $extension));
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
                $extensions[] = array_merge(
63 1
                    (array) reset($actionAttributes),
64 1
                    ['name' => (string) $app['name']],
65 1
                    ['favIconUrl' => (string) $app['favIconUrl']]
66
                );
67
            }
68
        }
69
70 1
        return $extensions;
71
    }
72
73 1
    public function discoverMimeType(string $mimeType): array
74
    {
75 1
        $mimeTypes = [];
76
77
        /** @var false|SimpleXMLElement[]|null $apps */
78 1
        $apps = $this->discover()->xpath(sprintf("//net-zone/app[@name='%s']", $mimeType));
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('action');
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
                $mimeTypes[] = array_merge(
96 1
                    (array) reset($actionAttributes),
97 1
                    ['name' => (string) $app['name']],
98
                );
99
            }
100
        }
101
102 1
        return $mimeTypes;
103
    }
104
105 1
    public function getCapabilities(): array
106
    {
107 1
        $capabilities = $this->discover()->xpath("//net-zone/app[@name='Capabilities']");
108
109 1
        if (false === $capabilities = reset($capabilities)) {
110
            return [];
111
        }
112
113 1
        return json_decode(
114 1
            (string) $this->request((string) $capabilities->action['urlsrc'])->getBody(),
115 1
            true,
116 1
            512,
117 1
            JSON_THROW_ON_ERROR
118
        );
119
    }
120
121 1
    public function getPublicKey(): string
122
    {
123 1
        return (string) $this->discover()->xpath('//proof-key/@value')[0];
124
    }
125
126 1
    public function getPublicKeyOld(): string
127
    {
128 1
        return (string) $this->discover()->xpath('//proof-key/@oldvalue')[0];
129
    }
130
131 4
    private function discover(): SimpleXMLElement
132
    {
133 4
        $simpleXmlElement = simplexml_load_string(
134
            (string) $this
135 4
                ->request(
136 4
                    sprintf('%s/%s', $this->configuration['server'], 'hosting/discovery')
137
                )
138 4
                ->getBody()
139
        );
140
141 4
        if (false === $simpleXmlElement) {
142
            // TODO
143
            throw new Exception('Unable to parse XML.');
144
        }
145
146 4
        return $simpleXmlElement;
147
    }
148
149 4
    private function request(string $url): ResponseInterface
150
    {
151
        $response = $this
152 4
            ->client
153 4
            ->sendRequest($this->psr17->createRequest('GET', $url));
154
155 4
        if (200 !== $response->getStatusCode()) {
156
            // TODO
157
            throw new Exception('Invalid status code');
158
        }
159
160 4
        return $response;
161
    }
162
}
163