Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
54.17% covered (warning)
54.17%
26 / 48
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiQueryBlockInfoTrait
54.17% covered (warning)
54.17%
26 / 48
33.33% covered (danger)
33.33%
1 / 3
22.65
0.00% covered (danger)
0.00%
0 / 1
 addBlockInfoToQuery
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
12
 addDeletedUserFilter
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 getBlockDetailsForRows
88.24% covered (warning)
88.24%
15 / 17
0.00% covered (danger)
0.00%
0 / 1
6.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 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21use MediaWiki\Block\CompositeBlock;
22use MediaWiki\Block\DatabaseBlock;
23use MediaWiki\Block\HideUserUtils;
24use MediaWiki\MediaWikiServices;
25use MediaWiki\Permissions\Authority;
26use Wikimedia\Rdbms\IExpression;
27use Wikimedia\Rdbms\IReadableDatabase;
28use Wikimedia\Rdbms\IResultWrapper;
29use Wikimedia\Rdbms\SelectQueryBuilder;
30
31/**
32 * @ingroup API
33 */
34trait ApiQueryBlockInfoTrait {
35    use ApiBlockInfoTrait;
36
37    /**
38     * Filters hidden users (where the user doesn't have the right to view them)
39     * Also adds relevant block information
40     *
41     * @deprecated since 1.42 use addDeletedUserFilter() or getBlockDetailsForRows()
42     * @param bool $showBlockInfo
43     * @return void
44     */
45    private function addBlockInfoToQuery( $showBlockInfo ) {
46        wfDeprecated( __METHOD__, '1.42' );
47        $db = $this->getDB();
48
49        if ( $showBlockInfo ) {
50            $queryInfo = DatabaseBlock::getQueryInfo();
51        } else {
52            $queryInfo = [
53                'tables' => [ 'ipblocks' ],
54                'fields' => [ 'ipb_deleted' ],
55                'joins' => [],
56            ];
57        }
58
59        $this->addTables( [ 'blk' => $queryInfo['tables'] ] );
60        $this->addFields( $queryInfo['fields'] );
61        $this->addJoinConds( $queryInfo['joins'] );
62        $this->addJoinConds( [
63            'blk' => [ 'LEFT JOIN', [
64                'ipb_user=user_id',
65                'ipb_expiry > ' . $db->addQuotes( $db->timestamp() ),
66            ] ],
67        ] );
68
69        // Don't show hidden names
70        if ( !$this->getAuthority()->isAllowed( 'hideuser' ) ) {
71            $this->addWhere( [ 'ipb_deleted' => [ 0, null ] ] );
72        }
73    }
74
75    /**
76     * Filter hidden users if the current user does not have the ability to
77     * view them. Also add a field hu_deleted which will be true if the user
78     * is hidden.
79     *
80     * @since 1.42
81     */
82    private function addDeletedUserFilter() {
83        // TODO: inject dependencies the way ApiWatchlistTrait does
84        $utils = MediaWikiServices::getInstance()->getHideUserUtils();
85        if ( !$this->getAuthority()->isAllowed( 'hideuser' ) ) {
86            $this->addWhere( $utils->getExpression( $this->getDB() ) );
87            // The field is always false since we are filtering out rows where it is true
88            $this->addFields( [ 'hu_deleted' => '1=0' ] );
89        } else {
90            $this->addFields( [
91                'hu_deleted' => $utils->getExpression(
92                    $this->getDB(),
93                    'user_id',
94                    HideUserUtils::HIDDEN_USERS
95                )
96            ] );
97        }
98    }
99
100    /**
101     * For a set of rows with a user_id field, get the block details for all
102     * users, and return them in array, formatted using
103     * ApiBlockInfoTrait::getBlockDetails().
104     *
105     * @since 1.42
106     * @param iterable<stdClass>|IResultWrapper $rows Rows with a user_id field
107     * @return array The block details indexed by user_id. If a user is not blocked,
108     *   the key will be absent.
109     */
110    private function getBlockDetailsForRows( $rows ) {
111        $ids = [];
112        foreach ( $rows as $row ) {
113            $ids[] = (int)$row->user_id;
114        }
115        if ( !$ids ) {
116            return [];
117        }
118        $blocks = MediaWikiServices::getInstance()->getDatabaseBlockStore()
119            ->newListFromConds( [ 'bt_user' => $ids ] );
120        $blocksByUser = [];
121        foreach ( $blocks as $block ) {
122            $blocksByUser[$block->getTargetUserIdentity()->getId()][] = $block;
123        }
124        $infoByUser = [];
125        foreach ( $blocksByUser as $id => $userBlocks ) {
126            if ( count( $userBlocks ) > 1 ) {
127                $maybeCompositeBlock = CompositeBlock::createFromBlocks( ...$userBlocks );
128            } else {
129                $maybeCompositeBlock = $userBlocks[0];
130            }
131            $infoByUser[$id] = $this->getBlockDetails( $maybeCompositeBlock );
132        }
133        return $infoByUser;
134    }
135
136    /***************************************************************************/
137    // region   Methods required from ApiQueryBase
138    /** @name   Methods required from ApiQueryBase */
139
140    /**
141     * @see ApiBase::getDB
142     * @return IReadableDatabase
143     */
144    abstract protected function getDB();
145
146    /**
147     * @see IContextSource::getAuthority
148     * @return Authority
149     */
150    abstract public function getAuthority();
151
152    /**
153     * @see ApiQueryBase::addTables
154     * @param string|array $tables
155     * @param string|null $alias
156     */
157    abstract protected function addTables( $tables, $alias = null );
158
159    /**
160     * @see ApiQueryBase::addFields
161     * @param array|string $fields
162     */
163    abstract protected function addFields( $fields );
164
165    /**
166     * @see ApiQueryBase::addWhere
167     * @param string|array|IExpression $conds
168     */
169    abstract protected function addWhere( $conds );
170
171    /**
172     * @see ApiQueryBase::addJoinConds
173     * @param array $conds
174     */
175    abstract protected function addJoinConds( $conds );
176
177    /**
178     * @return SelectQueryBuilder
179     */
180    abstract protected function getQueryBuilder();
181
182    // endregion -- end of methods required from ApiQueryBase
183
184}