Added proper landing page configuration per app
authorAlexander Ebert <ebert@woltlab.com>
Sun, 18 Dec 2016 20:09:21 +0000 (21:09 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 18 Dec 2016 20:14:32 +0000 (21:14 +0100)
wcfsetup/install/files/acp/templates/applicationEdit.tpl
wcfsetup/install/files/acp/templates/applicationManagement.tpl
wcfsetup/install/files/lib/acp/form/ApplicationEditForm.class.php
wcfsetup/install/files/lib/acp/page/ApplicationManagementPage.class.php
wcfsetup/install/files/lib/data/application/Application.class.php
wcfsetup/install/files/lib/data/page/Page.class.php
wcfsetup/install/files/lib/system/cache/builder/RoutingCacheBuilder.class.php
wcfsetup/install/files/lib/system/request/RequestHandler.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml
wcfsetup/setup/db/install.sql

index 1ef2ecc0bbcf0d86ce59552ff25668d6674ecc26..8b2efa1f759f5fa186aab7b4930c44db1d5bbe07 100644 (file)
                        </dd>
                </dl>
                
+               <dl>
+                       <dt><label for="landingPageID">{lang}wcf.acp.application.landingPage{/lang}</label></dt>
+                       <dd>
+                               <select name="landingPageID" id="landingPageID">
+                                       <option value="0">{lang}wcf.global.noSelection{/lang}</option>
+                                       
+                                       {foreach from=$pageNodeList item=pageNode}
+                                               {if !$pageNode->requireObjectID}
+                                                       <option value="{@$pageNode->pageID}"{if $pageNode->pageID == $landingPageID} selected{/if} data-identifier="{@$pageNode->identifier}">{if $pageNode->getDepth() > 1}{@"&nbsp;&nbsp;&nbsp;&nbsp;"|str_repeat:($pageNode->getDepth() - 1)}{/if}{$pageNode->name}</option>
+                                               {/if}
+                                       {/foreach}
+                               </select>
+                               <small>{lang}wcf.acp.application.landingPage.description{/lang}</small>
+                       </dd>
+               </dl>
+               
                {event name='domainFields'}
        </section>
        
index 51ba3fab2e6a9099f73cfc615b288ba3bb081c32..7bac0ef6eef750712e87135d0123febb4f0c2b08 100644 (file)
@@ -22,7 +22,7 @@
                                <th class="columnText columnPackageName">{lang}wcf.acp.package.name{/lang}</th>
                                <th class="columnText columnDomainName">{lang}wcf.acp.application.domainName{/lang}</th>
                                <th class="columnText columnDomainPath">{lang}wcf.acp.application.domainPath{/lang}</th>
-                               <th class="columnText columnCookieDomain">{lang}wcf.acp.application.cookieDomain{/lang}</th>
+                               <th class="columnText columnLandingPageID">{lang}wcf.acp.application.landingPage{/lang}</th>
                                
                                {event name='columnHeads'}
                        </tr>
                                        <td class="columnTitle columnPackageName"><a href="{link controller='ApplicationEdit' id=$application->packageID}{/link}">{$application->getPackage()}</a></td>
                                        <td class="columnText columnDomainName">{$application->domainName}</td>
                                        <td class="columnText columnDomainPath">{$application->domainPath}</td>
-                                       <td class="columnText columnCookieDomain">{$application->cookieDomain}</td>
+                                       <td class="columnText columnLandingPageID">
+                                               {if $application->landingPageID && $pageList[$application->landingPageID]|isset}
+                                                       {$pageList[$application->landingPageID]}
+                                               {else}
+                                                       {lang}wcf.global.noSelection{/lang}
+                                               {/if}
+                                       </td>
                                        
                                        {event name='columns'}
                                </tr>
index 4bb9e26c8f08e82aa5a30753314605b43618bca8..a46b402bb218a21f3265b83ed649e9230f757da9 100644 (file)
@@ -4,8 +4,12 @@ use wcf\data\application\Application;
 use wcf\data\application\ApplicationAction;
 use wcf\data\application\ViewableApplication;
 use wcf\data\package\PackageCache;
+use wcf\data\page\Page;
+use wcf\data\page\PageNodeTree;
 use wcf\system\application\ApplicationHandler;
 use wcf\form\AbstractForm;
+use wcf\system\cache\builder\ApplicationCacheBuilder;
+use wcf\system\cache\builder\RoutingCacheBuilder;
 use wcf\system\exception\IllegalLinkException;
 use wcf\system\exception\UserInputException;
 use wcf\system\Regex;
@@ -31,7 +35,7 @@ class ApplicationEditForm extends AbstractForm {
         * viewable application object
         * @var ViewableApplication
         */
-       public $application = null;
+       public $application;
        
        /**
         * cookie domain
@@ -51,6 +55,12 @@ class ApplicationEditForm extends AbstractForm {
         */
        public $domainPath = '';
        
+       /**
+        * landing page id
+        * @var integer
+        */
+       public $landingPageID = 0;
+       
        /**
         * @inheritDoc
         */
@@ -67,6 +77,12 @@ class ApplicationEditForm extends AbstractForm {
         */
        public $templateName = 'applicationEdit';
        
+       /**
+        * nested list of page nodes
+        * @var \RecursiveIteratorIterator
+        */
+       public $pageNodeList;
+       
        /**
         * @inheritDoc
         */
@@ -78,6 +94,8 @@ class ApplicationEditForm extends AbstractForm {
                if (!$this->application->packageID) {
                        throw new IllegalLinkException();
                }
+               
+               $this->pageNodeList = (new PageNodeTree())->getNodeList();
        }
        
        /**
@@ -89,6 +107,7 @@ class ApplicationEditForm extends AbstractForm {
                if (isset($_POST['cookieDomain'])) $this->cookieDomain = StringUtil::trim($_POST['cookieDomain']);
                if (isset($_POST['domainName'])) $this->domainName = StringUtil::trim($_POST['domainName']);
                if (isset($_POST['domainPath'])) $this->domainPath = StringUtil::trim($_POST['domainPath']);
+               if (isset($_POST['landingPageID'])) $this->landingPageID = intval($_POST['landingPageID']);
        }
        
        /**
@@ -101,6 +120,7 @@ class ApplicationEditForm extends AbstractForm {
                        $this->cookieDomain = $this->application->cookieDomain;
                        $this->domainName = $this->application->domainName;
                        $this->domainPath = $this->application->domainPath;
+                       $this->landingPageID = $this->application->landingPageID;
                }
        }
        
@@ -157,6 +177,16 @@ class ApplicationEditForm extends AbstractForm {
                        WCF::getTPL()->assign('conflictApplication', PackageCache::getInstance()->getPackage($row['packageID']));
                        throw new UserInputException('domainPath', 'conflict');
                }
+               
+               if ($this->landingPageID) {
+                       $page = new Page($this->landingPageID);
+                       if (!$page->pageID) {
+                               throw new UserInputException('landingPageID');
+                       }
+                       else if ($page->requireObjectID) {
+                               throw new UserInputException('landingPageID', 'invalid');
+                       }
+               }
        }
        
        /**
@@ -169,15 +199,36 @@ class ApplicationEditForm extends AbstractForm {
                $this->objectAction = new ApplicationAction([$this->application->getDecoratedObject()], 'update', ['data' => array_merge($this->additionalFields, [
                        'cookieDomain' => mb_strtolower($this->cookieDomain),
                        'domainName' => mb_strtolower($this->domainName),
-                       'domainPath' => $this->domainPath
+                       'domainPath' => $this->domainPath,
+                       'landingPageID' => ($this->landingPageID ?: null)
                ])]);
                $this->objectAction->executeAction();
                
                $this->saved();
                
+               if ($this->application->packageID === 1) {
+                       if ($this->landingPageID) {
+                               (new Page($this->landingPageID))->setAsLandingPage();
+                       }
+                       else {
+                               $sql = "UPDATE  wcf".WCF_N."_page
+                                       SET     isLandingPage = ?
+                                       WHERE   isLandingPage = ?";
+                               $statement = WCF::getDB()->prepareStatement($sql);
+                               $statement->execute([
+                                       0,
+                                       1
+                               ]);
+                       }
+               }
+               
                // re-calculate cookie settings
                ApplicationHandler::rebuild();
                
+               // reset caches to reflect new landing page
+               ApplicationCacheBuilder::getInstance()->reset();
+               RoutingCacheBuilder::getInstance()->reset();
+               
                // show success message
                WCF::getTPL()->assign('success', true);
        }
@@ -193,7 +244,9 @@ class ApplicationEditForm extends AbstractForm {
                        'cookieDomain' => $this->cookieDomain,
                        'domainName' => $this->domainName,
                        'domainPath' => $this->domainPath,
-                       'packageID' => $this->packageID
+                       'packageID' => $this->packageID,
+                       'pageNodeList' => $this->pageNodeList,
+                       'landingPageID' => $this->landingPageID
                ]);
        }
 }
index f08aa0ba9bfced7ee3f2c4ec4256c356720c23ac..5c325986ac9487a3c142d73befc36f3b8ed631a6 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 namespace wcf\acp\page;
 use wcf\data\application\ViewableApplicationList;
+use wcf\data\page\PageList;
 use wcf\page\AbstractPage;
 use wcf\system\WCF;
 
@@ -45,8 +46,12 @@ class ApplicationManagementPage extends AbstractPage {
        public function assignVariables() {
                parent::assignVariables();
                
+               $pageList = new PageList();
+               $pageList->readObjects();
+               
                WCF::getTPL()->assign([
-                       'applicationList' => $this->applicationList
+                       'applicationList' => $this->applicationList,
+                       'pageList' => $pageList->getObjects()
                ]);
        }
 }
index e512c4c1f4a42f1f2b6f95c468ee511718628d88..3fbcc891150ca1b6d719d117f23a8f47270e2bc7 100644 (file)
@@ -22,6 +22,7 @@ use wcf\util\FileUtil;
  * @property-read      string          $domainPath     path used to access the application
  * @property-read      string          $cookieDomain   domain used to set cookies (corresponds to `domain` cookie property; may not contain path components)
  * @property-read      integer         $isTainted      is `1` if the application is being uninstalled and thus should not be loaded during uninstallation, otherwise `0`
+ * @property-read       integer         $landingPageID  id of the page that is used as initial page when app is accessed without a controller name
  */
 class Application extends DatabaseObject {
        /**
index 383f4f23b1e6ca8f948461569c7ff8478e0fac24..f19c886cd529db9f19db8babf70d322a8f21986e 100644 (file)
@@ -8,6 +8,8 @@ use wcf\data\TDatabaseObjectOptions;
 use wcf\data\TDatabaseObjectPermissions;
 use wcf\system\acl\simple\SimpleAclResolver;
 use wcf\system\application\ApplicationHandler;
+use wcf\system\cache\builder\ApplicationCacheBuilder;
+use wcf\system\cache\builder\RoutingCacheBuilder;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\exception\SystemException;
 use wcf\system\request\LinkHandler;
@@ -250,6 +252,20 @@ class Page extends DatabaseObject implements ILinkableObject, ITitledObject {
                        $this->pageID
                ]);
                WCF::getDB()->commitTransaction();
+               
+               $sql = "UPDATE  wcf".WCF_N."_application
+                       SET     landingPageID = ?
+                       WHERE   packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute([
+                       $this->pageID,
+                       1
+               ]);
+               WCF::getDB()->commitTransaction();
+               
+               // reset caches to reflect new landing page
+               ApplicationCacheBuilder::getInstance()->reset();
+               RoutingCacheBuilder::getInstance()->reset();
        }
        
        /**
index 758e713762c51d913aabb0670e0c610c6f9d85e0..76cc53abd470430543cc0a57875503034613df6c 100644 (file)
@@ -2,6 +2,7 @@
 namespace wcf\system\cache\builder;
 use wcf\data\application\Application;
 use wcf\data\page\Page;
+use wcf\data\page\PageCache;
 use wcf\page\CmsPage;
 use wcf\system\application\ApplicationHandler;
 use wcf\system\request\ControllerMap;
@@ -254,7 +255,22 @@ class RoutingCacheBuilder extends AbstractCacheBuilder {
                                }
                        }
                        else {
-                               $controller = WCF::getApplicationObject($application)->getPrimaryController();
+                               if ($application->landingPageID) {
+                                       $page = PageCache::getInstance()->getPage($application->landingPageID);
+                                       if ($page !== null) {
+                                               if ($page->controller) {
+                                                       $controller = $page->controller;
+                                               }
+                                               else {
+                                                       $controller = '__WCF_CMS__' . $page->pageID;
+                                                       $controller = [$controller, $controller, CmsPage::class];
+                                               }
+                                       }
+                               }
+                               
+                               if ($controller === null) {
+                                       $controller = WCF::getApplicationObject($application)->getPrimaryController();
+                               }
                        }
                        
                        if (is_string($controller)) {
index 0f90dc81606b693041a1a87e395a38c9183e6915..e1d49e3e0aa1556ed19d1f37d1913b0a6b494ab4 100644 (file)
@@ -223,6 +223,7 @@ class RequestHandler extends SingletonFactory {
                else if (!empty($data['redirect'])) {
                        // force a redirect
                        HeaderUtil::redirect($data['redirect'], true, false);
+                       exit;
                }
                else if (!empty($data['application']) && $data['application'] !== $application) {
                        HeaderUtil::redirect(
index 3f1bfc31b47ee893ed475f6ed71d9a813f283a76..ba89c056b18865620aa2753270b13f2acb1d65c7 100644 (file)
@@ -63,6 +63,8 @@
                <item name="wcf.acp.application.domainPath.description"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Gib{else}Geben Sie{/if} den Pfad an, über den diese App erreichbar ist. Wenn die App zum Beispiel unter „http://www.example.com/community/forum/“ erreichbar ist, müsste hier die korrekte Angabe „/community/forum/“ lauten.]]></item>
                <item name="wcf.acp.application.edit"><![CDATA[App bearbeiten]]></item>
                <item name="wcf.acp.application.edit.title"><![CDATA[App bearbeiten: „<a href="{link controller='Package' id=$application->packageID}{/link}">{$application->getPackage()->getName()}</a>“]]></item>
+               <item name="wcf.acp.application.landingPage"><![CDATA[Einstiegsseite]]></item>
+               <item name="wcf.acp.application.landingPage.description"><![CDATA[Optional: {if LANGUAGE_USE_INFORMAL_VARIANT}Gib{else}Geben Sie{/if} die Seite an, die angezeigt wird, wenn diese App direkt aufgerufen wird.]]></item>
                <item name="wcf.acp.application.list"><![CDATA[Installierte Apps]]></item>
        </category>
        
index 10748b49eb6876152ba69ea6fbe8427ff2648983..16f09ed575c4fe841dba1fd438d72dba159dbfb3 100644 (file)
@@ -63,6 +63,8 @@
                <item name="wcf.acp.application.domainPath.description"><![CDATA[If you are accessing this application through “http://www.example.com/community/forum/”, please enter “/community/forum/”.]]></item>
                <item name="wcf.acp.application.edit"><![CDATA[Edit Application]]></item>
                <item name="wcf.acp.application.edit.title"><![CDATA[Edit Application: “<a href="{link controller='Package' id=$application->packageID}{/link}">{$application->getPackage()->getName()}</a>”]]></item>
+               <item name="wcf.acp.application.landingPage"><![CDATA[Entry Page]]></item>
+               <item name="wcf.acp.application.landingPage.description"><![CDATA[Optional: This page will be shown when a user is navigating to this app.]]></item>
                <item name="wcf.acp.application.list"><![CDATA[Installed Applications]]></item>
        </category>
        
index 7c40b38f1bca936aedaccde6150a88163e858717..5c2811d5289cec2b02ff8bcb03a5639933fed5bf 100644 (file)
@@ -149,7 +149,8 @@ CREATE TABLE wcf1_application (
        domainName VARCHAR(255) NOT NULL,
        domainPath VARCHAR(255) NOT NULL DEFAULT '/',
        cookieDomain VARCHAR(255) NOT NULL,
-       isTainted TINYINT(1) NOT NULL DEFAULT 0
+       isTainted TINYINT(1) NOT NULL DEFAULT 0,
+       landingPageID INT(10) NULL
 );
 
 DROP TABLE IF EXISTS wcf1_article;
@@ -1679,6 +1680,7 @@ ALTER TABLE wcf1_acp_template ADD FOREIGN KEY (packageID) REFERENCES wcf1_packag
 ALTER TABLE wcf1_ad ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
 
 ALTER TABLE wcf1_application ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
+ALTER TABLE wcf1_application ADD FOREIGN KEY (landingPageID) REFERENCES wcf1_page (pageID) ON DELETE SET NULL;
 
 ALTER TABLE wcf1_article ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE SET NULL;
 ALTER TABLE wcf1_article ADD FOREIGN KEY (categoryID) REFERENCES wcf1_category (categoryID) ON DELETE SET NULL;