Fix initialization of Context in Action class.
authordaniel <daniel.kinzler@wikimedia.de>
Thu, 19 Sep 2013 10:56:42 +0000 (12:56 +0200)
committerdaniel <daniel.kinzler@wikimedia.de>
Thu, 19 Sep 2013 13:11:00 +0000 (15:11 +0200)
When Action::getActionName calls Action::factory, $context
must be passed explicitly, since WikiPage does not have a getContext()
method (only Article does).

As a failsafe in Article::getContext(), use $this->page->getContext()
only if $this->page is an Article. If $this->context is null and $this->page
is not an article, fall back to RequestContext::getMain()

Change-Id: I6d8db29dfd1aaa68f3de4f8f418841205c2379af

includes/Action.php

index 23b648f..4b6e446 100644 (file)
@@ -142,7 +142,7 @@ abstract class Action {
                        return 'view';
                }
 
-               $action = Action::factory( $actionName, $context->getWikiPage() );
+               $action = Action::factory( $actionName, $context->getWikiPage(), $context );
                if ( $action instanceof Action ) {
                        return $action->getName();
                }
@@ -167,8 +167,14 @@ abstract class Action {
        final public function getContext() {
                if ( $this->context instanceof IContextSource ) {
                        return $this->context;
+               } else if ( $this->page instanceof Article ) {
+                       // NOTE: $this->page can be a WikiPage, which does not have a context.
+                       wfDebug( __METHOD__ . ': no context known, falling back to Article\'s context.' );
+                       return $this->page->getContext();
                }
-               return $this->page->getContext();
+
+               wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
+               return RequestContext::getMain();
        }
 
        /**
@@ -255,6 +261,12 @@ abstract class Action {
         * @param $context IContextSource
         */
        public function __construct( Page $page, IContextSource $context = null ) {
+               if ( $context === null ) {
+                       wfWarn( __METHOD__ . ' called without providing a Context object.' );
+                       // NOTE: We could try to initialize $context using $page->getContext(),
+                       //      if $page is an Article. That however seems to not work seamlessly.
+               }
+
                $this->page = $page;
                $this->context = $context;
        }
@@ -477,7 +489,7 @@ abstract class FormAction extends Action {
        public function execute( array $data = null, $captureErrors = true ) {
                try {
                        // Set a new context so output doesn't leak.
-                       $this->context = clone $this->page->getContext();
+                       $this->context = clone $this->getContext();
 
                        // This will throw exceptions if there's a problem
                        $this->checkCanExecute( $this->getUser() );
@@ -566,7 +578,7 @@ abstract class FormlessAction extends Action {
        public function execute( array $data = null, $captureErrors = true ) {
                try {
                        // Set a new context so output doesn't leak.
-                       $this->context = clone $this->page->getContext();
+                       $this->context = clone $this->getContext();
                        if ( is_array( $data ) ) {
                                $this->context->setRequest( new FauxRequest( $data, false ) );
                        }