summaryrefslogtreecommitdiff
blob: f2fcfe3715cdabefc7af5d96864fdea9f0202987 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?php

namespace MediaWiki\Extension\Notifications\Push;

use MediaWiki\Http\HttpRequestFactory;
use MWHttpRequest;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Status;

class NotificationServiceClient implements LoggerAwareInterface {

	use LoggerAwareTrait;

	/** @var HttpRequestFactory */
	private $httpRequestFactory;

	/** @var string */
	private $endpointBase;

	/**
	 * @param HttpRequestFactory $httpRequestFactory
	 * @param string $endpointBase push service notification request endpoint base URL
	 */
	public function __construct( HttpRequestFactory $httpRequestFactory, string $endpointBase ) {
		$this->httpRequestFactory = $httpRequestFactory;
		$this->endpointBase = $endpointBase;
	}

	/**
	 * Send a CHECK_ECHO notification request to the push service for each subscription found.
	 * TODO: Update the service to handle multiple providers in a single request (T254379)
	 * @param array $subscriptions Subscriptions for which to send the message
	 */
	public function sendCheckEchoRequests( array $subscriptions ): void {
		$tokenMap = [];
		foreach ( $subscriptions as $subscription ) {
			$provider = $subscription->getProvider();
			$topic = $subscription->getTopic() ?? 0;
			if ( !isset( $tokenMap[$topic][$provider] ) ) {
				$tokenMap[$topic][$provider] = [];
			}

			$tokenMap[$topic][$provider][] = $subscription->getToken();
		}
		foreach ( array_keys( $tokenMap ) as $topic ) {
			foreach ( array_keys( $tokenMap[$topic] ) as $provider ) {
				$tokens = $tokenMap[$topic][$provider];
				$payload = [
					'deviceTokens' => $tokens,
					'messageType' => 'checkEchoV1'
				];
				if ( $topic !== 0 ) {
					$payload['topic'] = $topic;
				}
				$this->sendRequest( $provider, $payload );
			}
		}
	}

	/**
	 * Send a notification request for a single push provider
	 * @param string $provider Provider endpoint to which to send the message
	 * @param array $payload message payload
	 */
	protected function sendRequest( string $provider, array $payload ): void {
		$request = $this->constructRequest( $provider, $payload );
		$status = $request->execute();
		if ( !$status->isOK() ) {
			$errors = $status->getErrorsByType( 'error' );
			$this->logger->warning(
				Status::wrap( $status )->getMessage( false, false, 'en' )->serialize(),
				[
					'error' => $errors,
					'caller' => __METHOD__,
					'content' => $request->getContent()
				]
			);
		}
	}

	/**
	 * Construct a MWHttpRequest object based on the subscription and payload.
	 * @param string $provider
	 * @param array $payload
	 * @return MWHttpRequest
	 */
	private function constructRequest( string $provider, array $payload ): MWHttpRequest {
		$url = "$this->endpointBase/$provider";
		$opts = [ 'method' => 'POST', 'postData' => json_encode( $payload ) ];
		$req = $this->httpRequestFactory->create( $url, $opts );
		$req->setHeader( 'Content-Type', 'application/json; charset=utf-8' );
		return $req;
	}

}