20 private static array $cache = [];
21 private static ?array $priorityCache =
null;
27 public static function preloadGroups( array $groups,
string $caller ): void {
28 $dbGroupIds = array_map( [ self::class,
'getGroupIdForDatabase' ], $groups );
29 $missing = array_keys( array_diff_key( array_flip( $dbGroupIds ), self::$cache ) );
34 $functionName = __METHOD__ .
" (for $caller)";
36 self::$cache += array_fill_keys( $missing,
null );
38 $dbr = Utilities::getSafeReadDB();
39 $conditions = count( $missing ) <= 500 ? [
'tmd_group' => array_map(
'strval', $missing ) ] : [];
42 [
'tmd_group',
'tmd_key',
'tmd_value' ],
46 foreach ( $res as $row ) {
47 self::$cache[$row->tmd_group][$row->tmd_key] = $row->tmd_value;
57 public static function get(
string $group,
string $key ) {
58 self::preloadGroups( [ $group ], __METHOD__ );
59 return self::$cache[self::getGroupIdForDatabase( $group )][$key] ??
false;
67 string $group,
string $key,
string $defaultValue
69 $value = self::get( $group, $key );
70 return $value ===
false ? $defaultValue : $value;
80 public static function set(
string $groupId,
string $key, $value ): void {
81 $dbw = MediaWikiServices::getInstance()
83 ->getConnection( DB_PRIMARY );
84 $dbGroupId = self::getGroupIdForDatabase( $groupId );
85 $data = [
'tmd_group' => $dbGroupId,
'tmd_key' => $key,
'tmd_value' => $value ];
86 if ( $value ===
false ) {
87 unset( $data[
'tmd_value'] );
88 $dbw->delete(
'translate_metadata', $data, __METHOD__ );
89 unset( self::$cache[$dbGroupId][$key] );
93 [ [
'tmd_group',
'tmd_key' ] ],
97 self::$cache[$dbGroupId][$key] = $value;
100 self::$priorityCache =
null;
108 $groups = self::get( $groupId,
'subgroups' );
109 if ( is_string( $groups ) ) {
110 if ( str_contains( $groups,
'|' ) ) {
111 $groups = explode(
'|', $groups );
113 $groups = array_map(
'trim', explode(
',', $groups ) );
116 foreach ( $groups as $index => $id ) {
117 if ( trim( $id ) ===
'' ) {
118 unset( $groups[$index] );
129 public static function setSubgroups(
string $groupId, array $subgroupIds ): void {
130 $subgroups = implode(
'|', $subgroupIds );
131 self::set( $groupId,
'subgroups', $subgroups );
136 $dbw = MediaWikiServices::getInstance()
137 ->getDBLoadBalancer()
138 ->getConnection( DB_PRIMARY );
140 $dbGroupId = self::getGroupIdForDatabase( $groupId );
141 $conditions = [
'tmd_group' => $dbGroupId ];
142 $dbw->delete(
'translate_metadata', $conditions, __METHOD__ );
143 self::$cache[ $dbGroupId ] =
null;
144 unset( self::$priorityCache[ $dbGroupId ] );
147 public static function isExcluded(
string $groupId,
string $code ): bool {
148 if ( self::$priorityCache === null ) {
149 $db = Utilities::getSafeReadDB();
152 'a' =>
'translate_metadata',
153 'b' =>
'translate_metadata'
156 'group' =>
'b.tmd_group',
157 'langs' =>
'b.tmd_value',
166 'a.tmd_group = b.tmd_group',
167 'a.tmd_key' =>
'priorityforce',
168 'a.tmd_value' =>
'on',
169 'b.tmd_key' =>
'prioritylangs',
175 self::$priorityCache = [];
176 foreach ( $res as $row ) {
177 self::$priorityCache[$row->group] =
178 array_flip( explode(
',', $row->langs ) );
182 $dbGroupId = self::getGroupIdForDatabase( $groupId );
183 $isDiscouraged = MessageGroups::getPriority( $groupId ) ===
'discouraged';
184 $hasLimitedLanguages = isset( self::$priorityCache[$dbGroupId] );
185 $isLanguageIncluded = isset( self::$priorityCache[$dbGroupId][$code] );
187 return $isDiscouraged || ( $hasLimitedLanguages && !$isLanguageIncluded );
200 foreach ( $groupIds as $groupId ) {
201 $dbGroupIdMap[ self::getGroupIdForDatabase( $groupId ) ] = $groupId;
205 'translate_metadata',
206 [
'tmd_group',
'tmd_key',
'tmd_value' ],
208 'tmd_group' => array_keys( $dbGroupIdMap ),
215 foreach ( $res as $row ) {
216 $groupId = $row->tmd_group;
218 $ret[ $dbGroupIdMap[ $groupId ] ][ $row->tmd_key ] = $row->tmd_value;
224 public static function moveMetadata(
227 array $metadataKeysToMove
229 self::preloadGroups( [ $oldGroupId, $newGroupId ], __METHOD__ );
230 foreach ( $metadataKeysToMove as $type ) {
231 $value = self::get( $oldGroupId, $type );
232 if ( $value !==
false ) {
233 self::set( $oldGroupId, $type,
false );
234 self::set( $newGroupId, $type, $value );
243 public static function clearMetadata(
string $groupId, array $metadataKeys ): void {
245 foreach ( $metadataKeys as $type ) {
246 self::set( $groupId, $type,
false );
252 $tables = [
'translate_metadata' ];
253 $field =
'tmd_group';
254 $conditions = [
'tmd_key' =>
'subgroups' ];
256 $db = Utilities::getSafeReadDB();
260 return $db->selectFieldValues( $tables, $field, $conditions, __METHOD__ );
263 private static function getGroupIdForDatabase(
string $groupId ): string {
265 if ( strlen( $groupId ) <= 200 ) {
269 $hash = hash(
'md5', $groupId );
271 return mb_strcut( $groupId, 0, 160 ) .
'||' . $hash;