File: ConsequencesLookup.php

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (129 lines) | stat: -rw-r--r-- 3,501 bytes parent folder | download | duplicates (2)
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php

namespace MediaWiki\Extension\AbuseFilter\Consequences;

use MediaWiki\Extension\AbuseFilter\CentralDBManager;
use MediaWiki\Extension\AbuseFilter\GlobalNameUtils;
use Psr\Log\LoggerInterface;
use Wikimedia\Rdbms\IReadableDatabase;
use Wikimedia\Rdbms\LBFactory;

/**
 * Class for retrieving actions and parameters from the database
 * @todo Can we better integrate this with FilterLookup?
 */
class ConsequencesLookup {
	public const SERVICE_NAME = 'AbuseFilterConsequencesLookup';

	/** @var LBFactory */
	private $lbFactory;
	/** @var CentralDBManager */
	private $centralDBManager;
	/** @var ConsequencesRegistry */
	private $consequencesRegistry;
	/** @var LoggerInterface */
	private $logger;

	/**
	 * @param LBFactory $lbFactory
	 * @param CentralDBManager $centralDBManager
	 * @param ConsequencesRegistry $consequencesRegistry
	 * @param LoggerInterface $logger
	 */
	public function __construct(
		LBFactory $lbFactory,
		CentralDBManager $centralDBManager,
		ConsequencesRegistry $consequencesRegistry,
		LoggerInterface $logger
	) {
		$this->lbFactory = $lbFactory;
		$this->centralDBManager = $centralDBManager;
		$this->consequencesRegistry = $consequencesRegistry;
		$this->logger = $logger;
	}

	/**
	 * @param array<int|string> $filters
	 * @return array[][]
	 */
	public function getConsequencesForFilters( array $filters ): array {
		$globalFilters = [];
		$localFilters = [];

		foreach ( $filters as $filter ) {
			[ $filterID, $global ] = GlobalNameUtils::splitGlobalName( $filter );

			if ( $global ) {
				$globalFilters[] = $filterID;
			} else {
				$localFilters[] = (int)$filter;
			}
		}

		// Load local filter info
		$dbr = $this->lbFactory->getReplicaDatabase();
		// Retrieve the consequences.
		$consequences = [];

		if ( count( $localFilters ) ) {
			$consequences = $this->loadConsequencesFromDB( $dbr, $localFilters );
		}

		if ( count( $globalFilters ) ) {
			$consequences += $this->loadConsequencesFromDB(
				$this->centralDBManager->getConnection( DB_REPLICA ),
				$globalFilters,
				GlobalNameUtils::GLOBAL_FILTER_PREFIX
			);
		}

		return $consequences;
	}

	/**
	 * @param IReadableDatabase $dbr
	 * @param int[] $filters
	 * @param string $prefix
	 * @return array[][]
	 */
	private function loadConsequencesFromDB( IReadableDatabase $dbr, array $filters, string $prefix = '' ): array {
		$actionsByFilter = [];
		foreach ( $filters as $filter ) {
			$actionsByFilter[$prefix . $filter] = [];
		}

		$res = $dbr->newSelectQueryBuilder()
			->select( '*' )
			->from( 'abuse_filter_action' )
			->leftJoin( 'abuse_filter', null, 'afa_filter=af_id' )
			->where( [ 'af_id' => $filters ] )
			->caller( __METHOD__ )
			->fetchResultSet();

		$dangerousActions = $this->consequencesRegistry->getDangerousActionNames();
		// Categorise consequences by filter.
		foreach ( $res as $row ) {
			if ( $row->af_throttled
				&& in_array( $row->afa_consequence, $dangerousActions )
			) {
				// Don't do the action, just log
				$this->logger->info(
					'Filter {filter_id} is throttled, skipping action: {action}',
					[
						'filter_id' => $row->af_id,
						'action' => $row->afa_consequence
					]
				);
			} elseif ( $row->afa_filter !== $row->af_id ) {
				// We probably got a NULL, as it's a LEFT JOIN. Don't add it.
				continue;
			} else {
				$actionsByFilter[$prefix . $row->afa_filter][$row->afa_consequence] =
					$row->afa_parameters !== '' ? explode( "\n", $row->afa_parameters ) : [];
			}
		}

		return $actionsByFilter;
	}

}