Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 43 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
HideUserUtils | |
0.00% |
0 / 43 |
|
0.00% |
0 / 3 |
56 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getExpression | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
20 | |||
addFieldToBuilder | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Block; |
4 | |
5 | use Wikimedia\Rdbms\IReadableDatabase; |
6 | use Wikimedia\Rdbms\SelectQueryBuilder; |
7 | |
8 | /** |
9 | * Helpers for building queries that determine whether a user is hidden |
10 | * @since 1.42 |
11 | */ |
12 | class HideUserUtils { |
13 | /** |
14 | * Select users that are not hidden |
15 | */ |
16 | public const SHOWN_USERS = 1; |
17 | |
18 | /** |
19 | * Select users that are hidden |
20 | */ |
21 | public const HIDDEN_USERS = 2; |
22 | |
23 | /** @var int */ |
24 | private $readStage; |
25 | |
26 | public function __construct( $blockTargetMigrationStage ) { |
27 | $this->readStage = $blockTargetMigrationStage & SCHEMA_COMPAT_READ_MASK; |
28 | } |
29 | |
30 | /** |
31 | * Get an SQL expression suitable for use in WHERE clause which will be |
32 | * true for either hidden or non-hidden users as specified. |
33 | * |
34 | * The expression will contain a subquery. |
35 | * |
36 | * @param IReadableDatabase $dbr |
37 | * @param string $userIdField The field to be used as the user_id when |
38 | * joining on block/ipblocks. Defaults to "user_id". |
39 | * @param int $status Either self::SHOWN_USERS or self::HIDDEN_USERS |
40 | * depending on what sort of user you want to match. |
41 | * @return string |
42 | */ |
43 | public function getExpression( |
44 | IReadableDatabase $dbr, |
45 | string $userIdField = 'user_id', |
46 | $status = self::SHOWN_USERS |
47 | ) { |
48 | if ( $this->readStage === SCHEMA_COMPAT_READ_OLD ) { |
49 | $cond = $status === self::HIDDEN_USERS ? '' : 'NOT '; |
50 | $cond .= 'EXISTS (' . |
51 | $dbr->newSelectQueryBuilder() |
52 | ->select( '1' ) |
53 | ->from( 'ipblocks', 'hu_ipblocks' ) |
54 | ->where( [ "hu_ipblocks.ipb_user=$userIdField", 'hu_ipblocks.ipb_deleted' => 1 ] ) |
55 | ->caller( __METHOD__ ) |
56 | ->getSQL() . |
57 | ')'; |
58 | } else { |
59 | // Use a scalar subquery, not IN/EXISTS, to avoid materialization (T360160) |
60 | $cond = '(' . |
61 | $dbr->newSelectQueryBuilder() |
62 | ->select( '1' ) |
63 | // $userIdField may be e.g. block_target.bt_user so an inner table |
64 | // alias is necessary to ensure that that refers to the outer copy |
65 | // of the block_target table. |
66 | ->from( 'block_target', 'hu_block_target' ) |
67 | ->join( 'block', 'hu_block', 'hu_block.bl_target=hu_block_target.bt_id' ) |
68 | ->where( [ "hu_block_target.bt_user=$userIdField", 'hu_block.bl_deleted' => 1 ] ) |
69 | ->caller( __METHOD__ ) |
70 | ->getSQL() . |
71 | ') ' . |
72 | ( $status === self::HIDDEN_USERS ? 'IS NOT NULL' : 'IS NULL' ); |
73 | } |
74 | return $cond; |
75 | } |
76 | |
77 | /** |
78 | * Add a field and related joins to the query builder. The field in the |
79 | * query result will be true if the user is hidden or false otherwise. |
80 | * |
81 | * Note that a GROUP BY option will be set, to avoid duplicating the result |
82 | * row if the user is hidden by more than one block. |
83 | * |
84 | * @param SelectQueryBuilder $qb The query builder to be modified |
85 | * @param string $userIdField The name of the user_id field to use in the join |
86 | * @param string $deletedFieldAlias The field alias which will contain the |
87 | * true if the user is deleted. |
88 | */ |
89 | public function addFieldToBuilder( |
90 | SelectQueryBuilder $qb, |
91 | $userIdField = 'user_id', |
92 | $deletedFieldAlias = 'hu_deleted' |
93 | ) { |
94 | if ( $this->readStage === SCHEMA_COMPAT_READ_OLD ) { |
95 | $qb |
96 | ->select( [ $deletedFieldAlias => 'ipb_deleted IS NOT NULL' ] ) |
97 | ->leftJoin( |
98 | 'ipblocks', 'hide_user_ipblocks', |
99 | [ "ipb_user=$userIdField", 'ipb_deleted' => 1 ] |
100 | ); |
101 | } else { |
102 | $group = $qb->newJoinGroup() |
103 | ->table( 'block_target' ) |
104 | ->join( 'block', 'hide_user_block', 'bl_target=bt_id' ); |
105 | $qb |
106 | ->select( [ $deletedFieldAlias => 'bl_deleted IS NOT NULL' ] ) |
107 | ->leftJoin( |
108 | $group, |
109 | 'hide_user_block_group', |
110 | [ "bt_user=$userIdField", 'bl_deleted' => 1 ] |
111 | ) |
112 | ->groupBy( $userIdField ); |
113 | } |
114 | } |
115 | } |