Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 28 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
LinkRecommendationHelper | |
0.00% |
0 / 28 |
|
0.00% |
0 / 4 |
110 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getLinkRecommendation | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 | |||
deleteLinkRecommendation | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
20 | |||
configError | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\NewcomerTasks\AddLink; |
4 | |
5 | use GrowthExperiments\ErrorException; |
6 | use GrowthExperiments\NewcomerTasks\ConfigurationLoader\ConfigurationLoader; |
7 | use GrowthExperiments\NewcomerTasks\TaskType\LinkRecommendationTaskType; |
8 | use GrowthExperiments\NewcomerTasks\TaskType\LinkRecommendationTaskTypeHandler; |
9 | use GrowthExperiments\Util; |
10 | use GrowthExperiments\WikiConfigException; |
11 | use MediaWiki\Deferred\DeferredUpdates; |
12 | use MediaWiki\Linker\LinkTarget; |
13 | use MediaWiki\Page\ProperPageIdentity; |
14 | use StatusValue; |
15 | use Wikimedia\Rdbms\IDBAccessObject; |
16 | |
17 | /** |
18 | * Shared functionality for various classes that consume link recommendations. |
19 | */ |
20 | class LinkRecommendationHelper { |
21 | |
22 | /** @var ConfigurationLoader */ |
23 | private $configurationLoader; |
24 | |
25 | /** @var LinkRecommendationProvider */ |
26 | private $linkRecommendationProvider; |
27 | |
28 | /** @var LinkRecommendationStore */ |
29 | private $linkRecommendationStore; |
30 | |
31 | /** |
32 | * @var callable returning {@link \CirrusSearch\WeightedTagsUpdater} |
33 | */ |
34 | private $weightedTagsUpdaterProvider; |
35 | |
36 | /** |
37 | * @param ConfigurationLoader $configurationLoader |
38 | * @param LinkRecommendationProvider $linkRecommendationProvider |
39 | * @param LinkRecommendationStore $linkRecommendationStore |
40 | * @param callable(): \CirrusSearch\WeightedTagsUpdater $weightedTagsUpdaterProvider |
41 | */ |
42 | public function __construct( |
43 | ConfigurationLoader $configurationLoader, |
44 | LinkRecommendationProvider $linkRecommendationProvider, |
45 | LinkRecommendationStore $linkRecommendationStore, |
46 | callable $weightedTagsUpdaterProvider |
47 | ) { |
48 | $this->configurationLoader = $configurationLoader; |
49 | $this->linkRecommendationProvider = $linkRecommendationProvider; |
50 | $this->linkRecommendationStore = $linkRecommendationStore; |
51 | $this->weightedTagsUpdaterProvider = $weightedTagsUpdaterProvider; |
52 | } |
53 | |
54 | /** |
55 | * Return the link recommendation stored for the given title. |
56 | * Returns null when all links of the recommendation are invalid. |
57 | * @param LinkTarget $title |
58 | * @return LinkRecommendation|null |
59 | * @throws ErrorException |
60 | */ |
61 | public function getLinkRecommendation( LinkTarget $title ): ?LinkRecommendation { |
62 | $taskTypeId = LinkRecommendationTaskTypeHandler::TASK_TYPE_ID; |
63 | $taskType = $this->configurationLoader->getTaskTypes()[$taskTypeId] ?? null; |
64 | if ( !$taskType ) { |
65 | throw $this->configError( "No such task type: $taskTypeId" ); |
66 | } elseif ( !$taskType instanceof LinkRecommendationTaskType ) { |
67 | throw $this->configError( "Not a link recommendation task type: $taskTypeId" ); |
68 | } |
69 | $linkRecommendation = $this->linkRecommendationProvider->get( $title, $taskType ); |
70 | if ( $linkRecommendation instanceof StatusValue ) { |
71 | throw new ErrorException( $linkRecommendation ); |
72 | } |
73 | return $linkRecommendation; |
74 | } |
75 | |
76 | /** |
77 | * Delete recommendations for a given page from the database and optionally from the search index. |
78 | * @param ProperPageIdentity $pageIdentity |
79 | * @param bool $deleteFromSearchIndex |
80 | * @param bool $allowJoiningSearchIndexDeletes if true, then CirrusSearch will join this with |
81 | * other events from the revision, waiting for up to 10 minutes |
82 | */ |
83 | public function deleteLinkRecommendation( |
84 | ProperPageIdentity $pageIdentity, |
85 | bool $deleteFromSearchIndex, |
86 | bool $allowJoiningSearchIndexDeletes = false |
87 | ): void { |
88 | if ( |
89 | $this->linkRecommendationStore->getByPageId( $pageIdentity->getId(), IDBAccessObject::READ_NORMAL ) !== null |
90 | ) { |
91 | DeferredUpdates::addCallableUpdate( function () use ( $pageIdentity ) { |
92 | $this->linkRecommendationStore->deleteByPageIds( [ $pageIdentity->getId() ] ); |
93 | } ); |
94 | } |
95 | if ( $deleteFromSearchIndex ) { |
96 | DeferredUpdates::addCallableUpdate( function () use ( $pageIdentity, $allowJoiningSearchIndexDeletes ) { |
97 | ( $this->weightedTagsUpdaterProvider )()->resetWeightedTags( |
98 | $pageIdentity, |
99 | [ LinkRecommendationTaskTypeHandler::WEIGHTED_TAG_PREFIX ], |
100 | $allowJoiningSearchIndexDeletes ? 'revision' : null |
101 | ); |
102 | } ); |
103 | } |
104 | } |
105 | |
106 | /** |
107 | * @param string $errorMessage |
108 | * @return ErrorException |
109 | */ |
110 | private function configError( string $errorMessage ): ErrorException { |
111 | Util::logException( new WikiConfigException( $errorMessage ) ); |
112 | return new ErrorException( StatusValue::newFatal( 'rawmessage', $errorMessage ) ); |
113 | } |
114 | |
115 | } |