Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
ProtectionFilter
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
2 / 2
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 filter
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3namespace GrowthExperiments\NewcomerTasks;
4
5use GrowthExperiments\NewcomerTasks\Task\TaskSet;
6use MediaWiki\Cache\LinkBatchFactory;
7use MediaWiki\Title\TitleFactory;
8use Wikimedia\Rdbms\IConnectionProvider;
9
10/**
11 * Filter out protected items from a small resultset.
12 */
13class ProtectionFilter extends AbstractTaskSetFilter implements TaskSetFilter {
14
15    /** @var TitleFactory */
16    private $titleFactory;
17
18    /** @var LinkBatchFactory */
19    private $linkBatchFactory;
20
21    private IConnectionProvider $connectionProvider;
22
23    /**
24     * @param TitleFactory $titleFactory
25     * @param LinkBatchFactory $linkBatchFactory
26     * @param IConnectionProvider $connectionProvider
27     */
28    public function __construct(
29        TitleFactory $titleFactory,
30        LinkBatchFactory $linkBatchFactory,
31        IConnectionProvider $connectionProvider
32    ) {
33        $this->titleFactory = $titleFactory;
34        $this->linkBatchFactory = $linkBatchFactory;
35        $this->connectionProvider = $connectionProvider;
36    }
37
38    /** @inheritDoc */
39    public function filter( TaskSet $taskSet, int $maxLength = PHP_INT_MAX ): TaskSet {
40        // Warm title cache for fetching the IDs.
41        $linkBatch = $this->linkBatchFactory->newLinkBatch();
42        $linkBatch->setCaller( __METHOD__ );
43        foreach ( $taskSet as $task ) {
44            $linkBatch->addObj( $task->getTitle() );
45        }
46        $linkBatch->execute();
47
48        $invalidTasks = [];
49        $validTasks = [];
50
51        foreach ( $taskSet as $task ) {
52            $title = $this->titleFactory->newFromLinkTarget( $task->getTitle() );
53            $validTasks[ $title->getArticleID() ] = $task;
54        }
55        // Do a single batch query instead of several individual queries with RestrictionStore.
56        // In the longer run, adding batch querying to RestrictionStore itself would be nice.
57        $results = [];
58        if ( $validTasks ) {
59            $results = $this->connectionProvider->getReplicaDatabase()->newSelectQueryBuilder()
60                ->select( [ 'pr_page' ] )
61                ->from( 'page_restrictions' )
62                ->where( [
63                    'pr_page' => array_keys( $validTasks ),
64                    'pr_type' => 'edit'
65                ] )
66                ->caller( __METHOD__ )
67                ->fetchResultSet();
68        }
69
70        foreach ( $results as $item ) {
71            // We found restrictions, so add the task to the invalid task list, and
72            // unset it from the valid task list.
73            $invalidTasks[$item->pr_page] = $validTasks[$item->pr_page];
74            unset( $validTasks[$item->pr_page] );
75        }
76
77        $validTasks = array_slice( $validTasks, 0, $maxLength, true );
78
79        return $this->copyValidAndInvalidTasksToNewTaskSet( $taskSet, $validTasks, $invalidTasks );
80    }
81
82}