MediaWiki
REL1_19
|
00001 <?php 00030 abstract class Action { 00031 00036 protected $page; 00037 00042 protected $context; 00043 00048 protected $fields; 00049 00057 private final static function getClass( $action, array $overrides ) { 00058 global $wgActions; 00059 $action = strtolower( $action ); 00060 00061 if ( !isset( $wgActions[$action] ) ) { 00062 return null; 00063 } 00064 00065 if ( $wgActions[$action] === false ) { 00066 return false; 00067 } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) { 00068 return $overrides[$action]; 00069 } elseif ( $wgActions[$action] === true ) { 00070 return ucfirst( $action ) . 'Action'; 00071 } else { 00072 return $wgActions[$action]; 00073 } 00074 } 00075 00084 public final static function factory( $action, Page $page, IContextSource $context = null ) { 00085 $class = self::getClass( $action, $page->getActionOverrides() ); 00086 if ( $class ) { 00087 $obj = new $class( $page, $context ); 00088 return $obj; 00089 } 00090 return $class; 00091 } 00092 00102 public final static function getActionName( IContextSource $context ) { 00103 global $wgActions; 00104 00105 $request = $context->getRequest(); 00106 $actionName = $request->getVal( 'action', 'view' ); 00107 00108 // Check for disabled actions 00109 if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) { 00110 $actionName = 'nosuchaction'; 00111 } 00112 00113 // Workaround for bug #20966: inability of IE to provide an action dependent 00114 // on which submit button is clicked. 00115 if ( $actionName === 'historysubmit' ) { 00116 if ( $request->getBool( 'revisiondelete' ) ) { 00117 $actionName = 'revisiondelete'; 00118 } else { 00119 $actionName = 'view'; 00120 } 00121 } elseif ( $actionName == 'editredlink' ) { 00122 $actionName = 'edit'; 00123 } 00124 00125 // Trying to get a WikiPage for NS_SPECIAL etc. will result 00126 // in WikiPage::factory throwing "Invalid or virtual namespace -1 given." 00127 // For SpecialPages et al, default to action=view. 00128 if ( !$context->canUseWikiPage() ) { 00129 return 'view'; 00130 } 00131 00132 $action = Action::factory( $actionName, $context->getWikiPage() ); 00133 if ( $action instanceof Action ) { 00134 return $action->getName(); 00135 } 00136 00137 return 'nosuchaction'; 00138 } 00139 00146 public final static function exists( $name ) { 00147 return self::getClass( $name, array() ) !== null; 00148 } 00149 00154 public final function getContext() { 00155 if ( $this->context instanceof IContextSource ) { 00156 return $this->context; 00157 } 00158 return $this->page->getContext(); 00159 } 00160 00166 public final function getRequest() { 00167 return $this->getContext()->getRequest(); 00168 } 00169 00175 public final function getOutput() { 00176 return $this->getContext()->getOutput(); 00177 } 00178 00184 public final function getUser() { 00185 return $this->getContext()->getUser(); 00186 } 00187 00193 public final function getSkin() { 00194 return $this->getContext()->getSkin(); 00195 } 00196 00202 public final function getLanguage() { 00203 return $this->getContext()->getLanguage(); 00204 } 00205 00212 public final function getLang() { 00213 wfDeprecated( __METHOD__, '1.19' ); 00214 return $this->getLanguage(); 00215 } 00216 00221 public final function getTitle() { 00222 return $this->page->getTitle(); 00223 } 00224 00231 public final function msg() { 00232 $params = func_get_args(); 00233 return call_user_func_array( array( $this->getContext(), 'msg' ), $params ); 00234 } 00235 00242 protected function __construct( Page $page, IContextSource $context = null ) { 00243 $this->page = $page; 00244 $this->context = $context; 00245 } 00246 00251 public abstract function getName(); 00252 00258 public function getRestriction() { 00259 return null; 00260 } 00261 00270 protected function checkCanExecute( User $user ) { 00271 $right = $this->getRestriction(); 00272 if ( $right !== null ) { 00273 $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user ); 00274 if ( count( $errors ) ) { 00275 throw new PermissionsError( $right, $errors ); 00276 } 00277 } 00278 00279 if ( $this->requiresUnblock() && $user->isBlocked() ) { 00280 $block = $user->mBlock; 00281 throw new UserBlockedError( $block ); 00282 } 00283 00284 // This should be checked at the end so that the user won't think the 00285 // error is only temporary when he also don't have the rights to execute 00286 // this action 00287 if ( $this->requiresWrite() && wfReadOnly() ) { 00288 throw new ReadOnlyError(); 00289 } 00290 } 00291 00296 public function requiresWrite() { 00297 return true; 00298 } 00299 00304 public function requiresUnblock() { 00305 return true; 00306 } 00307 00312 protected function setHeaders() { 00313 $out = $this->getOutput(); 00314 $out->setRobotPolicy( "noindex,nofollow" ); 00315 $out->setPageTitle( $this->getPageTitle() ); 00316 $this->getOutput()->setSubtitle( $this->getDescription() ); 00317 $out->setArticleRelated( true ); 00318 } 00319 00325 protected function getPageTitle() { 00326 return $this->getTitle()->getPrefixedText(); 00327 } 00328 00334 protected function getDescription() { 00335 return wfMsgHtml( strtolower( $this->getName() ) ); 00336 } 00337 00344 public abstract function show(); 00345 00350 public abstract function execute(); 00351 } 00352 00353 abstract class FormAction extends Action { 00354 00359 protected abstract function getFormFields(); 00360 00365 protected function preText() { return ''; } 00366 00370 protected function postText() { return ''; } 00371 00376 protected function alterForm( HTMLForm $form ) {} 00377 00382 protected function getForm() { 00383 $this->fields = $this->getFormFields(); 00384 00385 // Give hooks a chance to alter the form, adding extra fields or text etc 00386 wfRunHooks( 'ActionModifyFormFields', array( $this->getName(), &$this->fields, $this->page ) ); 00387 00388 $form = new HTMLForm( $this->fields, $this->getContext() ); 00389 $form->setSubmitCallback( array( $this, 'onSubmit' ) ); 00390 00391 // Retain query parameters (uselang etc) 00392 $form->addHiddenField( 'action', $this->getName() ); // Might not be the same as the query string 00393 $params = array_diff_key( 00394 $this->getRequest()->getQueryValues(), 00395 array( 'action' => null, 'title' => null ) 00396 ); 00397 $form->addHiddenField( 'redirectparams', wfArrayToCGI( $params ) ); 00398 00399 $form->addPreText( $this->preText() ); 00400 $form->addPostText( $this->postText() ); 00401 $this->alterForm( $form ); 00402 00403 // Give hooks a chance to alter the form, adding extra fields or text etc 00404 wfRunHooks( 'ActionBeforeFormDisplay', array( $this->getName(), &$form, $this->page ) ); 00405 00406 return $form; 00407 } 00408 00416 public abstract function onSubmit( $data ); 00417 00423 public abstract function onSuccess(); 00424 00432 public function show() { 00433 $this->setHeaders(); 00434 00435 // This will throw exceptions if there's a problem 00436 $this->checkCanExecute( $this->getUser() ); 00437 00438 $form = $this->getForm(); 00439 if ( $form->show() ) { 00440 $this->onSuccess(); 00441 } 00442 } 00443 00451 public function execute( array $data = null, $captureErrors = true ) { 00452 try { 00453 // Set a new context so output doesn't leak. 00454 $this->context = clone $this->page->getContext(); 00455 00456 // This will throw exceptions if there's a problem 00457 $this->checkCanExecute( $this->getUser() ); 00458 00459 $fields = array(); 00460 foreach ( $this->fields as $key => $params ) { 00461 if ( isset( $data[$key] ) ) { 00462 $fields[$key] = $data[$key]; 00463 } elseif ( isset( $params['default'] ) ) { 00464 $fields[$key] = $params['default']; 00465 } else { 00466 $fields[$key] = null; 00467 } 00468 } 00469 $status = $this->onSubmit( $fields ); 00470 if ( $status === true ) { 00471 // This might do permanent stuff 00472 $this->onSuccess(); 00473 return true; 00474 } else { 00475 return false; 00476 } 00477 } 00478 catch ( ErrorPageError $e ) { 00479 if ( $captureErrors ) { 00480 return false; 00481 } else { 00482 throw $e; 00483 } 00484 } 00485 } 00486 } 00487 00493 abstract class FormlessAction extends Action { 00494 00500 public abstract function onView(); 00501 00505 protected function getFormFields() { 00506 return false; 00507 } 00508 00509 public function onSubmit( $data ) { 00510 return false; 00511 } 00512 00513 public function onSuccess() { 00514 return false; 00515 } 00516 00517 public function show() { 00518 $this->setHeaders(); 00519 00520 // This will throw exceptions if there's a problem 00521 $this->checkCanExecute( $this->getUser() ); 00522 00523 $this->getOutput()->addHTML( $this->onView() ); 00524 } 00525 00533 public function execute( array $data = null, $captureErrors = true ) { 00534 try { 00535 // Set a new context so output doesn't leak. 00536 $this->context = clone $this->page->getContext(); 00537 if ( is_array( $data ) ) { 00538 $this->context->setRequest( new FauxRequest( $data, false ) ); 00539 } 00540 00541 // This will throw exceptions if there's a problem 00542 $this->checkCanExecute( $this->getUser() ); 00543 00544 $this->onView(); 00545 return true; 00546 } 00547 catch ( ErrorPageError $e ) { 00548 if ( $captureErrors ) { 00549 return false; 00550 } else { 00551 throw $e; 00552 } 00553 } 00554 } 00555 }