Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.32% covered (success)
90.32%
28 / 31
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiQueryBlockInfoTrait
93.33% covered (success)
93.33%
28 / 30
50.00% covered (danger)
50.00%
1 / 2
9.02
0.00% covered (danger)
0.00%
0 / 1
 addDeletedUserFilter
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 getBlockDetailsForRows
89.47% covered (warning)
89.47%
17 / 19
0.00% covered (danger)
0.00%
0 / 1
7.06
 getDB
n/a
0 / 0
n/a
0 / 0
0
 getAuthority
n/a
0 / 0
n/a
0 / 0
0
 addTables
n/a
0 / 0
n/a
0 / 0
0
 addFields
n/a
0 / 0
n/a
0 / 0
0
 addWhere
n/a
0 / 0
n/a
0 / 0
0
 addJoinConds
n/a
0 / 0
n/a
0 / 0
0
 getQueryBuilder
n/a
0 / 0
n/a
0 / 0
0
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\Api;
8
9use MediaWiki\Block\CompositeBlock;
10use MediaWiki\Block\HideUserUtils;
11use MediaWiki\MediaWikiServices;
12use MediaWiki\Permissions\Authority;
13use stdClass;
14use Wikimedia\Rdbms\IExpression;
15use Wikimedia\Rdbms\IReadableDatabase;
16use Wikimedia\Rdbms\IResultWrapper;
17use Wikimedia\Rdbms\SelectQueryBuilder;
18
19/**
20 * @ingroup API
21 */
22trait ApiQueryBlockInfoTrait {
23    use ApiBlockInfoTrait;
24
25    /**
26     * Filter hidden users if the current user does not have the ability to
27     * view them. Also add a field hu_deleted which will be true if the user
28     * is hidden.
29     *
30     * @since 1.42
31     */
32    private function addDeletedUserFilter() {
33        // TODO: inject dependencies the way ApiWatchlistTrait does
34        $utils = MediaWikiServices::getInstance()->getHideUserUtils();
35        if ( !$this->getAuthority()->isAllowed( 'hideuser' ) ) {
36            $this->addWhere( $utils->getExpression( $this->getDB() ) );
37            // The field is always false since we are filtering out rows where it is true
38            $this->addFields( [ 'hu_deleted' => '1=0' ] );
39        } else {
40            $this->addFields( [
41                'hu_deleted' => $utils->getExpression(
42                    $this->getDB(),
43                    'user_id',
44                    HideUserUtils::HIDDEN_USERS
45                )
46            ] );
47        }
48    }
49
50    /**
51     * For a set of rows with a user_id field, get the block details for all
52     * users, and return them in array, formatted using
53     * ApiBlockInfoTrait::getBlockDetails().
54     *
55     * @since 1.42
56     * @param iterable<stdClass>|IResultWrapper $rows Rows with a user_id field
57     * @return array The block details indexed by user_id. If a user is not blocked,
58     *   the key will be absent.
59     */
60    private function getBlockDetailsForRows( $rows ) {
61        $ids = [];
62        foreach ( $rows as $row ) {
63            $ids[] = (int)$row->user_id;
64        }
65        if ( !$ids ) {
66            return [];
67        }
68
69        $blockConds = [ 'bt_user' => $ids ];
70        if ( !$this->getAuthority()->isAllowed( 'hideuser' ) ) {
71            $blockConds['bl_deleted'] = 0;
72        }
73
74        $blocks = MediaWikiServices::getInstance()->getDatabaseBlockStore()->newListFromConds( $blockConds );
75        $blocksByUser = [];
76        foreach ( $blocks as $block ) {
77            $blocksByUser[$block->getTargetUserIdentity()->getId()][] = $block;
78        }
79        $infoByUser = [];
80        foreach ( $blocksByUser as $id => $userBlocks ) {
81            if ( count( $userBlocks ) > 1 ) {
82                $maybeCompositeBlock = CompositeBlock::createFromBlocks( ...$userBlocks );
83            } else {
84                $maybeCompositeBlock = $userBlocks[0];
85            }
86            $infoByUser[$id] = $this->getBlockDetails( $maybeCompositeBlock );
87        }
88        return $infoByUser;
89    }
90
91    /***************************************************************************/
92    // region   Methods required from ApiQueryBase
93    /** @name   Methods required from ApiQueryBase */
94
95    /**
96     * @see ApiBase::getDB
97     * @return IReadableDatabase
98     */
99    abstract protected function getDB();
100
101    /**
102     * @see IContextSource::getAuthority
103     * @return Authority
104     */
105    abstract public function getAuthority();
106
107    /**
108     * @see ApiQueryBase::addTables
109     * @param string|array $tables
110     * @param string|null $alias
111     */
112    abstract protected function addTables( $tables, $alias = null );
113
114    /**
115     * @see ApiQueryBase::addFields
116     * @param array|string $fields
117     */
118    abstract protected function addFields( $fields );
119
120    /**
121     * @see ApiQueryBase::addWhere
122     * @param string|array|IExpression $conds
123     */
124    abstract protected function addWhere( $conds );
125
126    /**
127     * @see ApiQueryBase::addJoinConds
128     * @param array $conds
129     */
130    abstract protected function addJoinConds( $conds );
131
132    /**
133     * @return SelectQueryBuilder
134     */
135    abstract protected function getQueryBuilder();
136
137    // endregion -- end of methods required from ApiQueryBase
138
139}
140
141/** @deprecated class alias since 1.43 */
142class_alias( ApiQueryBlockInfoTrait::class, 'ApiQueryBlockInfoTrait' );