Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 116
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialAllEvents
0.00% covered (danger)
0.00%
0 / 116
0.00% covered (danger)
0.00%
0 / 5
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
2
 getFormAndEvents
0.00% covered (danger)
0.00%
0 / 90
0.00% covered (danger)
0.00%
0 / 1
30
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 formatDate
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare( strict_types=1 );
4
5namespace MediaWiki\Extension\CampaignEvents\Special;
6
7use MediaWiki\Extension\CampaignEvents\Event\EventRegistration;
8use MediaWiki\Extension\CampaignEvents\Hooks\CampaignEventsHookRunner;
9use MediaWiki\Extension\CampaignEvents\MWEntity\WikiLookup;
10use MediaWiki\Extension\CampaignEvents\Pager\EventsPagerFactory;
11use MediaWiki\HTMLForm\HTMLForm;
12use MediaWiki\SpecialPage\SpecialPage;
13use Wikimedia\Timestamp\ConvertibleTimestamp;
14use Wikimedia\Timestamp\TimestampException;
15
16class SpecialAllEvents extends SpecialPage {
17    public const PAGE_NAME = 'AllEvents';
18    private EventsPagerFactory $eventsPagerFactory;
19
20    private CampaignEventsHookRunner $hookRunner;
21    private WikiLookup $wikiLookup;
22
23    /**
24     * @param EventsPagerFactory $eventsPagerFactory
25     * @param CampaignEventsHookRunner $hookRunner
26     * @param WikiLookup $wikiLookup
27     */
28    public function __construct(
29        EventsPagerFactory $eventsPagerFactory,
30        CampaignEventsHookRunner $hookRunner,
31        WikiLookup $wikiLookup
32    ) {
33        parent::__construct( self::PAGE_NAME );
34        $this->eventsPagerFactory = $eventsPagerFactory;
35        $this->hookRunner = $hookRunner;
36        $this->wikiLookup = $wikiLookup;
37    }
38
39    /**
40     * @inheritDoc
41     */
42    public function execute( $subPage ): void {
43        $this->setHeaders();
44        $this->addHelpLink( 'Extension:CampaignEvents' );
45        $this->getOutput()->addModuleStyles( [
46            'ext.campaignEvents.specialPages.styles',
47            'oojs-ui.styles.icons-location',
48            'oojs-ui.styles.icons-interactions',
49            'oojs-ui.styles.icons-wikimedia',
50            'oojs-ui.styles.icons-user',
51            'oojs-ui.styles.icons-editing-advanced'
52        ] );
53        $this->getOutput()->addModules( [ 'ext.campaignEvents.specialPages' ] );
54        $eventsContent = $this->getFormAndEvents();
55        $this->hookRunner->onCampaignEventsGetAllEventsContent(
56            $this->getOutput(),
57            $eventsContent
58        );
59        $this->getOutput()->addHTML( $eventsContent );
60    }
61
62    public function getFormAndEvents(): string {
63        $request = $this->getRequest();
64        $searchedVal = $request->getVal( 'wpSearch', '' );
65        $filterWiki = $request->getArray( 'wpFilterWikis', [] );
66        $meetingType = $request->getIntOrNull( 'wpMeetingType' );
67        $rawStartTime = $request->getVal( 'wpStartDate', (string)time() );
68        $startTime = $rawStartTime === '' ? '' : $this->formatDate( $rawStartTime, 'Y-m-d 00:00:00' );
69        $rawEndTime = $request->getVal( 'wpEndDate', '' );
70        $endTime = $rawEndTime === '' ? '' : $this->formatDate( $rawEndTime, 'Y-m-d 23:59:59' );
71
72        $showOngoing = true;
73        // Use a form identifier to tell whether the form has already been submitted or not, otherwise we can't
74        // distinguish between form not submitted and form submitted but checkbox unchecked. This is important because
75        // the checkbox is checked by default.
76        // Note that we can't do all this in a submit callback because the pager needs to be instantiated before the
77        // HTMLForm, due to the "limit" field.
78        $formIdentifier = 'campaignevents-allevents';
79        if ( $request->getVal( 'wpFormIdentifier' ) === $formIdentifier ) {
80            $showOngoing = $request->getCheck( 'wpShowOngoing' );
81        }
82
83        $pager = $this->eventsPagerFactory->newListPager(
84            $searchedVal,
85            $meetingType,
86            $startTime,
87            $endTime,
88            $showOngoing,
89            $filterWiki
90        );
91
92        $formDescriptor = [
93            'Search' => [
94                'type' => 'text',
95                'label-message' => 'campaignevents-allevents-label-search',
96                'default' => $searchedVal,
97                'cssclass' => 'ext-campaignevents-allevents-search-field'
98            ],
99            'MeetingType' => [
100                'type' => 'select',
101                'label-message' => 'campaignevents-allevents-label-meeting-type',
102                'options-messages' => [
103                    'campaignevents-eventslist-location-all-events' => null,
104                    'campaignevents-eventslist-location-online' => EventRegistration::MEETING_TYPE_ONLINE,
105                    'campaignevents-eventslist-location-in-person' => EventRegistration::MEETING_TYPE_IN_PERSON,
106                    'campaignevents-eventslist-location-online-and-in-person' =>
107                        EventRegistration::MEETING_TYPE_ONLINE_AND_IN_PERSON
108                ],
109                'default' => $meetingType,
110                'cssclass' => 'ext-campaignevents-allevents-meetingtype-field'
111            ],
112            'StartDate' => [
113                'type' => 'datetime',
114                'label-message' => 'campaignevents-allevents-label-start-date',
115                'icon' => 'calendar',
116                'cssclass' => 'ext-campaignevents-allevents-calendar-start-field mw-htmlform-autoinfuse-lazy',
117                'default' => $this->formatDate( $startTime, 'Y-m-d\TH:i:s.000\Z' ),
118            ],
119            'EndDate' => [
120                'type' => 'datetime',
121                'label-message' => 'campaignevents-allevents-label-end-date',
122                'icon' => 'calendar',
123                'cssclass' => 'ext-campaignevents-allevents-calendar-end-field mw-htmlform-autoinfuse-lazy',
124                'default' => '',
125            ],
126            'ShowOngoing' => [
127                'type' => 'toggle',
128                'label-message' => 'campaignevents-allevents-label-show-ongoing',
129                'cssclass' => 'ext-campaignevents-allevents-show-ongoing-field',
130                'default' => true,
131            ],
132            'Limit' => [
133                // NOTE: This has to be called 'limit' because the pager expects that name.
134                'name' => 'limit',
135                'type' => 'select',
136                'label-message' => 'campaignevents-allevents-label-events-per-page',
137                'default' => $pager->getLimit(),
138                'options' => $pager->getLimitSelectList(),
139                'cssclass' => 'ext-campaignevents-allevents-filter-field'
140            ],
141        ];
142        if ( $this->getConfig()->get( 'CampaignEventsEnableEventWikis' ) ) {
143            $formDescriptor['FilterWikis'] = [
144                'type' => 'multiselect',
145                'dropdown' => true,
146                'label-message' => 'campaignevents-allevents-label-filter-wikis',
147                'options' => $this->wikiLookup->getListForSelect(),
148                'placeholder-message' => 'campaignevents-allevents-placeholder-add-wikis',
149                'max' => 10,
150                'cssclass' => 'ext-campaignevents-allevents-wikis-field',
151            ];
152        }
153        $form = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
154            ->setWrapperLegendMsg( 'campaignevents-allevents-filter-legend' )
155            ->setSubmitTextMsg( 'campaignevents-allevents-label-submit' )
156            ->setMethod( 'get' )
157            ->setId( 'ext-campaignevents-allevents-form' )
158            ->setSubmitCallback( fn () => true )
159            ->setFormIdentifier( $formIdentifier, true )
160            ->prepareForm();
161
162        $navigation = $pager->getNavigationBar();
163
164        $result = $form->tryAuthorizedSubmit();
165
166        return $form->getHTML( $result ) . $navigation . $pager->getBody() . $navigation;
167    }
168
169    /**
170     * @inheritDoc
171     */
172    protected function getGroupName(): string {
173        return 'campaignevents';
174    }
175
176    private function formatDate( string $date, string $format = 'Y-m-d' ): string {
177        try {
178            $date = ( new ConvertibleTimestamp( $date ) )->format( $format );
179        } catch ( TimestampException $exception ) {
180            return '';
181        }
182        return $date;
183    }
184}