Passed
Push — master ( d8dbb6...192136 )
by Pol
01:46
created

WopiDiscovery   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Test Coverage

Coverage 89.47%

Importance

Changes 4
Bugs 0 Features 1
Metric Value
eloc 56
dl 0
loc 125
ccs 51
cts 57
cp 0.8947
rs 10
c 4
b 0
f 1
wmc 22

6 Methods

Rating   Name   Duplication   Size   Complexity  
A discover() 0 16 2
A __construct() 0 8 1
B discoverExtension() 0 31 8
A getCapabilities() 0 9 1
A request() 0 12 2
B discoverMimeType() 0 30 8
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 4
    public function __construct(
30
        WopiConfigurationInterface $configuration,
31
        ClientInterface $client,
32
        Psr17Interface $psr17
33
    ) {
34 4
        $this->configuration = $configuration;
35 4
        $this->client = $client;
36 4
        $this->psr17 = $psr17;
37 4
    }
38
39 1
    public function discoverExtension(string $extension): array
40
    {
41 1
        $extensions = [];
42
43
        /** @var false|SimpleXMLElement[]|null $apps */
44 1
        $apps = $this->discover()->xpath('//net-zone/app');
45
46 1
        if (false === $apps || null === $apps) {
47
            throw new Exception();
48
        }
49
50 1
        foreach ($apps as $app) {
51
            /** @var false|SimpleXMLElement[]|null $actions */
52 1
            $actions = $app->xpath(sprintf("action[@ext='%s']", $extension));
53
54 1
            if (false === $actions || null === $actions) {
55
                continue;
56
            }
57
58 1
            foreach ($actions as $action) {
59 1
                $actionAttributes = $action->attributes() ?: [];
60
61 1
                $extensions[] = array_merge(
62 1
                    (array) reset($actionAttributes),
63 1
                    ['name' => (string) $app['name']],
64 1
                    ['favIconUrl' => (string) $app['favIconUrl']]
65
                );
66
            }
67
        }
68
69 1
        return $extensions;
70
    }
71
72 1
    public function discoverMimeType(string $mimeType): array
73
    {
74 1
        $mimeTypes = [];
75
76
        /** @var false|SimpleXMLElement[]|null $apps */
77 1
        $apps = $this->discover()->xpath(sprintf("//net-zone/app[@name='%s']", $mimeType));
78
79 1
        if (false === $apps || null === $apps) {
80
            throw new Exception();
81
        }
82
83 1
        foreach ($apps as $app) {
84
            /** @var false|SimpleXMLElement[]|null $actions */
85 1
            $actions = $app->xpath('action');
86
87 1
            if (false === $actions || null === $actions) {
88
                continue;
89
            }
90
91 1
            foreach ($actions as $action) {
92 1
                $actionAttributes = $action->attributes() ?: [];
93
94 1
                $mimeTypes[] = array_merge(
95 1
                    (array) reset($actionAttributes),
96 1
                    ['name' => (string) $app['name']],
97
                );
98
            }
99
        }
100
101 1
        return $mimeTypes;
102
    }
103
104 1
    public function getCapabilities(): array
105
    {
106 1
        $capabilities = $this->discover()->xpath("//net-zone/app[@name='Capabilities']");
107
108 1
        return json_decode(
109 1
            (string) $this->request((string) $capabilities[0]->action['urlsrc'])->getBody(),
110 1
            true,
111 1
            512,
112 1
            JSON_THROW_ON_ERROR
113
        );
114
    }
115
116 3
    private function discover(): SimpleXMLElement
117
    {
118 3
        $simpleXmlElement = simplexml_load_string(
119
            (string) $this
120 3
                ->request(
121 3
                    sprintf('%s/%s', $this->configuration['server'], 'hosting/discovery')
122
                )
123 3
                ->getBody()
124
        );
125
126 3
        if (false === $simpleXmlElement) {
127
            // TODO
128
            throw new Exception('Unable to parse XML.');
129
        }
130
131 3
        return $simpleXmlElement;
132
    }
133
134 3
    private function request(string $url): ResponseInterface
135
    {
136
        $response = $this
137 3
            ->client
138 3
            ->sendRequest($this->psr17->createRequest('GET', $url));
139
140 3
        if (200 !== $response->getStatusCode()) {
141
            // TODO
142
            throw new Exception('Invalid status code');
143
        }
144
145 3
        return $response;
146
    }
147
}
148