Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.76% covered (warning)
86.76%
59 / 68
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateEventRegistrationHandler
86.76% covered (warning)
86.76%
59 / 68
66.67% covered (warning)
66.67%
4 / 6
13.39
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 getParamSettings
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 getSuccessResponse
33.33% covered (danger)
33.33%
3 / 9
0.00% covered (danger)
0.00%
0 / 1
5.67
 getExistingEvent
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 checkPermissions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createEventObject
90.91% covered (success)
90.91%
30 / 33
0.00% covered (danger)
0.00%
0 / 1
5.02
1<?php
2
3declare( strict_types=1 );
4
5namespace MediaWiki\Extension\CampaignEvents\Rest;
6
7use LogicException;
8use MediaWiki\DAO\WikiAwareEntity;
9use MediaWiki\Extension\CampaignEvents\Event\EditEventCommand;
10use MediaWiki\Extension\CampaignEvents\Event\EventFactory;
11use MediaWiki\Extension\CampaignEvents\Event\EventRegistration;
12use MediaWiki\Extension\CampaignEvents\Event\ExistingEventRegistration;
13use MediaWiki\Extension\CampaignEvents\Event\Store\IEventLookup;
14use MediaWiki\Extension\CampaignEvents\MWEntity\CampaignsCentralUserLookup;
15use MediaWiki\Extension\CampaignEvents\MWEntity\ICampaignsAuthority;
16use MediaWiki\Extension\CampaignEvents\Organizers\OrganizersStore;
17use MediaWiki\Extension\CampaignEvents\Permissions\PermissionChecker;
18use MediaWiki\Extension\CampaignEvents\Questions\EventQuestionsRegistry;
19use MediaWiki\Extension\CampaignEvents\Questions\UnknownQuestionException;
20use MediaWiki\Rest\LocalizedHttpException;
21use MediaWiki\Rest\Response;
22use StatusValue;
23use Wikimedia\Message\MessageValue;
24use Wikimedia\ParamValidator\ParamValidator;
25
26class UpdateEventRegistrationHandler extends AbstractEditEventRegistrationHandler {
27    use EventIDParamTrait;
28
29    private IEventLookup $eventLookup;
30
31    /**
32     * @param EventFactory $eventFactory
33     * @param PermissionChecker $permissionChecker
34     * @param EditEventCommand $editEventCommand
35     * @param OrganizersStore $organizersStore
36     * @param CampaignsCentralUserLookup $centralUserLookup
37     * @param EventQuestionsRegistry $eventQuestionsRegistry
38     * @param IEventLookup $eventLookup
39     */
40    public function __construct(
41        EventFactory $eventFactory,
42        PermissionChecker $permissionChecker,
43        EditEventCommand $editEventCommand,
44        OrganizersStore $organizersStore,
45        CampaignsCentralUserLookup $centralUserLookup,
46        EventQuestionsRegistry $eventQuestionsRegistry,
47        IEventLookup $eventLookup
48    ) {
49        parent::__construct(
50            $eventFactory,
51            $permissionChecker,
52            $editEventCommand,
53            $organizersStore,
54            $centralUserLookup,
55            $eventQuestionsRegistry
56        );
57        $this->eventLookup = $eventLookup;
58    }
59
60    /**
61     * @inheritDoc
62     */
63    public function getParamSettings(): array {
64        return [
65            'status' => [
66                static::PARAM_SOURCE => 'body',
67                ParamValidator::PARAM_TYPE => EventRegistration::VALID_STATUSES,
68                ParamValidator::PARAM_REQUIRED => true,
69            ]
70        ] + $this->getIDParamSetting() + parent::getParamSettings();
71    }
72
73    /**
74     * @inheritDoc
75     */
76    protected function getSuccessResponse( StatusValue $saveStatus ): Response {
77        $warnings = $saveStatus->getMessages( 'warning' );
78        if ( !$warnings ) {
79            return $this->getResponseFactory()->createNoContent();
80        }
81        $respWarnings = [];
82        foreach ( $warnings as $msg ) {
83            // XXX There's no standard way to format warnings.
84            $respWarnings[] = [ 'key' => $msg->getKey(), 'params' => $msg->getParams() ];
85        }
86        return $this->getResponseFactory()->createJson( [
87            'warnings' => $respWarnings
88        ] );
89    }
90
91    /**
92     * @return ExistingEventRegistration
93     */
94    protected function getExistingEvent(): ExistingEventRegistration {
95        $id = $this->getValidatedParams()['id'];
96        $registration = $this->getRegistrationOrThrow( $this->eventLookup, $id );
97        $eventPageWikiID = $registration->getPage()->getWikiId();
98        if ( $eventPageWikiID !== WikiAwareEntity::LOCAL ) {
99            // TODO: This could redirect with a 3xx status code, but it's unclear how we may be able to obtain
100            // the REST endpoint URL for external wikis (T312568).
101            throw new LocalizedHttpException(
102                MessageValue::new( 'campaignevents-rest-edit-page-nonlocal' )->params( $eventPageWikiID ),
103                400
104            );
105        }
106        return $registration;
107    }
108
109    /**
110     * @inheritDoc
111     */
112    protected function checkPermissions( ICampaignsAuthority $performer ): void {
113        // Nothing to check now. Deeper check will happen in EditEventCommand.
114    }
115
116    /**
117     * @inheritDoc
118     */
119    protected function createEventObject( array $body ): EventRegistration {
120        $existingEvent = $this->getExistingEvent();
121        $meetingType = 0;
122        if ( $body['online_meeting'] ) {
123            $meetingType |= EventRegistration::MEETING_TYPE_ONLINE;
124        }
125        if ( $body['inperson_meeting'] ) {
126            $meetingType |= EventRegistration::MEETING_TYPE_IN_PERSON;
127        }
128
129        $participantQuestionNames = [];
130        $currentQuestionIDs = $existingEvent->getParticipantQuestions();
131        foreach ( $currentQuestionIDs as $questionID ) {
132            try {
133                $participantQuestionNames[] = $this->eventQuestionsRegistry->dbIDToName( $questionID );
134            } catch ( UnknownQuestionException $e ) {
135                // TODO This could presumably happen if a question is removed. Maybe we should just ignore it in
136                // that case.
137                throw new LogicException( 'Unknown question in the database', 0, $e );
138            }
139        }
140
141        return $this->eventFactory->newEvent(
142            $existingEvent->getID(),
143            $body['event_page'],
144            $body['chat_url'],
145            $body['tracking_tool_id'],
146            $body['tracking_tool_event_id'],
147            $body['status'],
148            $body['timezone'],
149            $body['start_time'],
150            $body['end_time'],
151            // TODO MVP Get this from the request body
152            EventRegistration::TYPE_GENERIC,
153            $meetingType,
154            $body['meeting_url'],
155            $body['meeting_country'],
156            $body['meeting_address'],
157            $participantQuestionNames,
158            $existingEvent->getCreationTimestamp(),
159            $existingEvent->getLastEditTimestamp(),
160            $existingEvent->getDeletionTimestamp(),
161            EventFactory::VALIDATE_SKIP_DATES_PAST
162        );
163    }
164}