Providing a sane implementation for application start pages
authorAlexander Ebert <ebert@woltlab.com>
Sat, 14 Dec 2013 20:11:52 +0000 (21:11 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 14 Dec 2013 20:11:52 +0000 (21:11 +0100)
Accessing a non-primary application by it's directory will no longer redirect to the landing page, instead user is redirected to the application's primary controller.

wcfsetup/install/files/lib/system/WCF.class.php
wcfsetup/install/files/lib/system/application/AbstractApplication.class.php
wcfsetup/install/files/lib/system/application/IApplication.class.php
wcfsetup/install/files/lib/system/request/RequestHandler.class.php

index 379f7188f07228f99f6b844de235f3ee36938493..1acec6eeb13f96a06c7e38678e4e6336c37a4292 100644 (file)
@@ -61,10 +61,16 @@ if (!defined('NO_IMPORTS')) {
 class WCF {
        /**
         * list of currently loaded applications
-        * @var array<\wcf\system\application\IApplication>
+        * @var array<\wcf\data\application\Application>
         */
        protected static $applications = array();
        
+       /**
+        * list of currently loaded application objects
+        * @var array<\wcf\system\application\IApplication>
+        */
+       protected static $applicationObjects = array();
+       
        /**
         * list of autoload directories
         * @var array
@@ -490,8 +496,8 @@ class WCF {
                        }
                        
                        // init application and assign it as template variable
-                       $applicationObject = call_user_func(array($className, 'getInstance'));
-                       $this->getTPL()->assign('__'.$abbreviation, $applicationObject);
+                       self::$applicationObjects[$application->packageID] = call_user_func(array($className, 'getInstance'));
+                       $this->getTPL()->assign('__'.$abbreviation, self::$applicationObjects[$application->packageID]);
                }
                else {
                        unset(self::$autoloadDirectories[$abbreviation]);
@@ -510,7 +516,21 @@ class WCF {
                // register application
                self::$applications[$abbreviation] = $application;
                
-               return $applicationObject;
+               return self::$applicationObjects[$application->packageID];
+       }
+       
+       /**
+        * Returns the corresponding application object. Does not support the 'wcf' pseudo application.
+        * 
+        * @param       wcf\data\application\Application        $application
+        * @return      \wcf\system\application\IApplication
+        */
+       public static function getApplicationObject(Application $application) {
+               if (isset(self::$applicationObjects[$application->packageID])) {
+                       return self::$applicationObjects[$application->packageID];
+               }
+               
+               return null;
        }
        
        /**
index 2adbf767f4784f7d9e1688e6f7febc88af0bfcf8..3ad882b2f12c2033fd557cd3ec8b0cfa75579ea2 100644 (file)
@@ -33,6 +33,12 @@ abstract class AbstractApplication extends SingletonFactory implements IApplicat
         */
        protected $packageID = 0;
        
+       /**
+        * qualified name of application's primary controller
+        * @var string
+        */
+       protected $primaryController = '';
+       
        /**
         * @see \wcf\system\SingletonFactory::init()
         */
@@ -77,6 +83,13 @@ abstract class AbstractApplication extends SingletonFactory implements IApplicat
                return PackageCache::getInstance()->getPackage($this->packageID);
        }
        
+       /**
+        * @see \wcf\system\application\IApplication::getPrimaryController()
+        */
+       public function getPrimaryController() {
+               return $this->primaryController;
+       }
+       
        /**
         * @see \wcf\system\application\IApplication::__callStatic()
         */
index bde7c7d4393a32e31e5cad059c3ac3e03e2a6589..54e05ea3092e24cb123e63e4d2cbd6e04ab92607 100644 (file)
@@ -24,6 +24,13 @@ interface IApplication {
         */
        public function isActiveApplication();
        
+       /**
+        * Returns the qualified name of this application's primary controller.
+        * 
+        * @return      string
+        */
+       public function getPrimaryController();
+       
        /**
         * Forwards unknown method calls to WCF.
         * 
index 898cbd651eb245494322c45025ee0c6b908eb89c..fb31735d66e635bacaf165286eafd0ec6caa9cd3 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 namespace wcf\system\request;
+use wcf\system\application\AbstractApplication;
 use wcf\system\application\ApplicationHandler;
 use wcf\system\exception\AJAXException;
 use wcf\system\exception\IllegalLinkException;
@@ -134,6 +135,19 @@ class RequestHandler extends SingletonFactory {
                                                $routeData['controller'] = $landingPage->getController();
                                        }
                                        else {
+                                               // check if current URL matches an application but controller was omitted
+                                               $currentRequestURI = RouteHandler::getHost() . $requestUri;
+                                               foreach (ApplicationHandler::getInstance()->getApplications() as $application) {
+                                                       if ($currentRequestURI == $application->getPageURL()) {
+                                                               if ($controller = WCF::getApplicationObject($application)->getPrimaryController()) {
+                                                                       $controller = explode('\\', $controller);
+                                                                       HeaderUtil::redirect(LinkHandler::getInstance()->getLink(array_pop($controller), array('application' => $controller[0])));
+                                                                       exit;
+                                                               }
+                                                       }
+                                                       
+                                               }
+                                               
                                                // redirect to landing page
                                                HeaderUtil::redirect($landingPage->getLink(), true);
                                                exit;