Passed
Push — master ( 8d8060...3598fa )
by Pol
12:31 queued 05:18
created

WopiDiscovery::getCapabilities()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 1
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 9
ccs 0
cts 3
cp 0
crap 2
rs 10
c 3
b 0
f 1
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\Discovery;
11
12
use ChampsLibres\WopiLib\Configuration\WopiConfigurationInterface;
13
use Exception;
14
use loophp\psr17\Psr17Interface;
15
use Psr\Http\Client\ClientInterface;
16
use Psr\Http\Message\ResponseInterface;
17
use SimpleXMLElement;
18
19
use const JSON_THROW_ON_ERROR;
20
21
final class WopiDiscovery implements WopiDiscoveryInterface
22
{
23
    private ClientInterface $client;
24
25
    private WopiConfigurationInterface $configuration;
26
27
    private Psr17Interface $psr17;
28
29
    public function __construct(
30
        WopiConfigurationInterface $configuration,
31
        ClientInterface $client,
32
        Psr17Interface $psr17
33
    ) {
34
        $this->configuration = $configuration;
35
        $this->client = $client;
36
        $this->psr17 = $psr17;
37
    }
38
39
    public function discoverExtension(string $extension): array
40
    {
41
        $extensions = [];
42
43
        /** @var false|SimpleXMLElement[]|null $apps */
44
        $apps = $this->discover()->xpath('//net-zone/app');
45
46
        if (false === $apps || null === $apps) {
47
            throw new Exception();
48
        }
49
50
        foreach ($apps as $app) {
51
            /** @var false|SimpleXMLElement[]|null $actions */
52
            $actions = $app->xpath(sprintf("action[@ext='%s']", $extension));
53
54
            if (false === $actions || null === $actions) {
55
                continue;
56
            }
57
58
            foreach ($actions as $action) {
59
                $actionAttributes = $action->attributes() ?: [];
60
61
                $extensions[] = array_merge(
62
                    (array) reset($actionAttributes),
63
                    ['name' => (string) $app['name']],
64
                    ['favIconUrl' => (string) $app['favIconUrl']]
65
                );
66
            }
67
        }
68
69
        return $extensions;
70
    }
71
72
    public function discoverMimeType(string $mimeType): array
73
    {
74
        $mimeTypes = [];
75
76
        /** @var false|SimpleXMLElement[]|null $apps */
77
        $apps = $this->discover()->xpath(sprintf("//net-zone/app[@name='%s']", $mimeType));
78
79
        if (false === $apps || null === $apps) {
80
            throw new Exception();
81
        }
82
83
        foreach ($apps as $app) {
84
            /** @var false|SimpleXMLElement[]|null $actions */
85
            $actions = $app->xpath('action');
86
87
            if (false === $actions || null === $actions) {
88
                continue;
89
            }
90
91
            foreach ($actions as $action) {
92
                $actionAttributes = $action->attributes() ?: [];
93
94
                $mimeTypes[] = array_merge(
95
                    (array) reset($actionAttributes),
96
                    ['name' => (string) $app['name']],
97
                );
98
            }
99
        }
100
101
        return $mimeTypes;
102
    }
103
104
    public function getCapabilities(): array
105
    {
106
        $capabilities = $this->discover()->xpath("//net-zone/app[@name='Capabilities']");
107
108
        return json_decode(
109
            (string) $this->request((string) $capabilities[0]->action['urlsrc'])->getBody(),
110
            true,
111
            512,
112
            JSON_THROW_ON_ERROR
113
        );
114
    }
115
116
    private function discover(): SimpleXMLElement
117
    {
118
        $simpleXmlElement = simplexml_load_string(
119
            (string) $this
120
                ->request(
121
                    sprintf('%s/%s', $this->configuration['server'], 'hosting/discovery')
122
                )
123
                ->getBody()
124
        );
125
126
        if (false === $simpleXmlElement) {
127
            // TODO
128
            throw new Exception('Unable to parse XML.');
129
        }
130
131
        return $simpleXmlElement;
132
    }
133
134
    private function request(string $url): ResponseInterface
135
    {
136
        $response = $this
137
            ->client
138
            ->sendRequest($this->psr17->createRequest('GET', $url));
139
140
        if (200 !== $response->getStatusCode()) {
141
            // TODO
142
            throw new Exception('Invalid status code');
143
        }
144
145
        return $response;
146
    }
147
}
148