2declare( strict_types = 1 );
4namespace MediaWiki\Extension\Translate\MessageGroupProcessing;
7use MediaWiki\Page\PageIdentity;
8use Wikimedia\Rdbms\IConnectionProvider;
9use Wikimedia\Rdbms\RawSQLExpression;
10use Wikimedia\Rdbms\SelectQueryBuilder;
31 private array $tagCache = [];
33 public function __construct(
34 private readonly IConnectionProvider $dbProvider,
40 PageIdentity $identity,
45 if ( !$identity->exists() ) {
49 $articleId = $identity->getId();
51 $dbw = $this->dbProvider->getPrimaryDatabase();
53 'rt_page' => $articleId,
56 $dbw->newDeleteQueryBuilder()
57 ->deleteFrom(
'revtag' )
58 ->where( $conditions )
59 ->caller( __METHOD__ )
62 if ( $value !==
null ) {
63 $conditions[
'rt_value'] = serialize( implode(
'|', $value ) );
66 $conditions[
'rt_revision'] = $revisionId;
67 $dbw->newInsertQueryBuilder()
68 ->insertInto(
'revtag' )
70 ->caller( __METHOD__ )
73 $this->tagCache[$articleId][$tag] = $revisionId;
76 public function getLatestRevisionWithTag( PageIdentity $identity,
string $tag ): ?int {
77 $response = $this->getLatestRevisionsForTags( $identity, $tag );
78 return $response[$tag] ??
null;
83 if ( !$identity->exists() ) {
87 $articleId = $identity->getId();
93 foreach ( $tags as $tag ) {
94 if ( isset( $this->tagCache[$articleId][$tag] ) ) {
95 $response[$tag] = $this->tagCache[$articleId][$tag];
97 $remainingTags[] = $tag;
101 if ( !$remainingTags ) {
106 $dbr = Utilities::getSafeReadDB();
107 $results = $dbr->newSelectQueryBuilder()
108 ->select( [
'rt_revision' =>
'MAX(rt_revision)',
'rt_type' ] )
111 'rt_page' => $articleId,
112 'rt_type' => $remainingTags
114 ->groupBy(
'rt_type' )
115 ->caller( __METHOD__ )
118 foreach ( $results as $row ) {
119 $response[$row->rt_type] = (int)$row->rt_revision;
125 public function removeTags( PageIdentity $identity,
string ...$tag ): void {
126 if ( !$identity->exists() ) {
130 $articleId = $identity->getId();
132 $dbw = $this->dbProvider->getPrimaryDatabase();
133 $dbw->newDeleteQueryBuilder()
134 ->deleteFrom(
'revtag' )
136 'rt_page' => $articleId,
139 ->caller( __METHOD__ )
142 unset( $this->tagCache[$articleId] );
145 public function isRevIdFuzzy(
int $articleId,
int $revisionId ): bool {
146 $dbw = $this->dbProvider->getPrimaryDatabase();
147 $res = $dbw->newSelectQueryBuilder()
148 ->select(
'rt_type' )
151 'rt_page' => $articleId,
152 'rt_type' => self::FUZZY_TAG,
153 'rt_revision' => $revisionId
155 ->caller( __METHOD__ )
158 return $res !==
false;
173 public function getTransver( PageIdentity $identity, ?
int $revid =
null ): ?int {
175 $query = $db->newSelectQueryBuilder()
176 ->select(
'rt_value' )
179 'rt_page' => $identity->getId(),
180 'rt_type' => self::TRANSVER_PROP,
182 if ( $revid !==
null ) {
183 $query->where( $db->expr(
'rt_revision',
'<=', $revid ) );
186 ->orderBy(
'rt_revision', SelectQueryBuilder::SORT_DESC )
187 ->caller( __METHOD__ )
191 return $result ? (int)$result : null;
201 public function setTransver( PageIdentity $identity,
int $translationRevision,
int $transver ): void {
202 $dbw = $this->dbProvider->getPrimaryDatabase();
205 'rt_page' => $identity->getId(),
206 'rt_type' => self::TRANSVER_PROP,
207 'rt_revision' => $translationRevision,
208 'rt_value' => $transver,
210 $dbw->newReplaceQueryBuilder()
211 ->replaceInto(
'revtag' )
212 ->uniqueIndexFields( [
'rt_type',
'rt_page',
'rt_revision' ] )
214 ->caller( __METHOD__ )
228 $expr = $dbr->andExpr( [
229 new RawSQLExpression(
'rt_revision = page_latest' ),
230 'rt_type' => $revTagsLatest
233 $expr = $dbr->orExpr( [ $expr,
'rt_type' => $revTagsAny ] );
235 $pageIds = $dbr->newSelectQueryBuilder()
236 ->select(
'rt_page' )
246 ->groupBy(
'rt_page' )
247 ->caller( __METHOD__ )
248 ->fetchFieldValues();
249 return array_map( intval( ... ), $pageIds );