Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.88% covered (success)
96.88%
31 / 32
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PageEventLookup
96.88% covered (success)
96.88%
31 / 32
75.00% covered (warning)
75.00%
3 / 4
16
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getRegistrationForLocalPage
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 getRegistrationForPage
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
6.02
 getCanonicalPage
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare( strict_types=1 );
4
5namespace MediaWiki\Extension\CampaignEvents\Event;
6
7use MediaWiki\DAO\WikiAwareEntity;
8use MediaWiki\Extension\CampaignEvents\Event\Store\EventNotFoundException;
9use MediaWiki\Extension\CampaignEvents\Event\Store\IEventLookup;
10use MediaWiki\Extension\CampaignEvents\MWEntity\CampaignsPageFactory;
11use MediaWiki\Extension\CampaignEvents\MWEntity\ICampaignsPage;
12use MediaWiki\Extension\CampaignEvents\MWEntity\MWPageProxy;
13use MediaWiki\Extension\Translate\PageTranslation\TranslatablePage;
14use MediaWiki\Linker\LinkTarget;
15use MediaWiki\Page\PageIdentity;
16use MediaWiki\Title\TitleFactory;
17use RuntimeException;
18use Wikimedia\Rdbms\IDBAccessObject;
19
20/**
21 * This class is responsible for finding the event registration associated with a given page. This includes
22 * canonicalizing the page, in case the same event is associated with multiple pages.
23 */
24class PageEventLookup {
25    public const SERVICE_NAME = 'CampaignEventsPageEventLookup';
26
27    public const GET_CANONICALIZE = 'canonicalize';
28    public const GET_DIRECT = 'direct';
29
30    private IEventLookup $eventLookup;
31    private CampaignsPageFactory $campaignsPageFactory;
32    private TitleFactory $titleFactory;
33    private bool $isTranslateExtensionInstalled;
34
35    /**
36     * @param IEventLookup $eventLookup
37     * @param CampaignsPageFactory $campaignsPageFactory
38     * @param TitleFactory $titleFactory
39     * @param bool $isTranslateExtensionInstalled
40     */
41    public function __construct(
42        IEventLookup $eventLookup,
43        CampaignsPageFactory $campaignsPageFactory,
44        TitleFactory $titleFactory,
45        bool $isTranslateExtensionInstalled
46    ) {
47        $this->eventLookup = $eventLookup;
48        $this->campaignsPageFactory = $campaignsPageFactory;
49        $this->titleFactory = $titleFactory;
50        $this->isTranslateExtensionInstalled = $isTranslateExtensionInstalled;
51    }
52
53    /**
54     * @param PageIdentity|LinkTarget $page
55     * @param string $canonicalize self::GET_CANONICALIZE to canonicalize the given page, or self::GET_DIRECT to
56     * avoid canonicalization.
57     * @param int $readFlags One of the IDBAccessObject::READ_* constants
58     * @return ExistingEventRegistration|null
59     */
60    public function getRegistrationForLocalPage(
61        $page,
62        string $canonicalize = self::GET_CANONICALIZE,
63        int $readFlags = IDBAccessObject::READ_NORMAL
64    ): ?ExistingEventRegistration {
65        if ( $canonicalize === self::GET_CANONICALIZE ) {
66            $page = $this->getCanonicalPage( $page );
67        }
68
69        if ( $page->getNamespace() !== NS_EVENT ) {
70            return null;
71        }
72
73        $campaignsPage = $this->campaignsPageFactory->newFromLocalMediaWikiPage( $page );
74        try {
75            return $this->eventLookup->getEventByPage( $campaignsPage, $readFlags );
76        } catch ( EventNotFoundException $_ ) {
77            return null;
78        }
79    }
80
81    /**
82     * @param ICampaignsPage $page
83     * @param string $canonicalize self::GET_CANONICALIZE to canonicalize the given page, or self::GET_DIRECT to
84     * avoid canonicalization.
85     * @return ExistingEventRegistration|null
86     */
87    public function getRegistrationForPage(
88        ICampaignsPage $page,
89        string $canonicalize = self::GET_CANONICALIZE
90    ): ?ExistingEventRegistration {
91        if ( !$page instanceof MWPageProxy ) {
92            throw new RuntimeException( 'Unexpected ICampaignsPage implementation.' );
93        }
94
95        if ( $canonicalize === self::GET_CANONICALIZE ) {
96            $pageIdentity = $page->getPageIdentity();
97            $canonicalPageIdentity = $this->getCanonicalPage( $pageIdentity );
98            if ( $canonicalPageIdentity !== $pageIdentity ) {
99                $page = $this->campaignsPageFactory->newFromLocalMediaWikiPage( $canonicalPageIdentity );
100            }
101        }
102
103        if ( $page->getNamespace() !== NS_EVENT ) {
104            return null;
105        }
106
107        try {
108            return $this->eventLookup->getEventByPage( $page );
109        } catch ( EventNotFoundException $_ ) {
110            return null;
111        }
112    }
113
114    /**
115     * @param PageIdentity|LinkTarget $page
116     * @return PageIdentity
117     */
118    private function getCanonicalPage( $page ): PageIdentity {
119        // XXX: Can't canonicalize foreign pages.
120        if ( $this->isTranslateExtensionInstalled && $page->getWikiId() === WikiAwareEntity::LOCAL ) {
121            $title = $page instanceof PageIdentity
122                ? $this->titleFactory->newFromPageIdentity( $page )
123                : $this->titleFactory->newFromLinkTarget( $page );
124            $transPage = TranslatablePage::isTranslationPage( $title );
125            if ( $transPage ) {
126                // If this is a translation subpage, look up the source page instead (T357716)
127                return $transPage->getPageIdentity();
128            }
129        }
130        return $page;
131    }
132}