Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
68.89% covered (warning)
68.89%
31 / 45
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
CampaignContentHandler
68.89% covered (warning)
68.89%
31 / 45
50.00% covered (danger)
50.00%
3 / 6
19.90
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getContentClass
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeEmptyContent
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 preSaveTransform
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 fillParserOutput
60.00% covered (warning)
60.00%
18 / 30
0.00% covered (danger)
0.00%
0 / 1
6.60
 registerTemplates
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace MediaWiki\Extension\MediaUploader\Campaign;
4
5use Content;
6use Html;
7use MediaWiki\Content\Renderer\ContentParseParams;
8use MediaWiki\Content\Transform\PreSaveTransformParams;
9use MediaWiki\Extension\MediaUploader\Campaign\Exception\BaseCampaignException;
10use MediaWiki\Extension\MediaUploader\Config\ConfigFactory;
11use MediaWiki\Extension\MediaUploader\Config\ParsedConfig;
12use MediaWiki\Extension\MediaUploader\MediaUploaderServices;
13use ParserOutput;
14use TextContentHandler;
15use Title;
16
17/**
18 * Content handler for campaign pages.
19 */
20class CampaignContentHandler extends TextContentHandler {
21
22    /** @var ConfigFactory */
23    private $configFactory;
24
25    /**
26     * @param string $modelId
27     * @param ConfigFactory $configFactory
28     */
29    public function __construct( $modelId, ConfigFactory $configFactory ) {
30        parent::__construct( $modelId, [ CONTENT_FORMAT_CAMPAIGN ] );
31        $this->configFactory = $configFactory;
32    }
33
34    /**
35     * @return class-string<CampaignContent>
36     */
37    protected function getContentClass() {
38        return CampaignContent::class;
39    }
40
41    /**
42     * @return CampaignContent
43     */
44    public function makeEmptyContent() {
45        return new CampaignContent( 'enabled: false' );
46    }
47
48    /**
49     * Normalizes line endings before saving.
50     *
51     * @param Content $content
52     * @param PreSaveTransformParams $pstParams
53     *
54     * @return CampaignContent
55     */
56    public function preSaveTransform( Content $content, PreSaveTransformParams $pstParams ): Content {
57        /** @var CampaignContent $content */
58        '@phan-var CampaignContent $content';
59        // Allow the system user to bypass format and schema checks
60        if ( MediaUploaderServices::isSystemUser( $pstParams->getUser() ) ) {
61            $content->overrideValidationStatus();
62        }
63
64        if ( !$content->isValid() ) {
65            return $content;
66        }
67
68        return $content->copyWithNewText(
69            CampaignContent::normalizeLineEndings( $content->getText() )
70        );
71    }
72
73    /**
74     * @inheritDoc
75     */
76    public function fillParserOutput(
77        Content $content, ContentParseParams $cpoParams, ParserOutput &$output
78    ) {
79        /** @var CampaignContent $content */
80        '@phan-var CampaignContent $content';
81        $page = $cpoParams->getPage();
82        if ( $page->getDBkey() === CampaignContent::GLOBAL_CONFIG_ANCHOR_DBKEY ) {
83            // Handle the case of the global config anchor.
84            // We ignore config cache as this function may have been called by a
85            // recursive LinksUpdate, which means there are probably some templates
86            // that this config depends on that have changed. It's also possible
87            // that this was caused by a null edit by GlobalConfigAnchorUpdateJob,
88            // but then it still is safer to reparse the config than rely on cache
89            // that may be out of date.
90            $config = $this->configFactory->newGlobalConfig(
91                $cpoParams->getParserOptions(),
92                [],
93                true
94            );
95
96            $this->registerTemplates( $config, $output );
97
98            if ( $cpoParams->getGenerateHtml() ) {
99                $output->setText(
100                    wfMessage( 'mediauploader-global-config-anchor' )->parseAsBlock()
101                );
102            }
103            return;
104        }
105
106        // Handle a regular campaign.
107        $record = $content->newCampaignRecord( $cpoParams->getPage() );
108
109        try {
110            // Page ref and content will always be set, no need to check that.
111            $record->assertValid( $cpoParams->getPage()->getDBkey() );
112        } catch ( BaseCampaignException $e ) {
113            $output->setText( Html::errorBox( $e->getMessage() ) );
114            return;
115        }
116
117        // Here we also ignore the cache, as there's no way to tell whether
118        // it's just someone viewing the page and parser cache has expired, or there
119        // was an actual edit or a LinksUpdate. We can't defer this until later
120        // (like PageSaveComplete or LinksUpdateComplete), because we can't modify
121        // ParserOutput at those points. We need an up-to-date list of templates here
122        // and now.
123        $campaignConfig = $this->configFactory->newCampaignConfig(
124            $cpoParams->getParserOptions(),
125            $record,
126            $page,
127            [],
128            true
129        );
130
131        if ( $cpoParams->getGenerateHtml() ) {
132            $formatter = new CampaignPageFormatter( $record, $campaignConfig );
133            $formatter->fillParserOutput( $output );
134        }
135
136        $this->registerTemplates( $campaignConfig, $output );
137
138        // Add some styles
139        $output->addModuleStyles( [ 'ext.uploadWizard.uploadCampaign.display' ] );
140    }
141
142    /**
143     * Registers templates used in a ParsedConfig with a ParserOutput.
144     *
145     * @param ParsedConfig $parsedConfig
146     * @param ParserOutput $parserOutput
147     */
148    private function registerTemplates(
149        ParsedConfig $parsedConfig,
150        ParserOutput $parserOutput
151    ): void {
152        // FIXME: should we be registering other stuff??
153        foreach ( $parsedConfig->getTemplates() as $ns => $templates ) {
154            foreach ( $templates as $dbk => $ids ) {
155                $title = Title::makeTitle( $ns, $dbk );
156                $parserOutput->addTemplate( $title, $ids[0], $ids[1] );
157            }
158        }
159    }
160}