Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
90.74% |
49 / 54 |
|
57.14% |
4 / 7 |
CRAP | |
0.00% |
0 / 1 |
ApiHelpPanelPostQuestion | |
90.74% |
49 / 54 |
|
57.14% |
4 / 7 |
11.10 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
execute | |
95.24% |
20 / 21 |
|
0.00% |
0 / 1 |
4 | |||
getQuestionPoster | |
72.73% |
8 / 11 |
|
0.00% |
0 / 1 |
2.08 | |||
needsToken | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isInternal | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getAllowedParams | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
1 | |||
isWriteMode | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\Api; |
4 | |
5 | use ApiBase; |
6 | use ApiMain; |
7 | use ApiUsageException; |
8 | use GrowthExperiments\HelpPanel\QuestionPoster\QuestionPoster; |
9 | use GrowthExperiments\HelpPanel\QuestionPoster\QuestionPosterFactory; |
10 | use UserNotLoggedIn; |
11 | use Wikimedia\ParamValidator\ParamValidator; |
12 | use Wikimedia\ParamValidator\TypeDef\StringDef; |
13 | |
14 | class ApiHelpPanelPostQuestion extends ApiBase { |
15 | |
16 | public const API_PARAM_BODY = 'body'; |
17 | public const API_PARAM_SOURCE = 'source'; |
18 | public const API_PARAM_RELEVANT_TITLE = 'relevanttitle'; |
19 | |
20 | /** API name => [ source, target ] using the respective QuestionPosterFactory constants */ |
21 | private const QUESTION_POSTER_TYPES = [ |
22 | 'helpdesk' => |
23 | [ QuestionPosterFactory::SOURCE_HELP_PANEL, QuestionPosterFactory::TARGET_HELPDESK ], |
24 | 'mentor-homepage' => |
25 | [ QuestionPosterFactory::SOURCE_MENTORSHIP_MODULE, QuestionPosterFactory::TARGET_MENTOR_TALK ], |
26 | 'mentor-helppanel' => |
27 | [ QuestionPosterFactory::SOURCE_HELP_PANEL, QuestionPosterFactory::TARGET_MENTOR_TALK ], |
28 | // old names (FIXME remove once not in use) |
29 | 'helppanel' => |
30 | [ QuestionPosterFactory::SOURCE_HELP_PANEL, QuestionPosterFactory::TARGET_HELPDESK ], |
31 | 'homepage-mentorship' => |
32 | [ QuestionPosterFactory::SOURCE_MENTORSHIP_MODULE, QuestionPosterFactory::TARGET_MENTOR_TALK ], |
33 | ]; |
34 | |
35 | /** |
36 | * @var QuestionPosterFactory |
37 | */ |
38 | private $questionPosterFactory; |
39 | |
40 | /** |
41 | * @param ApiMain $mainModule |
42 | * @param string $moduleName |
43 | * @param QuestionPosterFactory $questionPosterFactory |
44 | */ |
45 | public function __construct( |
46 | ApiMain $mainModule, |
47 | $moduleName, |
48 | QuestionPosterFactory $questionPosterFactory |
49 | ) { |
50 | parent::__construct( $mainModule, $moduleName ); |
51 | $this->questionPosterFactory = $questionPosterFactory; |
52 | } |
53 | |
54 | /** |
55 | * Save help panel question post. |
56 | */ |
57 | public function execute() { |
58 | $params = $this->extractRequestParams(); |
59 | $questionPoster = $this->getQuestionPoster( |
60 | $params[self::API_PARAM_SOURCE], |
61 | $params[self::API_PARAM_BODY], |
62 | $params[self::API_PARAM_RELEVANT_TITLE] ?? '' |
63 | ); |
64 | |
65 | if ( $params[self::API_PARAM_RELEVANT_TITLE] ) { |
66 | $status = $questionPoster->validateRelevantTitle(); |
67 | if ( !$status->isGood() ) { |
68 | $this->dieStatus( $status ); |
69 | } |
70 | } |
71 | |
72 | $status = $questionPoster->submit(); |
73 | if ( !$status->isGood() ) { |
74 | $this->dieStatus( $status ); |
75 | } |
76 | |
77 | $result = [ |
78 | 'result' => 'success', |
79 | 'revision' => $questionPoster->getRevisionId(), |
80 | 'isfirstedit' => (int)$questionPoster->isFirstEdit(), |
81 | 'viewquestionurl' => $questionPoster->getResultUrl(), |
82 | 'source' => $params[self::API_PARAM_SOURCE] |
83 | ]; |
84 | |
85 | $this->getResult()->addValue( null, $this->getModuleName(), $result ); |
86 | } |
87 | |
88 | /** |
89 | * @param string $source |
90 | * @param string $body |
91 | * @param string|null $relevantTitle |
92 | * @return QuestionPoster |
93 | * @throws ApiUsageException |
94 | */ |
95 | private function getQuestionPoster( $source, $body, $relevantTitle ): QuestionPoster { |
96 | $questionPosterType = self::QUESTION_POSTER_TYPES[$source]; |
97 | try { |
98 | return $this->questionPosterFactory->getQuestionPoster( |
99 | $questionPosterType[0], |
100 | $questionPosterType[1], |
101 | $this->getContext(), |
102 | $body, |
103 | $relevantTitle ?? '' |
104 | ); |
105 | } catch ( UserNotLoggedIn $e ) { |
106 | throw ApiUsageException::newWithMessage( $this, |
107 | 'apierror-mustbeloggedin-helppanelquestionposter', 'notloggedin' ); |
108 | } |
109 | } |
110 | |
111 | /** |
112 | * @inheritDoc |
113 | */ |
114 | public function needsToken() { |
115 | return 'csrf'; |
116 | } |
117 | |
118 | /** @inheritDoc */ |
119 | public function isInternal() { |
120 | // For use by the question poster dialog only. All functionality available via core APIs. |
121 | return true; |
122 | } |
123 | |
124 | /** |
125 | * @inheritDoc |
126 | */ |
127 | public function getAllowedParams() { |
128 | return [ |
129 | self::API_PARAM_BODY => [ |
130 | ParamValidator::PARAM_REQUIRED => true, |
131 | ParamValidator::PARAM_TYPE => 'string', |
132 | StringDef::PARAM_MAX_CHARS => 2000, |
133 | ], |
134 | self::API_PARAM_SOURCE => [ |
135 | ParamValidator::PARAM_REQUIRED => false, |
136 | ParamValidator::PARAM_TYPE => array_keys( self::QUESTION_POSTER_TYPES ), |
137 | ParamValidator::PARAM_DEFAULT => 'helpdesk', |
138 | ApiBase::PARAM_HELP_MSG_PER_VALUE => [], |
139 | ], |
140 | self::API_PARAM_RELEVANT_TITLE => [ |
141 | ParamValidator::PARAM_REQUIRED => false, |
142 | ParamValidator::PARAM_TYPE => 'string', |
143 | ], |
144 | ]; |
145 | } |
146 | |
147 | /** |
148 | * @inheritDoc |
149 | */ |
150 | public function isWriteMode() { |
151 | return true; |
152 | } |
153 | } |