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