MediaWiki  REL1_23
Action.php
Go to the documentation of this file.
00001 <?php
00037 abstract class Action {
00038 
00043     protected $page;
00044 
00049     protected $context;
00050 
00055     protected $fields;
00056 
00064     final private static function getClass( $action, array $overrides ) {
00065         global $wgActions;
00066         $action = strtolower( $action );
00067 
00068         if ( !isset( $wgActions[$action] ) ) {
00069             return null;
00070         }
00071 
00072         if ( $wgActions[$action] === false ) {
00073             return false;
00074         } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
00075             return $overrides[$action];
00076         } elseif ( $wgActions[$action] === true ) {
00077             return ucfirst( $action ) . 'Action';
00078         } else {
00079             return $wgActions[$action];
00080         }
00081     }
00082 
00091     final public static function factory( $action, Page $page, IContextSource $context = null ) {
00092         $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
00093 
00094         if ( is_string( $classOrCallable ) ) {
00095             $obj = new $classOrCallable( $page, $context );
00096             return $obj;
00097         }
00098 
00099         if ( is_callable( $classOrCallable ) ) {
00100             return call_user_func_array( $classOrCallable, array( $page, $context ) );
00101         }
00102 
00103         return $classOrCallable;
00104     }
00105 
00115     final public static function getActionName( IContextSource $context ) {
00116         global $wgActions;
00117 
00118         $request = $context->getRequest();
00119         $actionName = $request->getVal( 'action', 'view' );
00120 
00121         // Check for disabled actions
00122         if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
00123             $actionName = 'nosuchaction';
00124         }
00125 
00126         // Workaround for bug #20966: inability of IE to provide an action dependent
00127         // on which submit button is clicked.
00128         if ( $actionName === 'historysubmit' ) {
00129             if ( $request->getBool( 'revisiondelete' ) ) {
00130                 $actionName = 'revisiondelete';
00131             } else {
00132                 $actionName = 'view';
00133             }
00134         } elseif ( $actionName == 'editredlink' ) {
00135             $actionName = 'edit';
00136         }
00137 
00138         // Trying to get a WikiPage for NS_SPECIAL etc. will result
00139         // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
00140         // For SpecialPages et al, default to action=view.
00141         if ( !$context->canUseWikiPage() ) {
00142             return 'view';
00143         }
00144 
00145         $action = Action::factory( $actionName, $context->getWikiPage(), $context );
00146         if ( $action instanceof Action ) {
00147             return $action->getName();
00148         }
00149 
00150         return 'nosuchaction';
00151     }
00152 
00159     final public static function exists( $name ) {
00160         return self::getClass( $name, array() ) !== null;
00161     }
00162 
00167     final public function getContext() {
00168         if ( $this->context instanceof IContextSource ) {
00169             return $this->context;
00170         } elseif ( $this->page instanceof Article ) {
00171             // NOTE: $this->page can be a WikiPage, which does not have a context.
00172             wfDebug( __METHOD__ . ": no context known, falling back to Article's context.\n" );
00173             return $this->page->getContext();
00174         }
00175 
00176         wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
00177         return RequestContext::getMain();
00178     }
00179 
00185     final public function getRequest() {
00186         return $this->getContext()->getRequest();
00187     }
00188 
00194     final public function getOutput() {
00195         return $this->getContext()->getOutput();
00196     }
00197 
00203     final public function getUser() {
00204         return $this->getContext()->getUser();
00205     }
00206 
00212     final public function getSkin() {
00213         return $this->getContext()->getSkin();
00214     }
00215 
00221     final public function getLanguage() {
00222         return $this->getContext()->getLanguage();
00223     }
00224 
00231     final public function getLang() {
00232         wfDeprecated( __METHOD__, '1.19' );
00233         return $this->getLanguage();
00234     }
00235 
00240     final public function getTitle() {
00241         return $this->page->getTitle();
00242     }
00243 
00250     final public function msg() {
00251         $params = func_get_args();
00252         return call_user_func_array( array( $this->getContext(), 'msg' ), $params );
00253     }
00254 
00263     public function __construct( Page $page, IContextSource $context = null ) {
00264         if ( $context === null ) {
00265             wfWarn( __METHOD__ . ' called without providing a Context object.' );
00266             // NOTE: We could try to initialize $context using $page->getContext(),
00267             //      if $page is an Article. That however seems to not work seamlessly.
00268         }
00269 
00270         $this->page = $page;
00271         $this->context = $context;
00272     }
00273 
00278     abstract public function getName();
00279 
00285     public function getRestriction() {
00286         return null;
00287     }
00288 
00298     protected function checkCanExecute( User $user ) {
00299         $right = $this->getRestriction();
00300         if ( $right !== null ) {
00301             $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user );
00302             if ( count( $errors ) ) {
00303                 throw new PermissionsError( $right, $errors );
00304             }
00305         }
00306 
00307         if ( $this->requiresUnblock() && $user->isBlocked() ) {
00308             $block = $user->getBlock();
00309             throw new UserBlockedError( $block );
00310         }
00311 
00312         // This should be checked at the end so that the user won't think the
00313         // error is only temporary when he also don't have the rights to execute
00314         // this action
00315         if ( $this->requiresWrite() && wfReadOnly() ) {
00316             throw new ReadOnlyError();
00317         }
00318         return true;
00319     }
00320 
00325     public function requiresWrite() {
00326         return true;
00327     }
00328 
00333     public function requiresUnblock() {
00334         return true;
00335     }
00336 
00341     protected function setHeaders() {
00342         $out = $this->getOutput();
00343         $out->setRobotPolicy( "noindex,nofollow" );
00344         $out->setPageTitle( $this->getPageTitle() );
00345         $this->getOutput()->setSubtitle( $this->getDescription() );
00346         $out->setArticleRelated( true );
00347     }
00348 
00354     protected function getPageTitle() {
00355         return $this->getTitle()->getPrefixedText();
00356     }
00357 
00363     protected function getDescription() {
00364         return $this->msg( strtolower( $this->getName() ) )->escaped();
00365     }
00366 
00373     abstract public function show();
00374 
00379     abstract public function execute();
00380 }