MDL-77917 communication_matrix: Use v1.7 upload content API

Version 1.7 of the Matrix API adds a new endpoint for uploading media.
`_matrix/media/v1/create` and adds a new path parameter to the existing
`_matrix/media/v3/upload` endpoint.
This commit is contained in:
Andrew Nicols 2023-07-11 10:24:37 +08:00
parent 914686bc5e
commit 6d1bd4787f
No known key found for this signature in database
GPG Key ID: 6D1E3157C8CFBF14
5 changed files with 150 additions and 19 deletions

View File

@ -24,6 +24,7 @@ use communication_matrix\local\spec\features\matrix\{
update_room_name_v3 as update_room_name_feature,
update_room_topic_v3 as update_room_topic_feature,
upload_content_v3 as upload_content_feature,
media_create_v1 as media_create_feature,
};
use communication_matrix\local\spec\features\synapse\{
create_user_v2 as create_user_feature,
@ -409,7 +410,7 @@ class communication_feature implements
* Update the room avatar when an instance image is added or updated.
*/
public function update_room_avatar(): void {
// Either of the following features of the remote API are required.
// Both of the following features of the remote API are required.
$this->matrixapi->require_features([
upload_content_feature::class,
update_room_avatar_feature::class,
@ -423,20 +424,37 @@ class communication_feature implements
$instanceimage = $this->processor->get_avatar();
$contenturi = null;
// If avatar is set for the instance, upload to Matrix. Otherwise, leave null for unsetting.
if (!empty($instanceimage)) {
// First upload the content.
$response = $this->matrixapi->upload_content($instanceimage);
$body = self::get_body($response);
$contenturi = $body->content_uri;
if ($this->matrixapi->implements_feature(media_create_feature::class)) {
// From version 1.7 we can fetch a mxc URI and use it before uploading the content.
if ($instanceimage) {
$response = $this->matrixapi->media_create();
$contenturi = self::get_body($response)->content_uri;
// Now update the room avatar.
$response = $this->matrixapi->update_room_avatar($this->get_room_id(), $contenturi);
// And finally upload the content.
$this->matrixapi->upload_content($instanceimage);
} else {
$response = $this->matrixapi->update_room_avatar($this->get_room_id(), null);
}
} else {
// Prior to v1.7 the only way to upload content was to upload the content, which returns a mxc URI to use.
if ($instanceimage) {
// First upload the content.
$response = $this->matrixapi->upload_content($instanceimage);
$body = self::get_body($response);
$contenturi = $body->content_uri;
}
// Now update the room avatar.
$response = $this->matrixapi->update_room_avatar($this->get_room_id(), $contenturi);
}
// Indicate the avatar has been synced if it was successfully set with Matrix.
if ($response->getReasonPhrase() === 'OK') {
$this->processor->set_avatar_synced_flag(true);
}
// Indicate the avatar has been synced if it was successfully set with Matrix.
if ($response->getReasonPhrase() === 'OK') {
$this->processor->set_avatar_synced_flag(true);
}
}

View File

@ -0,0 +1,47 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace communication_matrix\local\spec\features\matrix;
use communication_matrix\local\command;
use GuzzleHttp\Psr7\Response;
/**
* Matrix API feature to create an mxc Media URI.
*
* https://spec.matrix.org/v1.1/client-server-api/#post_matrixmediav3upload
*
* @package communication_matrix
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @codeCoverageIgnore
* This code does not warrant being tested. Testing offers no discernible benefit given its usage is tested.
*/
trait media_create_v1 {
/**
* Create a media URI.
*
* @return Response
*/
public function media_create(): Response {
return $this->execute(new command(
$this,
method: 'POST',
endpoint: '_matrix/media/v1/create',
));
}
}

View File

@ -37,23 +37,41 @@ trait upload_content_v3 {
* Upload the content in the matrix/synapse server.
*
* @param null|\stored_file $content The content to be uploaded
* @param null|string $mediaid The mediaid to associate a file with. Supported for v1.7 API an above only.
* @return Response
*/
public function upload_content(
?\stored_file $content,
?string $mediaid = null,
): Response {
$query = [];
if ($content) {
$query['filename'] = $content->get_filename();
}
$command = new command(
$this,
method: 'POST',
endpoint: '_matrix/media/v3/upload',
sendasjson: false,
query: $query,
);
if ($mediaid !== null) {
// Specification of the mediaid requires version 1.7 or above of the upload API.
// See https://spec.matrix.org/v1.7/client-server-api/#put_matrixmediav3uploadservernamemediaid.
$this->requires_version('1.7');
$command = new command(
$this,
method: 'PUT',
endpoint: '_matrix/media/v3/upload/:mediaid',
sendasjson: false,
query: $query,
params: [
'mediaid' => $mediaid,
],
);
} else {
$command = new command(
$this,
method: 'POST',
endpoint: '_matrix/media/v3/upload',
sendasjson: false,
query: $query,
);
}
if ($content) {
// Add the content-type, and header.

View File

@ -27,7 +27,9 @@ namespace communication_matrix\local\spec;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class v1p7 extends v1p6 {
// Note: A new Content Upload API was introduced, but it doesn't benefit us in any way.
// Note: A new Content Upload API was introduced.
// See details in the spec:
// https://github.com/matrix-org/matrix-spec-proposals/pull/2246.
use features\matrix\media_create_v1;
}

View File

@ -253,6 +253,16 @@ class matrix_client_test extends \advanced_testcase {
*/
public function implements_feature_provider(): array {
return [
'Basic supported feature' => [
'v1.7',
features\matrix\media_create_v1::class,
true,
],
'Basic unsupported feature' => [
'v1.6',
features\matrix\media_create_v1::class,
false,
],
'[supported] as array' => [
'v1.6',
[features\matrix\create_room_v3::class],
@ -266,6 +276,21 @@ class matrix_client_test extends \advanced_testcase {
],
true,
],
'[unsupported] as array' => [
'v1.6',
[
features\matrix\media_create_v1::class,
],
false,
],
'[unsupported, supported] as array' => [
'v1.6',
[
features\matrix\media_create_v1::class,
features\matrix\update_room_avatar_v3::class,
],
true,
],
];
}
@ -290,6 +315,27 @@ class matrix_client_test extends \advanced_testcase {
true,
];
$testcases['Require many including an unsupported feature'] = [
'v1.6',
[
features\matrix\create_room_v3::class,
features\matrix\media_create_v1::class,
],
false,
];
$testcases['Require many including an unsupported feature which has an alternate'] = [
'v1.6',
[
features\matrix\create_room_v3::class,
[
features\matrix\media_create_v1::class,
features\matrix\update_room_avatar_v3::class,
],
],
true,
];
return $testcases;
}