Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
65.71% covered (warning)
65.71%
23 / 35
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
NotificationServiceClient
65.71% covered (warning)
65.71%
23 / 35
75.00% covered (warning)
75.00%
3 / 4
14.03
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 sendCheckEchoRequests
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
6
 sendRequest
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 constructRequest
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\Notifications\Push;
4
5use MediaWiki\Http\HttpRequestFactory;
6use MediaWiki\Status\Status;
7use MWHttpRequest;
8use Psr\Log\LoggerAwareInterface;
9use Psr\Log\LoggerAwareTrait;
10
11class NotificationServiceClient implements LoggerAwareInterface {
12
13    use LoggerAwareTrait;
14
15    /** @var HttpRequestFactory */
16    private $httpRequestFactory;
17
18    /** @var string */
19    private $endpointBase;
20
21    /**
22     * @param HttpRequestFactory $httpRequestFactory
23     * @param string $endpointBase push service notification request endpoint base URL
24     */
25    public function __construct( HttpRequestFactory $httpRequestFactory, string $endpointBase ) {
26        $this->httpRequestFactory = $httpRequestFactory;
27        $this->endpointBase = $endpointBase;
28    }
29
30    /**
31     * Send a CHECK_ECHO notification request to the push service for each subscription found.
32     * TODO: Update the service to handle multiple providers in a single request (T254379)
33     * @param array $subscriptions Subscriptions for which to send the message
34     */
35    public function sendCheckEchoRequests( array $subscriptions ): void {
36        $tokenMap = [];
37        foreach ( $subscriptions as $subscription ) {
38            $provider = $subscription->getProvider();
39            $topic = $subscription->getTopic() ?? 0;
40            if ( !isset( $tokenMap[$topic][$provider] ) ) {
41                $tokenMap[$topic][$provider] = [];
42            }
43
44            $tokenMap[$topic][$provider][] = $subscription->getToken();
45        }
46        foreach ( $tokenMap as $topic => $providerMap ) {
47            foreach ( $providerMap as $provider => $tokens ) {
48                $payload = [
49                    'deviceTokens' => $tokens,
50                    'messageType' => 'checkEchoV1'
51                ];
52                if ( $topic !== 0 ) {
53                    $payload['topic'] = $topic;
54                }
55                $this->sendRequest( $provider, $payload );
56            }
57        }
58    }
59
60    /**
61     * Send a notification request for a single push provider
62     * @param string $provider Provider endpoint to which to send the message
63     * @param array $payload message payload
64     */
65    protected function sendRequest( string $provider, array $payload ): void {
66        $request = $this->constructRequest( $provider, $payload );
67        $status = $request->execute();
68        if ( !$status->isOK() ) {
69            $errors = $status->getErrorsByType( 'error' );
70            $this->logger->warning(
71                serialize( Status::wrap( $status )->getMessage( false, false, 'en' ) ),
72                [
73                    'error' => $errors,
74                    'caller' => __METHOD__,
75                    'content' => $request->getContent()
76                ]
77            );
78        }
79    }
80
81    /**
82     * Construct a MWHttpRequest object based on the subscription and payload.
83     * @param string $provider
84     * @param array $payload
85     * @return MWHttpRequest
86     */
87    private function constructRequest( string $provider, array $payload ): MWHttpRequest {
88        $url = "$this->endpointBase/$provider";
89        $opts = [ 'method' => 'POST', 'postData' => json_encode( $payload ) ];
90        $req = $this->httpRequestFactory->create( $url, $opts );
91        $req->setHeader( 'Content-Type', 'application/json; charset=utf-8' );
92        return $req;
93    }
94
95}