Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.00% covered (success)
92.00%
69 / 75
75.00% covered (warning)
75.00%
6 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiChangeContentModel
93.24% covered (success)
93.24%
69 / 74
75.00% covered (warning)
75.00%
6 / 8
15.07
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
 execute
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
1 / 1
6
 getAllowedParams
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
3
 mustBePosted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isWriteMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 needsToken
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHelpUrls
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Api;
4
5use MediaWiki\Content\IContentHandlerFactory;
6use MediaWiki\Page\ContentModelChangeFactory;
7use Wikimedia\ParamValidator\ParamValidator;
8use Wikimedia\Rdbms\IDBAccessObject;
9
10/**
11 * Api module to change the content model of existing pages
12 *
13 * For new pages, use the edit api and specify the desired content model and format.
14 *
15 * @since 1.35
16 * @ingroup API
17 * @author DannyS712
18 */
19class ApiChangeContentModel extends ApiBase {
20
21    public function __construct(
22        ApiMain $main,
23        string $action,
24        private readonly IContentHandlerFactory $contentHandlerFactory,
25        private readonly ContentModelChangeFactory $contentModelChangeFactory,
26    ) {
27        parent::__construct( $main, $action );
28    }
29
30    /**
31     * A lot of this code is based on SpecialChangeContentModel
32     */
33    public function execute() {
34        $params = $this->extractRequestParams();
35        $wikiPage = $this->getTitleOrPageId( $params );
36        $title = $wikiPage->getTitle();
37        $this->getErrorFormatter()->setContextTitle( $title );
38
39        if ( !$title->exists() ) {
40            $this->dieWithError( 'apierror-changecontentmodel-missingtitle' );
41        }
42
43        $newModel = $params['model'];
44
45        $this->checkUserRightsAny( 'editcontentmodel' );
46        $changer = $this->contentModelChangeFactory->newContentModelChange(
47            $this->getAuthority(),
48            $wikiPage,
49            $newModel
50        );
51        // Status messages should be apierror-*
52        $changer->setMessagePrefix( 'apierror-' );
53        $permissionStatus = $changer->authorizeChange();
54        if ( !$permissionStatus->isGood() ) {
55            $this->dieStatus( $permissionStatus );
56        }
57
58        if ( $params['tags'] ) {
59            $tagStatus = $changer->setTags( $params['tags'] );
60            if ( !$tagStatus->isGood() ) {
61                $this->dieStatus( $tagStatus );
62            }
63        }
64
65        // Everything passed, make the conversion
66        $status = $changer->doContentModelChange(
67            $this->getContext(),
68            $params['summary'] ?? '',
69            $params['bot']
70        );
71
72        if ( !$status->isGood() ) {
73            // Failed
74            $this->dieStatus( $status );
75        }
76        $logid = $status->getValue()['logid'];
77
78        $result = [
79            'result' => 'Success',
80            'title' => $title->getPrefixedText(),
81            'pageid' => $title->getArticleID(),
82            'contentmodel' => $title->getContentModel( IDBAccessObject::READ_LATEST ),
83            'logid' => $logid,
84            'revid' => $title->getLatestRevID( IDBAccessObject::READ_LATEST ),
85        ];
86
87        $this->getResult()->addValue( null, $this->getModuleName(), $result );
88    }
89
90    /** @inheritDoc */
91    public function getAllowedParams() {
92        $models = $this->contentHandlerFactory->getContentModels();
93        $modelOptions = [];
94        foreach ( $models as $model ) {
95            $handler = $this->contentHandlerFactory->getContentHandler( $model );
96            if ( !$handler->supportsDirectEditing() ) {
97                continue;
98            }
99            $modelOptions[] = $model;
100        }
101
102        return [
103            'title' => [
104                ParamValidator::PARAM_TYPE => 'string',
105            ],
106            'pageid' => [
107                ParamValidator::PARAM_TYPE => 'integer',
108            ],
109            'summary' => [
110                ParamValidator::PARAM_TYPE => 'string',
111            ],
112            'tags' => [
113                ParamValidator::PARAM_TYPE => 'tags',
114                ParamValidator::PARAM_ISMULTI => true,
115            ],
116            'model' => [
117                ParamValidator::PARAM_TYPE => $modelOptions,
118                ParamValidator::PARAM_REQUIRED => true,
119            ],
120            'bot' => false,
121        ];
122    }
123
124    /** @inheritDoc */
125    public function mustBePosted() {
126        return true;
127    }
128
129    /** @inheritDoc */
130    public function isWriteMode() {
131        return true;
132    }
133
134    /** @inheritDoc */
135    public function needsToken() {
136        return 'csrf';
137    }
138
139    /** @inheritDoc */
140    public function getHelpUrls() {
141        return 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel';
142    }
143
144    /** @inheritDoc */
145    protected function getExamplesMessages() {
146        return [
147            'action=changecontentmodel&title=Main Page&model=text&token=123ABC'
148                => 'apihelp-changecontentmodel-example'
149        ];
150    }
151}
152
153/** @deprecated class alias since 1.43 */
154class_alias( ApiChangeContentModel::class, 'ApiChangeContentModel' );