Skip to content

Commit

Permalink
Issue CollaboraOnline#56: Split raw xml loading into separate service.
Browse files Browse the repository at this point in the history
  • Loading branch information
donquixote committed Nov 14, 2024
1 parent f2bbd54 commit e13a51d
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 99 deletions.
1 change: 1 addition & 0 deletions collabora_online.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ services:
logger.channel.collabora_online:
parent: logger.channel_base
arguments: ['cool']
Drupal\collabora_online\Cool\CoolDiscoveryXmlEndpoint: { }
Drupal\collabora_online\Cool\CoolRequest: { }
133 changes: 133 additions & 0 deletions src/Cool/CoolDiscoveryXmlEndpoint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

declare(strict_types=1);

/*
* Copyright the Collabora Online contributors.
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

namespace Drupal\collabora_online\Cool;

use Drupal\collabora_online\Exception\CoolRequestException;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\RequestOptions;
use Psr\Http\Client\ClientExceptionInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\RequestStack;

/**
* Service to load the discovery.xml from the Collabora server.
*/
class CoolDiscoveryXmlEndpoint {

/**
* Constructor.
*
* @param \Drupal\Core\Logger\LoggerChannelInterface $logger
* Logger channel.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* Config factory.
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
* Request stack.
* @param \GuzzleHttp\ClientInterface $client
* Http client.
*/
public function __construct(
#[Autowire(service: 'logger.channel.collabora_online')]
protected readonly LoggerChannelInterface $logger,
protected readonly ConfigFactoryInterface $configFactory,
protected readonly RequestStack $requestStack,
protected readonly ClientInterface $client,
) {}

/**
* Loads the WOPI server url from configuration.
*
* @throws \Drupal\collabora_online\Exception\CoolRequestException
* The WOPI server url is misconfigured, or the protocol does not match
* that of the current Drupal request.
*/
protected function getWopiClientServerBaseUrl(): string {
$cool_settings = $this->configFactory->get('collabora_online.settings')->get('cool');
if (!$cool_settings) {
throw new CoolRequestException(
'The Collabora Online connection is not configured.',
// Use the same code as was previously used in this case.
201,
);
}
$wopi_client_server = $cool_settings['server'] ?? NULL;
if (!$wopi_client_server) {
throw new CoolRequestException(
'The configured Collabora Online server address is empty.',
201,
);
}
$wopi_client_server = trim($wopi_client_server);

if (!preg_match('@^https?://@', $wopi_client_server)) {
throw new CoolRequestException(
sprintf(
"The configured Collabora Online server address must begin with 'http://' or 'https://'. Found '%s'.",
$wopi_client_server,
),
204,
);
}

return $wopi_client_server;
}

/**
* Gets the contents of discovery.xml from the Collabora server.
*
* @return string
* The full contents of discovery.xml.
*
* @throws \Drupal\collabora_online\Exception\CoolRequestException
* The client url cannot be retrieved.
*/
public function getDiscoveryXml(): string {
$discovery_url = $this->getWopiClientServerBaseUrl() . '/hosting/discovery';

$cool_settings = $this->configFactory->get('collabora_online.settings')->get('cool');
if (!$cool_settings) {
throw new CoolRequestException(
'The Collabora Online connection is not configured.',
// Use the same code as was previously used in this case.
203,
);
}
$disable_checks = !empty($cool_settings['disable_cert_check']);

try {
$response = $this->client->get($discovery_url, [
RequestOptions::VERIFY => !$disable_checks,
]);
$xml = $response->getBody()->getContents();
}
catch (ClientExceptionInterface $e) {
// The backtrace of a client exception is typically not very
// interesting. Just log the message.
$this->logger->error("Failed to fetch from '@url': @message.", [
'@url' => $discovery_url,
'@message' => $e->getMessage(),
]);
throw new CoolRequestException(
'Not able to retrieve the discovery.xml file from the Collabora Online server.',
203,
$e,
);
}
return $xml;
}

}
103 changes: 4 additions & 99 deletions src/Cool/CoolRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@
namespace Drupal\collabora_online\Cool;

