Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 33
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 / 33
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 / 4
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 Content;
7use MediaWiki\Config\Config;
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    private ConfigValidatorFactory $configValidatorFactory;
29    private WikiPageConfigLoader $configLoader;
30    private TitleFactory $titleFactory;
31    private Config $config;
32
33    /**
34     * @param ConfigValidatorFactory $configValidatorFactory
35     * @param WikiPageConfigLoader $configLoader
36     * @param TitleFactory $titleFactory
37     * @param Config $config
38     */
39    public function __construct(
40        ConfigValidatorFactory $configValidatorFactory,
41        WikiPageConfigLoader $configLoader,
42        TitleFactory $titleFactory,
43        Config $config
44    ) {
45        $this->configValidatorFactory = $configValidatorFactory;
46        $this->configLoader = $configLoader;
47        $this->titleFactory = $titleFactory;
48        $this->config = $config;
49    }
50
51    /**
52     * @inheritDoc
53     */
54    public function onEditFilterMergedContent(
55        IContextSource $context,
56        Content $content,
57        Status $status,
58        $summary,
59        User $user,
60        $minoredit
61    ) {
62        // Check whether this is a config page edited
63        $title = $context->getTitle();
64        foreach ( $this->configValidatorFactory->getSupportedConfigPages() as $configTitle ) {
65            if ( $title->equals( $configTitle ) ) {
66                // Check content model
67                if (
68                    $content->getModel() !== CONTENT_MODEL_JSON ||
69                    !( $content instanceof TextContent )
70                ) {
71                    $status->fatal(
72                        'automoderator-config-validator-contentmodel-mismatch',
73                        $content->getModel()
74                    );
75                    return false;
76                }
77            }
78        }
79        return true;
80    }
81
82    /**
83     * @inheritDoc
84     */
85    public function onJsonValidateSave(
86        JsonContent $content, PageIdentity $pageIdentity, StatusValue $status
87    ) {
88        foreach ( $this->configValidatorFactory->getSupportedConfigPages() as $configTitle ) {
89            if ( $pageIdentity->isSamePageAs( $configTitle ) ) {
90                $data = FormatJson::parse( $content->getText(), FormatJson::FORCE_ASSOC )->getValue();
91                $status->merge(
92                    $this->configValidatorFactory
93                        // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
94                        ->newConfigValidator( TitleValue::castPageToLinkTarget( $pageIdentity ) )
95                        ->validate( $data )
96                );
97                if ( !$status->isGood() ) {
98                    // JsonValidateSave expects a fatal status on failure, but the validator uses isGood()
99                    $status->setOK( false );
100                }
101                return $status->isOK();
102            }
103        }
104    }
105
106    /**
107     * Invalidate configuration cache when needed.
108     * @inheritDoc
109     * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageSaveComplete
110     */
111    public function onPageSaveComplete(
112        $wikiPage, $user, $summary, $flags, $revisionRecord, $editResult
113    ) {
114        DeferredUpdates::addCallableUpdate( function () use ( $wikiPage ) {
115            $title = $wikiPage->getTitle();
116            foreach ( $this->configValidatorFactory->getSupportedConfigPages() as $configTitle ) {
117                if ( $title->equals( $configTitle ) ) {
118                    $this->configLoader->invalidate( $configTitle );
119                }
120            }
121        } );
122    }
123}