Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ConfigHooks
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 4
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onEditFilterMergedContent
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
30
 onJsonValidateSave
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 onPageSaveComplete
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace AutoModerator\Config;
4
5use AutoModerator\Config\Validation\ConfigValidatorFactory;
6use MediaWiki\Config\Config;
7use MediaWiki\Content\Content;
8use MediaWiki\Content\Hook\JsonValidateSaveHook;
9use MediaWiki\Content\JsonContent;
10use MediaWiki\Content\TextContent;
11use MediaWiki\Context\IContextSource;
12use MediaWiki\Deferred\DeferredUpdates;
13use MediaWiki\Hook\EditFilterMergedContentHook;
14use MediaWiki\Json\FormatJson;
15use MediaWiki\Page\PageIdentity;
16use MediaWiki\Status\Status;
17use MediaWiki\Storage\Hook\PageSaveCompleteHook;
18use MediaWiki\Title\TitleFactory;
19use MediaWiki\Title\TitleValue;
20use MediaWiki\User\User;
21use StatusValue;
22
23class ConfigHooks implements
24    EditFilterMergedContentHook,
25    JsonValidateSaveHook,
26    PageSaveCompleteHook
27{
28    public function __construct(
29        private readonly ConfigValidatorFactory $configValidatorFactory,
30        private readonly WikiPageConfigLoader $configLoader,
31        private readonly TitleFactory $titleFactory,
32        private readonly Config $config,
33    ) {
34    }
35
36    /**
37     * @inheritDoc
38     */
39    public function onEditFilterMergedContent(
40        IContextSource $context,
41        Content $content,
42        Status $status,
43        $summary,
44        User $user,
45        $minoredit
46    ) {
47        // Check whether this is a config page edited
48        $title = $context->getTitle();
49        foreach ( $this->configValidatorFactory->getSupportedConfigPages() as $configTitle ) {
50            if ( $title->equals( $configTitle ) ) {
51                // Check content model
52                if (
53                    $content->getModel() !== CONTENT_MODEL_JSON ||
54                    !( $content instanceof TextContent )
55                ) {
56                    $status->fatal(
57                        'automoderator-config-validator-contentmodel-mismatch',
58                        $content->getModel()
59                    );
60                    return false;
61                }
62            }
63        }
64        return true;
65    }
66
67    /**
68     * @inheritDoc
69     */
70    public function onJsonValidateSave(
71        JsonContent $content, PageIdentity $pageIdentity, StatusValue $status
72    ) {
73        foreach ( $this->configValidatorFactory->getSupportedConfigPages() as $configTitle ) {
74            if ( $pageIdentity->isSamePageAs( $configTitle ) ) {
75                $data = FormatJson::parse( $content->getText(), FormatJson::FORCE_ASSOC )->getValue();
76                $status->merge(
77                    $this->configValidatorFactory
78                        // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
79                        ->newConfigValidator( TitleValue::castPageToLinkTarget( $pageIdentity ) )
80                        ->validate( $data )
81                );
82                if ( !$status->isGood() ) {
83                    // JsonValidateSave expects a fatal status on failure, but the validator uses isGood()
84                    $status->setOK( false );
85                }
86                return $status->isOK();
87            }
88        }
89    }
90
91    /**
92     * Invalidate configuration cache when needed.
93     * @inheritDoc
94     * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageSaveComplete
95     */
96    public function onPageSaveComplete(
97        $wikiPage, $user, $summary, $flags, $revisionRecord, $editResult
98    ) {
99        DeferredUpdates::addCallableUpdate( function () use ( $wikiPage ) {
100            $title = $wikiPage->getTitle();
101            foreach ( $this->configValidatorFactory->getSupportedConfigPages() as $configTitle ) {
102                if ( $title->equals( $configTitle ) ) {
103                    $this->configLoader->invalidate( $configTitle );
104                }
105            }
106        } );
107    }
108}