use Drupal\collabora_online\Exception\CoolRequestException;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\RequestOptions;
use Psr\Http\Client\ClientExceptionInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

/**
* Service to fetch a WOPI client url.
Expand All @@ -28,18 +22,11 @@ class CoolRequest {
/**
* Constructor.
*
* @param \Drupal\Core\Logger\LoggerChannelInterface $logger
* Logger channel.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* Config factory.
* @param \GuzzleHttp\ClientInterface $client
* Http client.
* @param \Drupal\collabora_online\Cool\CoolDiscoveryXmlEndpoint $discoveryXmlEndpoint
* Service to load the discovery.xml from the Collabora server.
*/
public function __construct(
#[Autowire(service: 'logger.channel.collabora_online')]
protected readonly LoggerChannelInterface $logger,
protected readonly ConfigFactoryInterface $configFactory,
protected readonly ClientInterface $client,
protected readonly CoolDiscoveryXmlEndpoint $discoveryXmlEndpoint,
) {}

/**
Expand All @@ -56,7 +43,7 @@ public function __construct(
* The client url cannot be retrieved.
*/
public function getWopiClientURL(string $mimetype = 'text/plain'): string {
$discovery = $this->getDiscoveryXml();
$discovery = $this->discoveryXmlEndpoint->getDiscoveryXml();

$discovery_parsed = simplexml_load_string($discovery);
if (!$discovery_parsed) {
Expand All @@ -71,88 +58,6 @@ public function getWopiClientURL(string $mimetype = 'text/plain'): string {
return $wopi_src;
}

/**
* Loads the WOPI server url from configuration.
*
* @throws \Drupal\collabora_online\Exception\CoolRequestException
* The WOPI server url is misconfigured, or the protocol does not match
* that of the current Drupal request.
*/
protected function getWopiClientServerBaseUrl(): string {
$cool_settings = $this->configFactory->get('collabora_online.settings')->get('cool');
if (!$cool_settings) {
throw new CoolRequestException(
'The Collabora Online connection is not configured.',
// Use the same code as was previously used in this case.
201,
);
}
$wopi_client_server = $cool_settings['server'] ?? NULL;
if (!$wopi_client_server) {
throw new CoolRequestException(
'The configured Collabora Online server address is empty.',
201,
);
}
$wopi_client_server = trim($wopi_client_server);

if (!preg_match('@^https?://@', $wopi_client_server)) {
throw new CoolRequestException(
sprintf(
"The configured Collabora Online server address must begin with 'http://' or 'https://'. Found '%s'.",
$wopi_client_server,
),
204,
);
}

return $wopi_client_server;
}

/**
* Gets the contents of discovery.xml from the Collabora server.
*
* @return string
* The full contents of discovery.xml.
*
* @throws \Drupal\collabora_online\Exception\CoolRequestException
* The client url cannot be retrieved.
*/
protected function getDiscoveryXml(): string {
$discovery_url = $this->getWopiClientServerBaseUrl() . '/hosting/discovery';

$cool_settings = $this->configFactory->get('collabora_online.settings')->get('cool');
if (!$cool_settings) {
throw new CoolRequestException(
'The Collabora Online connection is not configured.',
// Use the same code as was previously used in this case.
203,
);
}
$disable_checks = !empty($cool_settings['disable_cert_check']);

try {
$response = $this->client->get($discovery_url, [
RequestOptions::VERIFY => !$disable_checks,
]);
$xml = $response->getBody()->getContents();
}
catch (ClientExceptionInterface $e) {
// The backtrace of a client exception is typically not very
// interesting. Just log the message.
$this->logger->error("Failed to fetch from '@url': @message.", [
'@url' => $discovery_url,
'@message' => $e->getMessage(),
]);
throw new CoolRequestException(
'Not able to retrieve the discovery.xml file from the Collabora Online server.',
203,
$e,
);
}
return $xml;
}

/**
* Extracts a WOPI url from the parsed discovery.xml.
*
Expand Down

0 comments on commit e13a51d

Please sign in to comment.