Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.46% covered (warning)
88.46%
46 / 52
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
RecentChangeSaveHookHandler
88.46% covered (warning)
88.46%
46 / 52
50.00% covered (danger)
50.00%
2 / 4
21.68
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
 handle
84.62% covered (warning)
84.62%
11 / 13
0.00% covered (danger)
0.00%
0 / 1
8.23
 checkModel
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
8
 triggerJob
84.00% covered (warning)
84.00%
21 / 25
0.00% covered (danger)
0.00%
0 / 1
4.07
1<?php
2/**
3 * Copyright (C) 2016 Brad Jorsch <bjorsch@wikimedia.org>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19namespace ORES\Hooks;
20
21use Exception;
22use MediaWiki\MediaWikiServices;
23use MediaWiki\Request\WebRequest;
24use ORES\Services\FetchScoreJob;
25use Psr\Log\LoggerInterface;
26use RecentChange;
27
28class RecentChangeSaveHookHandler {
29
30    /**
31     * @var LoggerInterface
32     */
33    private $logger;
34
35    /**
36     * @var WebRequest
37     */
38    private $request;
39
40    /**
41     * @param LoggerInterface $logger
42     * @param WebRequest $request
43     */
44    public function __construct( LoggerInterface $logger, WebRequest $request ) {
45        $this->logger = $logger;
46        $this->request = $request;
47    }
48
49    /**
50     * @param RecentChange $rc
51     * @param array[] $modelsConfig
52     * @param bool $excludeBots
53     * @param bool[] $enabledNamespaces
54     */
55    public function handle(
56        RecentChange $rc,
57        array $modelsConfig,
58        $excludeBots,
59        array $enabledNamespaces
60    ) {
61        if ( $rc->getAttribute( 'rc_bot' ) && $excludeBots ) {
62            return;
63        }
64
65        // Check if we actually want score for this namespace
66        $ns = $rc->getAttribute( 'rc_namespace' );
67        if ( $enabledNamespaces &&
68            !( isset( $enabledNamespaces[$ns] ) && $enabledNamespaces[$ns] )
69        ) {
70            return;
71        }
72
73        $models = [];
74        foreach ( $modelsConfig as $model => $modelConfig ) {
75            $add = $this->checkModel( $rc, $modelConfig );
76            if ( $add === true ) {
77                $models[] = $model;
78            }
79        }
80
81        ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )->onORESCheckModels( $rc, $models );
82
83        $this->triggerJob( $rc, $models );
84    }
85
86    private function checkModel( RecentChange $rc, array $config ) {
87        if ( $config['enabled'] !== true ) {
88            return false;
89        }
90
91        $acceptedTypes = $config['types'] ?? [ RC_EDIT, RC_NEW ];
92        if ( !in_array( $rc->getAttribute( 'rc_type' ), $acceptedTypes ) ) {
93            return false;
94        }
95
96        $ns = $rc->getAttribute( 'rc_namespace' );
97        if ( isset( $config['namespaces'] ) && !in_array( $ns, $config['namespaces'] ) ) {
98            return false;
99        }
100
101        if ( isset( $config['excludeBots'] ) && $config['excludeBots'] !== false &&
102            $rc->getAttribute( 'rc_bot' )
103        ) {
104            return false;
105        }
106
107        return true;
108    }
109
110    private function triggerJob( RecentChange $rc, array $models ) {
111        if ( $models === [] ) {
112            return;
113        }
114
115        $revid = $rc->getAttribute( 'rc_this_oldid' );
116        $this->logger->debug( 'Processing edit {revid}', [
117            'revid' => $revid,
118        ] );
119        $ua = $this->request->getHeader( 'User-Agent' );
120        $ua = $ua !== false ? $this->request->normalizeUnicode( $ua ) : false;
121        $job = new FetchScoreJob( $rc->getTitle(), [
122            'revid' => $revid,
123            'originalRequest' => [
124                'ip' => $this->request->getIP(),
125                'userAgent' => $ua,
126            ],
127            'models' => $models,
128            'precache' => true,
129        ] );
130        try {
131            MediaWikiServices::getInstance()->getJobQueueGroup()->push( $job );
132            $this->logger->debug( 'Job pushed for {revid}', [
133                'revid' => $revid,
134            ] );
135        } catch ( Exception $e ) {
136            $this->logger->error( 'Job push failed for {revid}', [
137                'revid' => $revid,
138            ] );
139        }
140    }
141
142}