diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2f4233..30d8cb3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,23 +7,16 @@ on: jobs: test: name: "PHPUnit: MW ${{ matrix.mw }}, PHP ${{ matrix.php }}" - continue-on-error: ${{ matrix.experimental }} strategy: matrix: include: - mw: 'REL1_43' php: '8.1' - experimental: false - mw: 'REL1_43' php: '8.2' - experimental: false - mw: 'REL1_43' php: '8.3' - experimental: false - - mw: 'master' - php: '8.4' - experimental: true runs-on: ubuntu-latest @@ -75,15 +68,6 @@ jobs: - name: Run PHPUnit run: php tests/phpunit/phpunit.php -c extensions/PageApprovals/ - if: matrix.mw != 'master' - - - name: Run PHPUnit with code coverage - run: php tests/phpunit/phpunit.php -c extensions/PageApprovals/ --coverage-clover coverage.xml - if: matrix.mw == 'master' - - - name: Upload code coverage - run: bash <(curl -s https://codecov.io/bash) - if: matrix.mw == 'master' diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 909c43f..0d5b057 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -63,12 +63,14 @@ + categories]]> page_title]]> + @@ -83,6 +85,17 @@ IDatabase::LIST_OR ) ]]]> + NS_CATEGORY, + 'lt_title' => $this->normalizeCategoryTitles( $categories ), + $this->db->makeList( + [ + 'latest_approval.al_is_approved' => 0, + 'latest_approval.al_is_approved IS NULL' + ], + IDatabase::LIST_OR + ) + ]]]> diff --git a/src/Adapters/DatabasePendingApprovalRetriever.php b/src/Adapters/DatabasePendingApprovalRetriever.php index caaba4b..19bdc0a 100644 --- a/src/Adapters/DatabasePendingApprovalRetriever.php +++ b/src/Adapters/DatabasePendingApprovalRetriever.php @@ -38,6 +38,22 @@ public function getPendingApprovalsForApprover( int $approverId ): array { * @param string[] $categories */ private function queryPendingApprovals( array $categories ): IResultWrapper { + if ( $this->hasLegacyCategoryLinksSchema() ) { + return $this->queryPendingApprovalsLegacy( $categories ); + } + + return $this->queryPendingApprovalsWithLinkTarget( $categories ); + } + + private function hasLegacyCategoryLinksSchema(): bool { + return version_compare( MW_VERSION, '1.45', '<' ); + } + + /** + * Query for MW 1.43–1.44 where categorylinks has cl_to. + * @param string[] $categories + */ + private function queryPendingApprovalsLegacy( array $categories ): IResultWrapper { $latestApprovalSubquery = $this->getLatestApprovalSubquery(); return $this->db->select( @@ -81,6 +97,57 @@ private function queryPendingApprovals( array $categories ): IResultWrapper { ); } + /** + * Query for MW 1.45+ where categorylinks uses cl_target_id referencing the linktarget table. + * @param string[] $categories + */ + private function queryPendingApprovalsWithLinkTarget( array $categories ): IResultWrapper { + $latestApprovalSubquery = $this->getLatestApprovalSubquery(); + + return $this->db->select( + [ + 'page', + 'revision', + 'categorylinks', + 'linktarget', + 'latest_approval' => $latestApprovalSubquery + ], + [ + 'page_id', + 'page_namespace', + 'page_title', + 'rev_timestamp', + 'rev_actor', + 'GROUP_CONCAT(DISTINCT lt_title) AS categories', + 'latest_approval.al_is_approved', + 'latest_approval.al_timestamp' + ], + [ + 'lt_namespace' => NS_CATEGORY, + 'lt_title' => $this->normalizeCategoryTitles( $categories ), + $this->db->makeList( + [ + 'latest_approval.al_is_approved' => 0, + 'latest_approval.al_is_approved IS NULL' + ], + IDatabase::LIST_OR + ) + ], + __METHOD__, + [ + 'GROUP BY' => 'page_id', + 'ORDER BY' => 'rev_timestamp DESC', + 'LIMIT' => $this->limit + ], + [ + 'revision' => [ 'INNER JOIN', 'page_latest = rev_id' ], + 'categorylinks' => [ 'INNER JOIN', 'page_id = cl_from' ], + 'linktarget' => [ 'INNER JOIN', 'cl_target_id = lt_id' ], + 'latest_approval' => [ 'LEFT JOIN', 'page_id = latest_approval.al_page_id' ] + ] + ); + } + private function getLatestApprovalSubquery(): Subquery { return $this->db->buildSelectSubquery( [ diff --git a/tests/Adapters/DatabasePendingApprovalRetrieverTest.php b/tests/Adapters/DatabasePendingApprovalRetrieverTest.php index 50bbaad..e4a405e 100644 --- a/tests/Adapters/DatabasePendingApprovalRetrieverTest.php +++ b/tests/Adapters/DatabasePendingApprovalRetrieverTest.php @@ -22,7 +22,7 @@ class DatabasePendingApprovalRetrieverTest extends PageApprovalsIntegrationTest protected function setUp(): void { parent::setUp(); - $this->tablesUsed = [ 'page', 'revision', 'categorylinks', 'approval_log' ]; + $this->tablesUsed = [ 'page', 'revision', 'categorylinks', 'linktarget', 'approval_log' ]; $this->approverRepository = new InMemoryApproverRepository(); $this->retriever = new DatabasePendingApprovalRetriever( $this->db, $this->approverRepository );