Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.14% |
68 / 70 |
|
66.67% |
4 / 6 |
CRAP | |
0.00% |
0 / 1 |
ApiInvalidateImageRecommendation | |
97.14% |
68 / 70 |
|
66.67% |
4 / 6 |
8 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
execute | |
96.97% |
32 / 33 |
|
0.00% |
0 / 1 |
3 | |||
needsToken | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
mustBePosted | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getAllowedParams | |
100.00% |
27 / 27 |
|
100.00% |
1 / 1 |
1 | |||
isInternal | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\Api; |
4 | |
5 | use ApiBase; |
6 | use ApiMain; |
7 | use ApiUsageException; |
8 | use GrowthExperiments\NewcomerTasks\AddImage\AddImageSubmissionHandler; |
9 | use GrowthExperiments\NewcomerTasks\ConfigurationLoader\ConfigurationLoader; |
10 | use GrowthExperiments\NewcomerTasks\NewcomerTasksUserOptionsLookup; |
11 | use GrowthExperiments\NewcomerTasks\TaskSuggester\TaskSuggesterFactory; |
12 | use GrowthExperiments\NewcomerTasks\TaskType\ImageRecommendationBaseTaskType; |
13 | use GrowthExperiments\NewcomerTasks\TaskType\ImageRecommendationTaskTypeHandler; |
14 | use GrowthExperiments\NewcomerTasks\TaskType\SectionImageRecommendationTaskTypeHandler; |
15 | use MediaWiki\Logger\LoggerFactory; |
16 | use MediaWiki\ParamValidator\TypeDef\TitleDef; |
17 | use MediaWiki\Title\TitleFactory; |
18 | use Psr\Log\LoggerAwareTrait; |
19 | use Wikimedia\Assert\Assert; |
20 | use Wikimedia\ParamValidator\ParamValidator; |
21 | |
22 | /** |
23 | * Endpoint for invalidating image recommendation. |
24 | * |
25 | * This is used when the recommendation is determined to be invalid upon display (for example, |
26 | * when the article already has an image). See mw.libs.ge.AddImageArticleTarget. |
27 | */ |
28 | class ApiInvalidateImageRecommendation extends ApiBase { |
29 | use LoggerAwareTrait; |
30 | |
31 | private AddImageSubmissionHandler $imageSubmissionHandler; |
32 | private TaskSuggesterFactory $taskSuggesterFactory; |
33 | private NewcomerTasksUserOptionsLookup $newcomerTasksUserOptionsLookup; |
34 | private TitleFactory $titleFactory; |
35 | private ConfigurationLoader $configurationLoader; |
36 | |
37 | /** |
38 | * @param ApiMain $mainModule |
39 | * @param string $moduleName |
40 | * @param ConfigurationLoader $configurationLoader |
41 | * @param AddImageSubmissionHandler $imageSubmissionHandler |
42 | * @param TaskSuggesterFactory $taskSuggesterFactory |
43 | * @param NewcomerTasksUserOptionsLookup $newcomerTasksUserOptionsLookup |
44 | * @param TitleFactory $titleFactory |
45 | */ |
46 | public function __construct( |
47 | ApiMain $mainModule, |
48 | string $moduleName, |
49 | ConfigurationLoader $configurationLoader, |
50 | AddImageSubmissionHandler $imageSubmissionHandler, |
51 | TaskSuggesterFactory $taskSuggesterFactory, |
52 | NewcomerTasksUserOptionsLookup $newcomerTasksUserOptionsLookup, |
53 | TitleFactory $titleFactory |
54 | ) { |
55 | parent::__construct( $mainModule, $moduleName ); |
56 | $this->configurationLoader = $configurationLoader; |
57 | $this->imageSubmissionHandler = $imageSubmissionHandler; |
58 | $this->taskSuggesterFactory = $taskSuggesterFactory; |
59 | $this->newcomerTasksUserOptionsLookup = $newcomerTasksUserOptionsLookup; |
60 | $this->titleFactory = $titleFactory; |
61 | |
62 | $this->setLogger( LoggerFactory::getInstance( 'GrowthExperiments' ) ); |
63 | } |
64 | |
65 | /** |
66 | * @inheritDoc |
67 | * @throws ApiUsageException |
68 | */ |
69 | public function execute() { |
70 | $params = $this->extractRequestParams(); |
71 | // This API is used by external clients for their own structured task workflows so |
72 | // include disabled task types. |
73 | $allTaskTypes = $this->configurationLoader->getTaskTypes() |
74 | + $this->configurationLoader->getDisabledTaskTypes(); |
75 | $taskType = $allTaskTypes[$params['tasktype']] ?? null; |
76 | if ( $taskType === null ) { |
77 | $this->logger->warning( |
78 | 'Task type {tasktype} was not found in {configpage}', |
79 | [ |
80 | 'tasktype' => $params['tasktype'], |
81 | 'configpage' => $this->getConfig()->get( 'GENewcomerTasksConfigTitle' ), |
82 | ] |
83 | ); |
84 | $this->dieWithError( |
85 | [ 'growthexperiments-homepage-imagesuggestiondata-not-in-config', $params['tasktype'] ], |
86 | 'not-in-config' |
87 | ); |
88 | } |
89 | |
90 | Assert::parameterType( ImageRecommendationBaseTaskType::class, $taskType, '$taskType' ); |
91 | '@phan-var ImageRecommendationBaseTaskType $taskType';/** @var ImageRecommendationBaseTaskType $taskType */ |
92 | $titleValue = $params['title']; |
93 | |
94 | $page = $this->titleFactory->newFromLinkTarget( $titleValue )->toPageIdentity(); |
95 | if ( $page->exists() ) { |
96 | $this->imageSubmissionHandler->invalidateRecommendation( |
97 | $taskType, |
98 | $page, |
99 | $this->getAuthority()->getUser()->getId(), |
100 | null, |
101 | $params['filename'], |
102 | $params['sectiontitle'], |
103 | $params['sectionnumber'], |
104 | ); |
105 | $this->getResult()->addValue( null, $this->getModuleName(), [ |
106 | 'status' => 'ok' |
107 | ] ); |
108 | } else { |
109 | $this->dieWithError( [ 'apierror-invalidtitle', $titleValue->getDBkey() ] ); |
110 | } |
111 | } |
112 | |
113 | /** |
114 | * @inheritDoc |
115 | */ |
116 | public function needsToken() { |
117 | return 'csrf'; |
118 | } |
119 | |
120 | /** |
121 | * @inheritDoc |
122 | */ |
123 | public function mustBePosted() { |
124 | return true; |
125 | } |
126 | |
127 | /** |
128 | * @inheritDoc |
129 | */ |
130 | public function getAllowedParams() { |
131 | return [ |
132 | 'tasktype' => [ |
133 | ParamValidator::PARAM_TYPE => [ |
134 | // Do not filter out non-existing task-types: during API structure tests |
135 | // none of the task types exist and an empty list would cause test failures. |
136 | ImageRecommendationTaskTypeHandler::TASK_TYPE_ID, |
137 | SectionImageRecommendationTaskTypeHandler::TASK_TYPE_ID, |
138 | ], |
139 | ParamValidator::PARAM_REQUIRED => false, |
140 | ParamValidator::PARAM_DEFAULT => ImageRecommendationTaskTypeHandler::TASK_TYPE_ID, |
141 | ], |
142 | 'title' => [ |
143 | ParamValidator::PARAM_REQUIRED => true, |
144 | ParamValidator::PARAM_TYPE => 'title', |
145 | TitleDef::PARAM_RETURN_OBJECT => true, |
146 | ], |
147 | 'filename' => [ |
148 | ParamValidator::PARAM_REQUIRED => true, |
149 | ParamValidator::PARAM_TYPE => 'string', |
150 | ], |
151 | 'sectiontitle' => [ |
152 | ParamValidator::PARAM_REQUIRED => false, |
153 | ParamValidator::PARAM_TYPE => 'string', |
154 | ], |
155 | 'sectionnumber' => [ |
156 | ParamValidator::PARAM_REQUIRED => false, |
157 | ParamValidator::PARAM_TYPE => 'integer', |
158 | ] |
159 | ]; |
160 | } |
161 | |
162 | /** @inheritDoc */ |
163 | public function isInternal() { |
164 | return true; |
165 | } |
166 | } |