Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
92.78% |
90 / 97 |
|
75.00% |
3 / 4 |
CRAP | |
0.00% |
0 / 1 |
AbstractEditEventRegistrationHandler | |
92.78% |
90 / 97 |
|
75.00% |
3 / 4 |
11.05 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
1 | |||
validate | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
checkPermissions | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
execute | |
66.67% |
14 / 21 |
|
0.00% |
0 / 1 |
8.81 | |||
getSuccessResponse | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getBodyParamSettings | |
100.00% |
66 / 66 |
|
100.00% |
1 / 1 |
2 | |||
createEventObject | n/a |
0 / 0 |
n/a |
0 / 0 |
0 |
1 | <?php |
2 | |
3 | declare( strict_types=1 ); |
4 | |
5 | namespace MediaWiki\Extension\CampaignEvents\Rest; |
6 | |
7 | use MediaWiki\Config\Config; |
8 | use MediaWiki\Extension\CampaignEvents\Event\EditEventCommand; |
9 | use MediaWiki\Extension\CampaignEvents\Event\EventFactory; |
10 | use MediaWiki\Extension\CampaignEvents\Event\EventRegistration; |
11 | use MediaWiki\Extension\CampaignEvents\Event\InvalidEventDataException; |
12 | use MediaWiki\Extension\CampaignEvents\MWEntity\CampaignsCentralUserLookup; |
13 | use MediaWiki\Extension\CampaignEvents\MWEntity\ICampaignsAuthority; |
14 | use MediaWiki\Extension\CampaignEvents\MWEntity\MWAuthorityProxy; |
15 | use MediaWiki\Extension\CampaignEvents\MWEntity\UserNotGlobalException; |
16 | use MediaWiki\Extension\CampaignEvents\MWEntity\WikiLookup; |
17 | use MediaWiki\Extension\CampaignEvents\Organizers\OrganizersStore; |
18 | use MediaWiki\Extension\CampaignEvents\Permissions\PermissionChecker; |
19 | use MediaWiki\Extension\CampaignEvents\Questions\EventQuestionsRegistry; |
20 | use MediaWiki\Permissions\PermissionStatus; |
21 | use MediaWiki\Rest\Handler; |
22 | use MediaWiki\Rest\Response; |
23 | use MediaWiki\Rest\TokenAwareHandlerTrait; |
24 | use MediaWiki\Rest\Validator\Validator; |
25 | use RuntimeException; |
26 | use StatusValue; |
27 | use Wikimedia\ParamValidator\ParamValidator; |
28 | use Wikimedia\ParamValidator\TypeDef\TimestampDef; |
29 | |
30 | abstract class AbstractEditEventRegistrationHandler extends Handler { |
31 | use TokenAwareHandlerTrait; |
32 | use FailStatusUtilTrait; |
33 | |
34 | protected EventFactory $eventFactory; |
35 | protected PermissionChecker $permissionChecker; |
36 | protected EditEventCommand $editEventCommand; |
37 | private OrganizersStore $organizersStore; |
38 | private CampaignsCentralUserLookup $centralUserLookup; |
39 | protected EventQuestionsRegistry $eventQuestionsRegistry; |
40 | protected WikiLookup $wikiLookup; |
41 | protected bool $eventWikisEnabled; |
42 | |
43 | public function __construct( |
44 | EventFactory $eventFactory, |
45 | PermissionChecker $permissionChecker, |
46 | EditEventCommand $editEventCommand, |
47 | OrganizersStore $organizersStore, |
48 | CampaignsCentralUserLookup $centralUserLookup, |
49 | EventQuestionsRegistry $eventQuestionsRegistry, |
50 | WikiLookup $wikiLookup, |
51 | Config $config |
52 | ) { |
53 | $this->eventFactory = $eventFactory; |
54 | $this->permissionChecker = $permissionChecker; |
55 | $this->editEventCommand = $editEventCommand; |
56 | $this->organizersStore = $organizersStore; |
57 | $this->centralUserLookup = $centralUserLookup; |
58 | $this->eventQuestionsRegistry = $eventQuestionsRegistry; |
59 | $this->wikiLookup = $wikiLookup; |
60 | $this->eventWikisEnabled = $config->get( 'CampaignEventsEnableEventWikis' ); |
61 | } |
62 | |
63 | /** |
64 | * @inheritDoc |
65 | */ |
66 | public function validate( Validator $restValidator ): void { |
67 | parent::validate( $restValidator ); |
68 | $this->validateToken(); |
69 | } |
70 | |
71 | /** |
72 | * @param ICampaignsAuthority $performer |
73 | */ |
74 | abstract protected function checkPermissions( ICampaignsAuthority $performer ): void; |
75 | |
76 | /** |
77 | * @inheritDoc |
78 | */ |
79 | public function execute() { |
80 | $body = $this->getValidatedBody(); |
81 | |
82 | $performer = new MWAuthorityProxy( $this->getAuthority() ); |
83 | $this->checkPermissions( $performer ); |
84 | |
85 | try { |
86 | $event = $this->createEventObject( $body ); |
87 | } catch ( InvalidEventDataException $e ) { |
88 | $this->exitWithStatus( $e->getStatus() ); |
89 | } |
90 | |
91 | $eventID = $event->getID(); |
92 | if ( $eventID === null ) { |
93 | $organizerNames = [ $this->getAuthority()->getUser()->getName() ]; |
94 | } else { |
95 | $organizers = $this->organizersStore->getEventOrganizers( $eventID ); |
96 | $organizerNames = []; |
97 | foreach ( $organizers as $organizer ) { |
98 | $user = $organizer->getUser(); |
99 | try { |
100 | $organizerNames[] = $this->centralUserLookup->getUserName( $user ); |
101 | } catch ( UserNotGlobalException $_ ) { |
102 | // Should never happen. |
103 | throw new RuntimeException( "Organizer in the database has no central account." ); |
104 | } |
105 | } |
106 | } |
107 | |
108 | $saveStatus = $this->editEventCommand->doEditIfAllowed( $event, $performer, $organizerNames ); |
109 | if ( !$saveStatus->isOK() ) { |
110 | $httptStatus = $saveStatus instanceof PermissionStatus ? 403 : 400; |
111 | $this->exitWithStatus( $saveStatus, $httptStatus ); |
112 | } |
113 | |
114 | return $this->getSuccessResponse( $saveStatus ); |
115 | } |
116 | |
117 | /** |
118 | * @param StatusValue $saveStatus |
119 | * @return Response |
120 | */ |
121 | abstract protected function getSuccessResponse( StatusValue $saveStatus ): Response; |
122 | |
123 | /** |
124 | * @return array |
125 | */ |
126 | public function getBodyParamSettings(): array { |
127 | $params = [ |
128 | 'event_page' => [ |
129 | static::PARAM_SOURCE => 'body', |
130 | ParamValidator::PARAM_TYPE => 'title', |
131 | ParamValidator::PARAM_REQUIRED => true, |
132 | ], |
133 | 'chat_url' => [ |
134 | static::PARAM_SOURCE => 'body', |
135 | ParamValidator::PARAM_TYPE => 'string', |
136 | ], |
137 | 'tracking_tool_id' => [ |
138 | static::PARAM_SOURCE => 'body', |
139 | ParamValidator::PARAM_TYPE => 'string', |
140 | ], |
141 | 'tracking_tool_event_id' => [ |
142 | static::PARAM_SOURCE => 'body', |
143 | ParamValidator::PARAM_TYPE => 'string', |
144 | ], |
145 | 'timezone' => [ |
146 | static::PARAM_SOURCE => 'body', |
147 | ParamValidator::PARAM_TYPE => 'string', |
148 | ParamValidator::PARAM_REQUIRED => true, |
149 | ], |
150 | 'start_time' => [ |
151 | static::PARAM_SOURCE => 'body', |
152 | ParamValidator::PARAM_TYPE => 'timestamp', |
153 | TimestampDef::PARAM_TIMESTAMP_FORMAT => TS_MW, |
154 | ParamValidator::PARAM_REQUIRED => true, |
155 | ], |
156 | 'end_time' => [ |
157 | static::PARAM_SOURCE => 'body', |
158 | ParamValidator::PARAM_TYPE => 'timestamp', |
159 | TimestampDef::PARAM_TIMESTAMP_FORMAT => TS_MW, |
160 | ParamValidator::PARAM_REQUIRED => true, |
161 | ], |
162 | /* TODO MVP: Re-add this |
163 | 'type' => [ |
164 | static::PARAM_SOURCE => 'body', |
165 | ParamValidator::PARAM_TYPE => EventRegistration::VALID_TYPES, |
166 | ParamValidator::PARAM_REQUIRED => true, |
167 | ], |
168 | */ |
169 | 'online_meeting' => [ |
170 | static::PARAM_SOURCE => 'body', |
171 | ParamValidator::PARAM_TYPE => 'boolean', |
172 | ], |
173 | 'inperson_meeting' => [ |
174 | static::PARAM_SOURCE => 'body', |
175 | ParamValidator::PARAM_TYPE => 'boolean', |
176 | ], |
177 | 'meeting_url' => [ |
178 | static::PARAM_SOURCE => 'body', |
179 | ParamValidator::PARAM_TYPE => 'string', |
180 | ], |
181 | 'meeting_country' => [ |
182 | static::PARAM_SOURCE => 'body', |
183 | ParamValidator::PARAM_TYPE => 'string', |
184 | ], |
185 | 'meeting_address' => [ |
186 | static::PARAM_SOURCE => 'body', |
187 | ParamValidator::PARAM_TYPE => 'string', |
188 | ], |
189 | ] + $this->getTokenParamDefinition(); |
190 | |
191 | if ( $this->eventWikisEnabled ) { |
192 | $params['wikis'] = [ |
193 | static::PARAM_SOURCE => 'body', |
194 | ParamValidator::PARAM_TYPE => $this->wikiLookup->getAllWikis(), |
195 | ParamValidator::PARAM_ISMULTI => true, |
196 | ParamValidator::PARAM_ISMULTI_LIMIT1 => EventFactory::MAX_WIKIS, |
197 | ParamValidator::PARAM_ALL => true, |
198 | ParamValidator::PARAM_REQUIRED => true, |
199 | ]; |
200 | } |
201 | |
202 | return $params; |
203 | } |
204 | |
205 | /** |
206 | * Creates an EventRegistration object with the data from the request body, with |
207 | * appropriate validation. |
208 | * |
209 | * @param array $body Request body data |
210 | * @return EventRegistration |
211 | * @throws InvalidEventDataException |
212 | */ |
213 | abstract protected function createEventObject( array $body ): EventRegistration; |
214 | } |