MediaWiki master
ApiProtect.php
Go to the documentation of this file.
1<?php
29
33class ApiProtect extends ApiBase {
34
36
37 private RestrictionStore $restrictionStore;
38
46 public function __construct(
47 ApiMain $mainModule,
48 $moduleName,
49 WatchlistManager $watchlistManager,
50 UserOptionsLookup $userOptionsLookup,
51 RestrictionStore $restrictionStore
52 ) {
53 parent::__construct( $mainModule, $moduleName );
54 $this->restrictionStore = $restrictionStore;
55
56 // Variables needed in ApiWatchlistTrait trait
57 $this->watchlistExpiryEnabled = $this->getConfig()->get( MainConfigNames::WatchlistExpiry );
58 $this->watchlistMaxDuration =
59 $this->getConfig()->get( MainConfigNames::WatchlistExpiryMaxDuration );
60 $this->watchlistManager = $watchlistManager;
61 $this->userOptionsLookup = $userOptionsLookup;
62 }
63
64 public function execute() {
66
67 $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
68 $titleObj = $pageObj->getTitle();
69 $this->getErrorFormatter()->setContextTitle( $titleObj );
70
71 $this->checkTitleUserPermissions( $titleObj, 'protect' );
72
73 $user = $this->getUser();
74 $tags = $params['tags'];
75
76 // Check if user can add tags
77 if ( $tags !== null ) {
78 $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $tags, $this->getAuthority() );
79 if ( !$ableToTag->isOK() ) {
80 $this->dieStatus( $ableToTag );
81 }
82 }
83
84 $expiry = (array)$params['expiry'];
85 if ( count( $expiry ) != count( $params['protections'] ) ) {
86 if ( count( $expiry ) == 1 ) {
87 $expiry = array_fill( 0, count( $params['protections'] ), $expiry[0] );
88 } else {
89 $this->dieWithError( [
90 'apierror-toofewexpiries',
91 count( $expiry ),
92 count( $params['protections'] )
93 ] );
94 }
95 }
96
97 $restrictionTypes = $this->restrictionStore->listApplicableRestrictionTypes( $titleObj );
98 $levels = $this->getPermissionManager()->getNamespaceRestrictionLevels(
99 $titleObj->getNamespace(),
100 $user
101 );
102
103 $protections = [];
104 $expiryarray = [];
105 $resultProtections = [];
106 foreach ( $params['protections'] as $i => $prot ) {
107 $p = explode( '=', $prot );
108 $protections[$p[0]] = ( $p[1] == 'all' ? '' : $p[1] );
109
110 if ( $titleObj->exists() && $p[0] == 'create' ) {
111 $this->dieWithError( 'apierror-create-titleexists' );
112 }
113 if ( !$titleObj->exists() && $p[0] != 'create' ) {
114 $this->dieWithError( 'apierror-missingtitle-createonly' );
115 }
116
117 if ( !in_array( $p[0], $restrictionTypes ) && $p[0] != 'create' ) {
118 $this->dieWithError( [ 'apierror-protect-invalidaction', wfEscapeWikiText( $p[0] ) ] );
119 }
120 if ( !in_array( $p[1], $levels ) && $p[1] != 'all' ) {
121 $this->dieWithError( [ 'apierror-protect-invalidlevel', wfEscapeWikiText( $p[1] ) ] );
122 }
123
124 if ( wfIsInfinity( $expiry[$i] ) ) {
125 $expiryarray[$p[0]] = 'infinity';
126 } else {
127 $exp = strtotime( $expiry[$i] );
128 if ( $exp < 0 || !$exp ) {
129 $this->dieWithError( [ 'apierror-invalidexpiry', wfEscapeWikiText( $expiry[$i] ) ] );
130 }
131
132 $exp = wfTimestamp( TS_MW, $exp );
133 if ( $exp < wfTimestampNow() ) {
134 $this->dieWithError( [ 'apierror-pastexpiry', wfEscapeWikiText( $expiry[$i] ) ] );
135 }
136 $expiryarray[$p[0]] = $exp;
137 }
138 $resultProtections[] = [
139 $p[0] => $protections[$p[0]],
140 'expiry' => ApiResult::formatExpiry( $expiryarray[$p[0]], 'infinite' ),
141 ];
142 }
143
144 $cascade = $params['cascade'];
145
146 $watch = $params['watch'] ? 'watch' : $params['watchlist'];
147 $watchlistExpiry = $this->getExpiryFromParams( $params );
148 $this->setWatch( $watch, $titleObj, $user, 'watchdefault', $watchlistExpiry );
149
150 $status = $pageObj->doUpdateRestrictions(
151 $protections,
152 $expiryarray,
153 $cascade,
154 $params['reason'],
155 $user,
156 $tags ?? []
157 );
158
159 if ( !$status->isOK() ) {
160 $this->dieStatus( $status );
161 }
162 $res = [
163 'title' => $titleObj->getPrefixedText(),
164 'reason' => $params['reason']
165 ];
166 if ( $cascade ) {
167 $res['cascade'] = true;
168 }
169 $res['protections'] = $resultProtections;
170 $result = $this->getResult();
171 ApiResult::setIndexedTagName( $res['protections'], 'protection' );
172 $result->addValue( null, $this->getModuleName(), $res );
173 }
174
175 public function mustBePosted() {
176 return true;
177 }
178
179 public function isWriteMode() {
180 return true;
181 }
182
183 public function getAllowedParams() {
184 return [
185 'title' => [
186 ParamValidator::PARAM_TYPE => 'string',
187 ],
188 'pageid' => [
189 ParamValidator::PARAM_TYPE => 'integer',
190 ],
191 'protections' => [
192 ParamValidator::PARAM_ISMULTI => true,
193 ParamValidator::PARAM_REQUIRED => true,
194 ],
195 'expiry' => [
196 ParamValidator::PARAM_ISMULTI => true,
197 ParamValidator::PARAM_ALLOW_DUPLICATES => true,
198 ParamValidator::PARAM_DEFAULT => 'infinite',
199 ],
200 'reason' => '',
201 'tags' => [
202 ParamValidator::PARAM_TYPE => 'tags',
203 ParamValidator::PARAM_ISMULTI => true,
204 ],
205 'cascade' => false,
206 'watch' => [
207 ParamValidator::PARAM_DEFAULT => false,
208 ParamValidator::PARAM_DEPRECATED => true,
209 ],
210 ] + $this->getWatchlistParams();
211 }
212
213 public function needsToken() {
214 return 'csrf';
215 }
216
217 protected function getExamplesMessages() {
218 $title = Title::newMainPage()->getPrefixedText();
219 $mp = rawurlencode( $title );
220
221 return [
222 "action=protect&title={$mp}&token=123ABC&" .
223 'protections=edit=sysop|move=sysop&cascade=&expiry=20070901163000|never'
224 => 'apihelp-protect-example-protect',
225 "action=protect&title={$mp}&token=123ABC&" .
226 'protections=edit=all|move=all&reason=Lifting%20restrictions'
227 => 'apihelp-protect-example-unprotect',
228 "action=protect&title={$mp}&token=123ABC&" .
229 'protections=&reason=Lifting%20restrictions'
230 => 'apihelp-protect-example-unprotect2',
231 ];
232 }
233
234 public function getHelpUrls() {
235 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Protect';
236 }
237}
getExpiryFromParams(array $params)
Get formatted expiry from the given parameters, or null if no expiry was provided.
setWatch(string $watch, Title $title, User $user, ?string $userOption=null, ?string $expiry=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
getWatchlistParams(array $watchOptions=[])
Get additional allow params specific to watchlisting.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfIsInfinity( $str)
Determine input string is represents as infinity.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
array $params
The job parameters.
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:64
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1542
checkTitleUserPermissions(PageIdentity $pageIdentity, $actions, array $options=[])
Helper function for permission-denied errors.
Definition ApiBase.php:1681
getErrorFormatter()
Definition ApiBase.php:691
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition ApiBase.php:740
getResult()
Get the result object.
Definition ApiBase.php:680
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:820
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:541
getTitleOrPageId( $params, $load=false)
Attempts to load a WikiPage object from a title or pageid parameter, if possible.
Definition ApiBase.php:1107
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition ApiBase.php:1598
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:65
isWriteMode()
Indicates whether this module requires write mode.
getExamplesMessages()
Returns usage examples for this module.
needsToken()
Returns the token type this module requires in order to execute.
__construct(ApiMain $mainModule, $moduleName, WatchlistManager $watchlistManager, UserOptionsLookup $userOptionsLookup, RestrictionStore $restrictionStore)
mustBePosted()
Indicates whether this module must be called with a POST request.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getHelpUrls()
Return links to more detailed help pages about the module.
static canAddTagsAccompanyingChange(array $tags, Authority $performer=null, $checkBlock=true)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
A class containing constants representing the names of configuration variables.
Represents a title within MediaWiki.
Definition Title.php:78
Provides access to user options.
Service for formatting and validating API parameters.
trait ApiWatchlistTrait
An ApiWatchlistTrait adds class properties and convenience methods for APIs that allow you to watch a...