MediaWiki  REL1_24
Action.php
Go to the documentation of this file.
00001 <?php
00037 abstract class Action {
00038 
00044     protected $page;
00045 
00051     protected $context;
00052 
00058     protected $fields;
00059 
00067     final private static function getClass( $action, array $overrides ) {
00068         global $wgActions;
00069         $action = strtolower( $action );
00070 
00071         if ( !isset( $wgActions[$action] ) ) {
00072             return null;
00073         }
00074 
00075         if ( $wgActions[$action] === false ) {
00076             return false;
00077         } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
00078             return $overrides[$action];
00079         } elseif ( $wgActions[$action] === true ) {
00080             return ucfirst( $action ) . 'Action';
00081         } else {
00082             return $wgActions[$action];
00083         }
00084     }
00085 
00095     final public static function factory( $action, Page $page, IContextSource $context = null ) {
00096         $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
00097 
00098         if ( is_string( $classOrCallable ) ) {
00099             $obj = new $classOrCallable( $page, $context );
00100             return $obj;
00101         }
00102 
00103         if ( is_callable( $classOrCallable ) ) {
00104             return call_user_func_array( $classOrCallable, array( $page, $context ) );
00105         }
00106 
00107         return $classOrCallable;
00108     }
00109 
00119     final public static function getActionName( IContextSource $context ) {
00120         global $wgActions;
00121 
00122         $request = $context->getRequest();
00123         $actionName = $request->getVal( 'action', 'view' );
00124 
00125         // Check for disabled actions
00126         if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
00127             $actionName = 'nosuchaction';
00128         }
00129 
00130         // Workaround for bug #20966: inability of IE to provide an action dependent
00131         // on which submit button is clicked.
00132         if ( $actionName === 'historysubmit' ) {
00133             if ( $request->getBool( 'revisiondelete' ) ) {
00134                 $actionName = 'revisiondelete';
00135             } else {
00136                 $actionName = 'view';
00137             }
00138         } elseif ( $actionName == 'editredlink' ) {
00139             $actionName = 'edit';
00140         }
00141 
00142         // Trying to get a WikiPage for NS_SPECIAL etc. will result
00143         // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
00144         // For SpecialPages et al, default to action=view.
00145         if ( !$context->canUseWikiPage() ) {
00146             return 'view';
00147         }
00148 
00149         $action = Action::factory( $actionName, $context->getWikiPage(), $context );
00150         if ( $action instanceof Action ) {
00151             return $action->getName();
00152         }
00153 
00154         return 'nosuchaction';
00155     }
00156 
00164     final public static function exists( $name ) {
00165         return self::getClass( $name, array() ) !== null;
00166     }
00167 
00173     final public function getContext() {
00174         if ( $this->context instanceof IContextSource ) {
00175             return $this->context;
00176         } elseif ( $this->page instanceof Article ) {
00177             // NOTE: $this->page can be a WikiPage, which does not have a context.
00178             wfDebug( __METHOD__ . ": no context known, falling back to Article's context.\n" );
00179             return $this->page->getContext();
00180         }
00181 
00182         wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
00183         return RequestContext::getMain();
00184     }
00185 
00192     final public function getRequest() {
00193         return $this->getContext()->getRequest();
00194     }
00195 
00202     final public function getOutput() {
00203         return $this->getContext()->getOutput();
00204     }
00205 
00212     final public function getUser() {
00213         return $this->getContext()->getUser();
00214     }
00215 
00222     final public function getSkin() {
00223         return $this->getContext()->getSkin();
00224     }
00225 
00231     final public function getLanguage() {
00232         return $this->getContext()->getLanguage();
00233     }
00234 
00241     final public function getTitle() {
00242         return $this->page->getTitle();
00243     }
00244 
00251     final public function msg() {
00252         $params = func_get_args();
00253         return call_user_func_array( array( $this->getContext(), 'msg' ), $params );
00254     }
00255 
00264     public function __construct( Page $page, IContextSource $context = null ) {
00265         if ( $context === null ) {
00266             wfWarn( __METHOD__ . ' called without providing a Context object.' );
00267             // NOTE: We could try to initialize $context using $page->getContext(),
00268             //      if $page is an Article. That however seems to not work seamlessly.
00269         }
00270 
00271         $this->page = $page;
00272         $this->context = $context;
00273     }
00274 
00281     abstract public function getName();
00282 
00290     public function getRestriction() {
00291         return null;
00292     }
00293 
00303     protected function checkCanExecute( User $user ) {
00304         $right = $this->getRestriction();
00305         if ( $right !== null ) {
00306             $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user );
00307             if ( count( $errors ) ) {
00308                 throw new PermissionsError( $right, $errors );
00309             }
00310         }
00311 
00312         if ( $this->requiresUnblock() && $user->isBlocked() ) {
00313             $block = $user->getBlock();
00314             throw new UserBlockedError( $block );
00315         }
00316 
00317         // This should be checked at the end so that the user won't think the
00318         // error is only temporary when he also don't have the rights to execute
00319         // this action
00320         if ( $this->requiresWrite() && wfReadOnly() ) {
00321             throw new ReadOnlyError();
00322         }
00323     }
00324 
00331     public function requiresWrite() {
00332         return true;
00333     }
00334 
00341     public function requiresUnblock() {
00342         return true;
00343     }
00344 
00350     protected function setHeaders() {
00351         $out = $this->getOutput();
00352         $out->setRobotPolicy( "noindex,nofollow" );
00353         $out->setPageTitle( $this->getPageTitle() );
00354         $out->setSubtitle( $this->getDescription() );
00355         $out->setArticleRelated( true );
00356     }
00357 
00363     protected function getPageTitle() {
00364         return $this->getTitle()->getPrefixedText();
00365     }
00366 
00373     protected function getDescription() {
00374         return $this->msg( strtolower( $this->getName() ) )->escaped();
00375     }
00376 
00385     abstract public function show();
00386 }