From 6638b6a9413dad0609878dcc38f2cd78f3564f28 Mon Sep 17 00:00:00 2001 From: Lens0021 / Leslie Date: Sun, 19 Feb 2023 17:59:37 +0900 Subject: [PATCH] Update extension test workflow on REL1_39 branch (#386) (#414) --- extension.json | 3 +- includes/Hooks/RecursiveCategory.php | 45 +++++++++- .../Hooks/RecursiveCategoryTest.php | 86 +++++++++++++++++++ .../SpecialCategoryIntersectionSearchTest.php | 2 +- tests/phpunit/unit/Hooks/MainTest.php | 2 +- 5 files changed, 133 insertions(+), 5 deletions(-) create mode 100644 tests/phpunit/integration/Hooks/RecursiveCategoryTest.php diff --git a/extension.json b/extension.json index d14b1dd..00c2bf6 100644 --- a/extension.json +++ b/extension.json @@ -38,11 +38,12 @@ }, "RecursiveCategory": { "class": "MediaWiki\\Extension\\FacetedCategory\\Hooks\\RecursiveCategory", - "services": [] + "services": ["DBLoadBalancer", "JobQueueGroup"] } }, "Hooks": { "BeforePageDisplay": "Main", + "CategoryAfterPageAdded": "RecursiveCategory", "ContentAlterParserOutput": "RecursiveCategory", "MakeGlobalVariablesScript": "RecursiveCategory", "OutputPageParserOutput": "RecursiveCategory", diff --git a/includes/Hooks/RecursiveCategory.php b/includes/Hooks/RecursiveCategory.php index ff48f40..b2515d5 100644 --- a/includes/Hooks/RecursiveCategory.php +++ b/includes/Hooks/RecursiveCategory.php @@ -3,18 +3,59 @@ namespace MediaWiki\Extension\FacetedCategory\Hooks; use Category; +use JobQueueGroup; +use RefreshLinksJob; use Title; +use Wikimedia\Rdbms\ILoadBalancer; class RecursiveCategory implements + \MediaWiki\Page\Hook\CategoryAfterPageAddedHook, \MediaWiki\Content\Hook\ContentAlterParserOutputHook, \MediaWiki\Hook\OutputPageParserOutputHook, \MediaWiki\Hook\MakeGlobalVariablesScriptHook { + /** @const string direct-categories key. */ + public const DIRECT_CATEGORIES_PROPERTY_NAME = 'direct-categories'; + + /** @var ILoadBalancer */ + private $loadBalancer; + + /** @var JobQueueGroup */ + private $jobQueueGroup; + /** - * direct-categories key. + * @param ILoadBalancer $loadBalancer + * @param JobQueueGroup $jobQueueGroup */ - public const DIRECT_CATEGORIES_PROPERTY_NAME = 'direct-categories'; + public function __construct( ILoadBalancer $loadBalancer, JobQueueGroup $jobQueueGroup ) { + $this->loadBalancer = $loadBalancer; + $this->jobQueueGroup = $jobQueueGroup; + } + + /** + * @inheritDoc + */ + public function onCategoryAfterPageAdded( $category, $wikiPage ) { + // return true; + $title = $wikiPage->getTitle(); + if ( $title->getNamespace() !== NS_CATEGORY || !str_contains( $title->getText(), '/' ) ) { + return true; + } + + $dbr = $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA ); + $pages = $dbr->selectFieldValues( + 'categorylinks', + 'cl_from', + [ 'cl_to' => $title->getDBKey() ], + __METHOD__ + ); + foreach ( $pages as $id ) { + $title = Title::newFromId( $id ); + $job = new RefreshLinksJob( $title, [ 'parseThreshold' => 0 ] ); + $this->jobQueueGroup->push( $job ); + } + } /** * When adding categories to a page, include the parent of the category also. diff --git a/tests/phpunit/integration/Hooks/RecursiveCategoryTest.php b/tests/phpunit/integration/Hooks/RecursiveCategoryTest.php new file mode 100644 index 0000000..42d75c1 --- /dev/null +++ b/tests/phpunit/integration/Hooks/RecursiveCategoryTest.php @@ -0,0 +1,86 @@ +db->selectFieldValues( + 'categorylinks', + 'cl_to', + [ + 'cl_from' => $title->getId(), + ], + ); + $this->assertEqualsCanonicalizing( $expected, $actual, $message ); + } + + public function testCategorizedUsingParent() { + $parent = $this->createTitle( 'Category:Facet/Parent1', '[[Category:Facet/Cat1]][[Category:Facet/Cat2]]' ); + $child = $this->createTitle( 'Child1', '[[Category:Facet/Parent1]]' ); + $this->assertCategory( $child, [ + 'Facet/Cat1', + 'Facet/Cat2', + 'Facet/Parent1', + ], + 'Should be registered to the specified category including the grandparent categories.' + ); + } + + public function testLateAddingCategoryToParent() { + $parentText = 'Facet/Parent-' . mt_rand(); + $child = $this->createTitle( 'Child-' . mt_rand(), "[[Category:$parentText]]" ); + $parent = $this->createTitle( "Category:$parentText", '[[Category:Facet/Cat1]]' ); + $this->assertCategory( $child, [ $parentText ] ); + + $this->runJobs(); + + $this->assertCategory( $child, [ + 'Facet/Cat1', + $parentText, + ], + 'Should be registered to the specified category including the grandparent categories' + ); + } + + public function testGrandParentCategoryChange() { + $suffix = mt_rand(); + $child = $this->createTitle( "Child-$suffix", "[[Category:Facet/Parent-$suffix]]" ); + $parent = $this->createTitle( "Category:Facet/Parent-$suffix", "[[Category:Facet/GrandParent-$suffix]]" ); + $grandParent = $this->createTitle( "Category:Facet/GrandParent-$suffix", "[[Category:Facet/Cat1-$suffix]]" ); + + $this->runJobs(); + + $this->assertCategory( $child, [ + "Facet/Cat1-$suffix", + "Facet/Parent-$suffix", + "Facet/GrandParent-$suffix", + ] ); + } + + /** + * @param string $name + * @param string $content + * @return Title + */ + protected function createTitle( $name, $content ) { + $content = new WikitextContent( $content ); + + $title = Title::newFromText( $name ); + $page = $this->getServiceContainer()->getWikiPageFactory()->newFromTitle( $title ); + + $updater = $page->newPageUpdater( $this->getTestUser()->getUser() ); + $updater->setContent( 'main', $content ); + $updater->saveRevision( CommentStoreComment::newUnsavedComment( 'Test' ) ); + + return $page->getTitle(); + } +} diff --git a/tests/phpunit/integration/SpecialCategoryIntersectionSearchTest.php b/tests/phpunit/integration/SpecialCategoryIntersectionSearchTest.php index 6181fe8..e6962dc 100644 --- a/tests/phpunit/integration/SpecialCategoryIntersectionSearchTest.php +++ b/tests/phpunit/integration/SpecialCategoryIntersectionSearchTest.php @@ -1,6 +1,6 @@