/**
  * dispatch the request
  *
  * @param WikiaApp $app
  * @param WikiaRequest $request
  * @return WikiaResponse
  */
 public function dispatch(WikiaApp $app, WikiaRequest $request)
 {
     $autoloadClasses = $app->wg->AutoloadClasses;
     if (empty($autoloadClasses)) {
         throw new WikiaException("wgAutoloadClasses is empty, cannot dispatch Request");
     }
     $format = $request->getVal('format', WikiaResponse::FORMAT_HTML);
     $response = F::build('WikiaResponse', array('format' => $format, 'request' => $request));
     if ($app->wg->EnableSkinTemplateOverride && $app->isSkinInitialized()) {
         $response->setSkinName($app->wg->User->getSkin()->getSkinName());
     }
     // Main dispatch is a loop because Controllers can forward to each other
     // Error condition is also handled via dispatching to the error controller
     do {
         $request->setDispatched(true);
         try {
             $method = $this->getMethodName($request);
             // Determine the "base" name for the controller, stripping off Controller/Service/Module
             $controllerName = $app->getBaseName($request->getVal('controller'));
             // Service classes must be dispatched by full name otherwise we look for a controller.
             if ($app->isService($request->getVal('controller'))) {
                 $controllerClassName = $app->getServiceClassName($controllerName);
             } else {
                 $controllerClassName = $app->getControllerClassName($controllerName);
             }
             $profilename = __METHOD__ . " ({$controllerName}_{$method})";
             if (empty($controllerName)) {
                 throw new WikiaException("Invalid controller name: {$controllerName}");
             }
             if (empty($autoloadClasses[$controllerClassName])) {
                 throw new WikiaException("Controller class does not exist: {$controllerClassName}");
             }
             $app->wf->profileIn($profilename);
             $response->setControllerName($controllerClassName);
             $response->setMethodName($method);
             $controller = F::build($controllerClassName);
             /* @var $controller WikiaController */
             // map X to executeX method names for things that used to be modules
             if (!method_exists($controller, $method)) {
                 $method = ucfirst($method);
                 // This will throw an exception if the template is missing
                 // Refactor the offending class to not use executeXYZ methods or set format in request params
                 if ($format == WikiaResponse::FORMAT_HTML) {
                     $response->getView()->setTemplate($controllerName, $method);
                 }
                 $method = "execute{$method}";
                 $params = $request->getParams();
                 // old modules expect params in a different place
             }
             if (!$request->isInternal() && !$controller->allowsExternalRequests() || in_array($method, array('allowsExternalRequests', 'getRequest', 'setRequest', 'getResponse', 'setResponse', 'getApp', 'setApp', 'init')) || !method_exists($controller, $method) || !is_callable(array($controller, $method))) {
                 throw new WikiaException("Could not dispatch {$controllerClassName}::{$method}");
             }
             // Initialize the RequestContext object if it is not already set
             // SpecialPageController context is already set by SpecialPageFactory::execute by the time it gets here
             if ($controller->getContext() === null) {
                 $controller->setContext(RequestContext::getMain());
             }
             // If a SpecialPageController is dispatching a request to itself, preserve the original request context
             // TODO: come up with a better fix for this (it's because of the setInstance call in WikiaSpecialPageController)
             $originalRequest = $controller->getRequest();
             $originalResponse = $controller->getResponse();
             $controller->setRequest($request);
             $controller->setResponse($response);
             $controller->setApp($app);
             $controller->init();
             // BugId:5125 - keep old hooks naming convention
             $hookMethod = ucfirst($this->getMethodName($request));
             $hookResult = $app->runHook("{$controllerName}{$hookMethod}BeforeExecute", array(&$controller, &$params));
             if ($hookResult) {
                 $result = $controller->{$method}($params);
                 if ($result === false) {
                     // skip template rendering when false returned
                     $controller->skipRendering();
                 }
             }
             // Preserve original request (this is for SpecialPageControllers)
             if ($originalRequest != null) {
                 $controller->setRequest($originalRequest);
             }
             if ($originalResponse != null) {
                 $controller->setResponse($originalResponse);
             }
             // we ignore the result of the AfterExecute hook
             $app->runHook("{$controllerName}{$hookMethod}AfterExecute", array(&$controller, &$params));
             $app->wf->profileOut($profilename);
         } catch (Exception $e) {
             $app->wf->profileOut($profilename);
             $response->setException($e);
             Wikia::log(__METHOD__, $e->getMessage());
             // if we catch an exception, redirect to the WikiaError controller
             if ($controllerClassName != 'WikiaErrorController' && $method != 'error') {
                 $response->getView()->setTemplatePath(null);
                 $request->setVal('controller', 'WikiaError');
                 $request->setVal('method', 'error');
                 $request->setDispatched(false);
             }
         }
     } while (!$request->isDispatched());
     if ($request->isInternal() && $response->hasException()) {
         Wikia::logBacktrace(__METHOD__ . '::exception');
         throw new WikiaDispatchedException("Internal Throw ({$response->getException()->getMessage()})", $response->getException());
     }
     return $response;
 }