Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
38 / 38 |
|
100.00% |
3 / 3 |
CRAP | |
100.00% |
1 / 1 |
PruningLinkRecommendationProvider | |
100.00% |
38 / 38 |
|
100.00% |
3 / 3 |
7 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
get | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
pruneLinkRecommendation | |
100.00% |
29 / 29 |
|
100.00% |
1 / 1 |
4 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\NewcomerTasks\AddLink; |
4 | |
5 | use GrowthExperiments\NewcomerTasks\TaskType\LinkRecommendationTaskType; |
6 | use GrowthExperiments\NewcomerTasks\TaskType\TaskType; |
7 | use MediaWiki\Cache\LinkBatchFactory; |
8 | use MediaWiki\Linker\LinkTarget; |
9 | use MediaWiki\Title\MalformedTitleException; |
10 | use MediaWiki\Title\TitleFactory; |
11 | use StatusValue; |
12 | |
13 | /** |
14 | * A link recommendation provider that removes red links and links which have been rejected too |
15 | * often. The class works as a decorator wrapping another provider. |
16 | */ |
17 | class PruningLinkRecommendationProvider implements LinkRecommendationProvider { |
18 | |
19 | /** @var TitleFactory */ |
20 | private $titleFactory; |
21 | |
22 | /** @var LinkBatchFactory */ |
23 | private $linkBatchFactory; |
24 | |
25 | /** @var LinkRecommendationStore */ |
26 | private $linkRecommendationStore; |
27 | |
28 | /** @var LinkRecommendationProvider */ |
29 | private $innerProvider; |
30 | |
31 | /** @var bool */ |
32 | private $pruneRedLinks; |
33 | |
34 | /** |
35 | * @param TitleFactory $titleFactory |
36 | * @param LinkBatchFactory $linkBatchFactory |
37 | * @param LinkRecommendationStore $linkRecommendationStore |
38 | * @param LinkRecommendationProvider $innerProvider |
39 | * @param bool $pruneRedLinks Prune red links? Should be true in production settings as we |
40 | * don't want to recommend red links, but in a developer setup it might be convenient to |
41 | * pretend that all recommended articles exist. |
42 | */ |
43 | public function __construct( |
44 | TitleFactory $titleFactory, |
45 | LinkBatchFactory $linkBatchFactory, |
46 | LinkRecommendationStore $linkRecommendationStore, |
47 | LinkRecommendationProvider $innerProvider, |
48 | bool $pruneRedLinks |
49 | ) { |
50 | $this->titleFactory = $titleFactory; |
51 | $this->linkBatchFactory = $linkBatchFactory; |
52 | $this->linkRecommendationStore = $linkRecommendationStore; |
53 | $this->innerProvider = $innerProvider; |
54 | $this->pruneRedLinks = $pruneRedLinks; |
55 | } |
56 | |
57 | /** |
58 | * @inheritDoc |
59 | * @throws MalformedTitleException |
60 | */ |
61 | public function get( LinkTarget $title, TaskType $taskType ) { |
62 | $recommendation = $this->innerProvider->get( $title, $taskType ); |
63 | if ( $recommendation instanceof StatusValue ) { |
64 | return $recommendation; |
65 | } |
66 | |
67 | return $this->pruneLinkRecommendation( $recommendation ); |
68 | } |
69 | |
70 | /** |
71 | * Remove exclusion-listed links and optionally red links from a LinkRecommendation. |
72 | * Returns a warning status when all links have been removed. |
73 | * @param LinkRecommendation $linkRecommendation |
74 | * @return LinkRecommendation|StatusValue |
75 | * @throws MalformedTitleException |
76 | */ |
77 | private function pruneLinkRecommendation( LinkRecommendation $linkRecommendation ) { |
78 | $excludedLinkIds = $this->linkRecommendationStore->getExcludedLinkIds( |
79 | $linkRecommendation->getPageId(), |
80 | LinkRecommendationTaskType::REJECTION_EXCLUSION_LIMIT |
81 | ); |
82 | $this->linkBatchFactory->newLinkBatch( |
83 | array_map( |
84 | function ( LinkRecommendationLink $link ) { |
85 | return $this->titleFactory->newFromText( $link->getLinkTarget() ); |
86 | }, |
87 | $linkRecommendation->getLinks() |
88 | ) |
89 | )->execute(); |
90 | $goodLinks = array_filter( $linkRecommendation->getLinks(), |
91 | function ( LinkRecommendationLink $link ) use ( $excludedLinkIds ) { |
92 | $pageId = $this->titleFactory->newFromTextThrow( $link->getLinkTarget() )->getArticleID(); |
93 | if ( $this->pruneRedLinks && !$pageId ) { |
94 | return false; |
95 | } |
96 | return !in_array( $pageId, $excludedLinkIds ); |
97 | } ); |
98 | |
99 | if ( !$goodLinks ) { |
100 | // Message used for debugging, keep it in English to reduce translator burden. |
101 | return StatusValue::newGood()->warning( 'rawmessage', |
102 | 'All of the links in the recommendation have been pruned' ); |
103 | } |
104 | // In most cases we could just return the original object; opt for consistency instead. |
105 | return new LinkRecommendation( |
106 | $linkRecommendation->getTitle(), |
107 | $linkRecommendation->getPageId(), |
108 | $linkRecommendation->getRevisionId(), |
109 | $goodLinks, |
110 | $linkRecommendation->getMetadata() |
111 | ); |
112 | } |
113 | |
114 | } |