Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
22.86% covered (danger)
22.86%
8 / 35
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
PageURLResolver
22.86% covered (danger)
22.86%
8 / 35
20.00% covered (danger)
20.00%
1 / 5
133.52
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUrl
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
4.18
 getFullUrl
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
 getCanonicalUrl
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
 getCacheKey
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare( strict_types=1 );
4
5namespace MediaWiki\Extension\CampaignEvents\MWEntity;
6
7use MediaWiki\DAO\WikiAwareEntity;
8use MediaWiki\Title\Title;
9use MediaWiki\Title\TitleFactory;
10use MediaWiki\WikiMap\WikiMap;
11use RuntimeException;
12use UnexpectedValueException;
13
14class PageURLResolver {
15    public const SERVICE_NAME = 'CampaignEventsPageURLResolver';
16
17    private TitleFactory $titleFactory;
18
19    /** @var string[] Cached results of getUrl() */
20    private array $urlCache = [];
21    /** @var string[] Cached results of getFullUrl() */
22    private array $fullUrlCache = [];
23    /** @var string[] Cached results of getCanonicalUrl() */
24    private array $canonicalUrlCache = [];
25
26    /**
27     * @param TitleFactory $titleFactory
28     */
29    public function __construct( TitleFactory $titleFactory ) {
30        $this->titleFactory = $titleFactory;
31    }
32
33    /**
34     * Returns the URL of a page. This could be a local URL (for local pages) or a full URL (for
35     * foreign wiki pages).
36     * @param ICampaignsPage $page
37     * @return string
38     */
39    public function getUrl( ICampaignsPage $page ): string {
40        if ( !$page instanceof MWPageProxy ) {
41            throw new UnexpectedValueException( 'Unknown campaigns page implementation: ' . get_class( $page ) );
42        }
43        $cacheKey = $this->getCacheKey( $page );
44        if ( !isset( $this->urlCache[$cacheKey] ) ) {
45            $wikiID = $page->getWikiId();
46            $this->urlCache[$cacheKey] = $wikiID === WikiAwareEntity::LOCAL
47                ? $this->titleFactory->castFromPageIdentity( $page->getPageIdentity() )->getLocalURL()
48                : WikiMap::getForeignURL( $wikiID, $page->getPrefixedText() );
49        }
50        return $this->urlCache[$cacheKey];
51    }
52
53    /**
54     * Returns the full URL of a page. Unlike getUrl, this is guaranteed to be the full URL even for local pages.
55     * @param ICampaignsPage $page
56     * @return string
57     */
58    public function getFullUrl( ICampaignsPage $page ): string {
59        if ( !$page instanceof MWPageProxy ) {
60            throw new UnexpectedValueException( 'Unknown campaigns page implementation: ' . get_class( $page ) );
61        }
62        $cacheKey = $this->getCacheKey( $page );
63        if ( !isset( $this->fullUrlCache[$cacheKey] ) ) {
64            $wikiID = $page->getWikiId();
65            $this->fullUrlCache[$cacheKey] = $wikiID === WikiAwareEntity::LOCAL
66                ? $this->titleFactory->castFromPageIdentity( $page->getPageIdentity() )->getFullURL()
67                : WikiMap::getForeignURL( $wikiID, $page->getPrefixedText() );
68        }
69        return $this->fullUrlCache[$cacheKey];
70    }
71
72    /**
73     * Returns the canonical URL of a page. This should be used for things like email notifications.
74     * @see Title::getCanonicalURL()
75     *
76     * @param ICampaignsPage $page
77     * @return string
78     */
79    public function getCanonicalUrl( ICampaignsPage $page ): string {
80        if ( !$page instanceof MWPageProxy ) {
81            throw new UnexpectedValueException( 'Unknown campaigns page implementation: ' . get_class( $page ) );
82        }
83        $cacheKey = $this->getCacheKey( $page );
84        if ( !isset( $this->canonicalUrlCache[$cacheKey] ) ) {
85            $wikiID = $page->getWikiId();
86            if ( $wikiID === WikiAwareEntity::LOCAL ) {
87                $this->canonicalUrlCache[$cacheKey] = $this->titleFactory
88                    ->castFromPageIdentity( $page->getPageIdentity() )
89                    ->getCanonicalURL();
90            } else {
91                $wiki = WikiMap::getWiki( $wikiID );
92                if ( !$wiki ) {
93                    throw new RuntimeException( "Cannot obtain reference to wiki $wikiID" );
94                }
95                $this->canonicalUrlCache[$cacheKey] = $wiki->getCanonicalUrl( $page->getPrefixedText() );
96            }
97        }
98        return $this->canonicalUrlCache[$cacheKey];
99    }
100
101    /**
102     * @param ICampaignsPage $page
103     * @return string
104     */
105    private function getCacheKey( ICampaignsPage $page ): string {
106        // No need to actually convert it to the wiki ID if it's local.
107        $wikiIDStr = $page->getWikiId() === WikiAwareEntity::LOCAL ? '' : $page->getWikiId();
108        return $wikiIDStr . '|' . $page->getPrefixedText();
109    }
110}