Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.92% covered (success)
97.92%
47 / 48
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
SimilarEditorsClient
97.92% covered (success)
97.92%
47 / 48
75.00% covered (warning)
75.00%
3 / 4
10
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getEditor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSimilarEditors
97.06% covered (success)
97.06%
33 / 34
0.00% covered (danger)
0.00%
0 / 1
7
 logErrors
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\SimilarEditors;
4
5use MediaWiki\Http\HttpRequestFactory;
6use Psr\Log\LoggerInterface;
7use Status;
8
9class SimilarEditorsClient implements Client {
10
11    /**
12     * @var HttpRequestFactory
13     */
14    private $httpRequestFactory;
15
16    /**
17     * @var LoggerInterface
18     */
19    private $logger;
20
21    /**
22     * @var string
23     */
24    private $apiUrl;
25
26    /**
27     * @var string
28     */
29    private $apiUser;
30
31    /**
32     * @var string
33     */
34    private $apiPassword;
35
36    /**
37     * @param HttpRequestFactory $httpRequestFactory
38     * @param LoggerInterface $logger
39     * @param string $apiUrl
40     * @param string $apiUser
41     * @param string $apiPassword
42     */
43    public function __construct(
44        HttpRequestFactory $httpRequestFactory,
45        LoggerInterface $logger,
46        string $apiUrl,
47        string $apiUser,
48        string $apiPassword
49    ) {
50        $this->httpRequestFactory = $httpRequestFactory;
51        $this->logger = $logger;
52        $this->apiUrl = $apiUrl;
53        $this->apiUser = $apiUser;
54        $this->apiPassword = $apiPassword;
55    }
56
57    /**
58     * @inheritDoc
59     */
60    public function getEditor( string $editor ) {
61        return null;
62    }
63
64    /**
65     * @inheritDoc
66     */
67    public function getSimilarEditors( string $editor ) {
68        $request = $this->httpRequestFactory->create(
69            $this->apiUrl . '?usertext=' . urlencode( $editor ),
70            [
71                'method' => 'GET',
72                'username' => $this->apiUser,
73                'password' => $this->apiPassword
74            ],
75            __METHOD__
76        );
77
78        $status = $request->execute();
79        $requestContent = $request->getContent();
80        $json = $requestContent !== null ? json_decode( $requestContent, true ) : null;
81
82        if ( $status->isOK() ) {
83            if ( $json && isset( $json['results'] ) ) {
84                return array_map( static function ( $result ) {
85                    return new Neighbor(
86                        $result['user_text'],
87                        $result['num_edits_in_data'],
88                        $result['edit-overlap'],
89                        $result['edit-overlap-inv'],
90                        new TimeOverlap(
91                            $result['day-overlap']['cos-sim'],
92                            $result['day-overlap']['level']
93                        ),
94                        new TimeOverlap(
95                            $result['hour-overlap']['cos-sim'],
96                            $result['hour-overlap']['level']
97                        ),
98                        $result['follow-up'] ?? [] );
99                }, $json['results'] );
100            }
101        }
102
103        // Bad status, or good status but response body contains either an error or bad data
104        $this->logErrors( $status, $requestContent );
105        if ( $json && isset( $json['error-type'] ) ) {
106            return $json['error-type'];
107        }
108        return '';
109    }
110
111    /**
112     * @param Status $status
113     * @param string|null $content
114     * @return void
115     */
116    private function logErrors( $status, $content ) {
117        $this->logger->warning(
118            Status::wrap( $status )->getWikiText( false, false, 'en' ),
119            [
120                'error' => $status->getErrorsByType( 'error' ),
121                'caller' => __METHOD__,
122                'content' => $content
123            ]
124        );
125    }
126}