Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
MessageGroupSubscriptionStore.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\MessageGroupProcessing;
5
7use Wikimedia\Rdbms\IConnectionProvider;
8
16 private const VIRTUAL_DOMAIN = 'virtual-translate';
17 private const TABLE_NAME = 'translate_message_group_subscriptions';
19 private const MAX_GROUP_LENGTH = 200;
20
21 public function __construct(
22 private readonly IConnectionProvider $dbProvider,
23 ) {
24 }
25
26 public function addSubscription( string $groupId, int $userId ): void {
27 $this->dbProvider->getPrimaryDatabase( self::VIRTUAL_DOMAIN )
28 ->newReplaceQueryBuilder()
29 ->replaceInto( self::TABLE_NAME )
30 ->uniqueIndexFields( [ 'tmgs_group', 'tmgs_user_id' ] )
31 ->row( [
32 'tmgs_group' => self::getGroupIdForDatabase( $groupId ),
33 'tmgs_user_id' => $userId,
34 ] )
35 ->caller( __METHOD__ )
36 ->execute();
37 }
38
44 public function getSubscriptions( ?array $groupIds, ?int $userId ): array {
45 $queryBuilder = $this->dbProvider
46 ->getReplicaDatabase( self::VIRTUAL_DOMAIN )
47 ->newSelectQueryBuilder()
48 ->select( [ 'tmgs_group', 'tmgs_user_id' ] )
49 ->from( self::TABLE_NAME )
50 ->caller( __METHOD__ );
51
52 if ( $groupIds ) {
53 $dbGroupIds = array_map( self::getGroupIdForDatabase( ... ), $groupIds );
54 $dbGroupIdMap = array_combine( $dbGroupIds, $groupIds );
55 $queryBuilder->where( [ 'tmgs_group' => $dbGroupIds ] );
56 } else {
57 $groupIds = array_keys( MessageGroups::getAllGroups() );
58 $dbGroupIds = array_map( self::getGroupIdForDatabase( ... ), $groupIds );
59 $dbGroupIdMap = array_combine( $dbGroupIds, $groupIds );
60 }
61
62 if ( $userId ) {
63 $queryBuilder->andWhere( [ 'tmgs_user_id' => $userId ] );
64 }
65
66 $subscriptions = [];
67 foreach ( $queryBuilder->fetchResultSet() as $row ) {
68 // Handle unknown groups gracefully so that they can be removed
69 $subscriptions[$dbGroupIdMap[$row->tmgs_group] ?? $row->tmgs_group][] = (int)$row->tmgs_user_id;
70 }
71 return $subscriptions;
72 }
73
78 public function getSubscriptionByGroupUnion( array $groupIds ): array {
79 $userIds = $this->dbProvider
80 ->getReplicaDatabase( self::VIRTUAL_DOMAIN )
81 ->newSelectQueryBuilder()
82 ->select( 'tmgs_user_id' )
83 ->from( self::TABLE_NAME )
84 ->where( [ 'tmgs_group' => $groupIds ] )
85 ->having( 'COUNT(tmgs_group) = ' . count( $groupIds ) )
86 ->caller( __METHOD__ )
87 ->fetchFieldValues();
88 return array_map( intval( ... ), $userIds );
89 }
90
91 public function removeSubscriptions( string $groupId, int $userId ): void {
92 $this->dbProvider->getPrimaryDatabase( self::VIRTUAL_DOMAIN )
93 ->newDeleteQueryBuilder()
94 ->deleteFrom( self::TABLE_NAME )
95 ->where( [
96 'tmgs_group' => $groupId,
97 'tmgs_user_id' => $userId
98 ] )
99 ->caller( __METHOD__ )
100 ->execute();
101 }
102
103 public static function getGroupIdForDatabase( MessageGroup|string $groupId ): string {
104 if ( $groupId instanceof MessageGroup ) {
105 $groupId = $groupId->getId();
106 }
107
108 return strlen( $groupId ) > self::MAX_GROUP_LENGTH ?
109 // Note: mb_strcut operates on bytes but leaves multi-byte characters intact
110 mb_strcut( $groupId, 0, 160 ) . '||' . md5( $groupId ) :
111 $groupId;
112 }
113}
Store service for looking up and storing user subscriptions to message group.
Interface for message groups.