<permissions>admin.content.cms.canManagePage</permissions>
</acpmenuitem>
+ <acpmenuitem name="wcf.acp.menu.link.cms.page.landing">
+ <controller><![CDATA[wcf\acp\form\PageLandingForm]]></controller>
+ <parent>wcf.acp.menu.link.cms.page.list</parent>
+ <permissions>admin.content.cms.canManagePage</permissions>
+ <icon>fa-home</icon>
+ </acpmenuitem>
+
<acpmenuitem name="wcf.acp.menu.link.cms.page.add">
<controller><![CDATA[wcf\acp\form\PageAddForm]]></controller>
<parent>wcf.acp.menu.link.cms.page.list</parent>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/vortex/menu.xsd">
+ <import>
+ <menu identifier="com.woltlab.wcf.MainMenu">
+ <title language="de">Hauptmenü</title>
+ <title language="en">Main Menu</title>
+
+ <box>
+ <position>mainMenu</position>
+ <showheader>0</showheader>
+ <visibleeveryhwere>1</visibleeveryhwere>
+ </box>
+ </menu>
+ </import>
+</data>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/vortex/menuItem.xsd">
+ <import>
+ <item identifier="com.woltlab.wcf.Dashboard">
+ <menu>com.woltlab.wcf.MainMenu</menu>
+ <title language="de"><![CDATA[Dashboard]]></title>
+ <title language="en"><![CDATA[Dashboard]]></title>
+ <page>com.woltlab.wcf.Dashboard</page>
+ </item>
+
+ <item identifier="com.woltlab.wcf.MembersList">
+ <menu>com.woltlab.wcf.MainMenu</menu>
+ <title language="de"><![CDATA[Mitglieder]]></title>
+ <title language="en"><![CDATA[Members]]></title>
+ <page>com.woltlab.wcf.MembersList</page>
+ </item>
+ <item identifier="com.woltlab.wcf.RecentActivityList">
+ <parent>com.woltlab.wcf.MembersList</parent>
+ <title language="de"><![CDATA[Letzte Aktivitäten]]></title>
+ <title language="en"><![CDATA[Recent Activities]]></title>
+ <page>com.woltlab.wcf.RecentActivityList</page>
+ </item>
+ <item identifier="com.woltlab.wcf.UsersOnlineList">
+ <parent>com.woltlab.wcf.MembersList</parent>
+ <title language="de"><![CDATA[Benutzer Online]]></title>
+ <title language="en"><![CDATA[Users Online]]></title>
+ <page>com.woltlab.wcf.UsersOnlineList</page>
+ </item>
+ <item identifier="com.woltlab.wcf.Team">
+ <parent>com.woltlab.wcf.MembersList</parent>
+ <title language="de"><![CDATA[Team]]></title>
+ <title language="en"><![CDATA[Team]]></title>
+ <page>com.woltlab.wcf.Team</page>
+ </item>
+ <item identifier="com.woltlab.wcf.UserSearch">
+ <parent>com.woltlab.wcf.MembersList</parent>
+ <title language="de"><![CDATA[Benutzer suchen]]></title>
+ <title language="en"><![CDATA[Search Users]]></title>
+ <page>com.woltlab.wcf.UserSearch</page>
+ </item>
+
+ <!-- TODO: privacy policy / footer menu? -->
+ </import>
+</data>
<packagedescription><![CDATA[Free web-framework, designed and developed for complex community applications.]]></packagedescription>
<packagedescription language="de"><![CDATA[Freies Web-Framework, das für komplexe Community-Anwendungen entworfen und entwickelt wurde.]]></packagedescription>
<isapplication>1</isapplication>
- <version>2.2.0 Alpha 1</version> <!-- codename: vortex -->
+ <version>2.2.0 Alpha 2</version> <!-- codename: vortex -->
<date>2015-10-22</date>
</packageinformation>
<instruction type="userNotificationEvent" />
<instruction type="aclOption" />
<instruction type="page" />
+ <instruction type="menu" />
+ <instruction type="menuItem" />
<instruction type="script">acp/post_install.php</instruction>
</instructions>
+
+ <instructions type="update" fromversion="2.2.0 Alpha 1">
+ <instruction type="page" />
+ <instruction type="menuItem" />
+ </instructions>
</package>
<pip name="userMenu">wcf\system\package\plugin\UserMenuPackageInstallationPlugin</pip>
<pip name="userNotificationEvent">wcf\system\package\plugin\UserNotificationEventPackageInstallationPlugin</pip>
<pip name="dashboardBox">wcf\system\package\plugin\DashboardBoxPackageInstallationPlugin</pip>
+ <pip name="box">wcf\system\package\plugin\BoxPackageInstallationPlugin</pip>
+ <pip name="menu">wcf\system\package\plugin\MenuPackageInstallationPlugin</pip>
+ <pip name="menuItem">wcf\system\package\plugin\MenuItemPackageInstallationPlugin</pip>
</import>
</data>
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/page.xsd">
<import>
+ <!-- dynamic -->
+ <page identifier="com.woltlab.wcf.Dashboard">
+ <controller>wcf\page\DashboardPage</controller>
+ <name language="de"><![CDATA[Dashboard]]></name>
+ <name language="en"><![CDATA[Dashboard]]></name>
+ </page>
+
+ <page identifier="com.woltlab.wcf.MembersList">
+ <controller>wcf\page\MembersListPage</controller>
+ <name language="de"><![CDATA[Mitglieder]]></name>
+ <name language="en"><![CDATA[Members]]></name>
+ </page>
+ <page identifier="com.woltlab.wcf.RecentActivityList">
+ <controller>wcf\page\RecentActivityListPage</controller>
+ <name language="de"><![CDATA[Letzte Aktivitäten]]></name>
+ <name language="en"><![CDATA[Recent Activities]]></name>
+ <parent>com.woltlab.wcf.MembersList</parent>
+ </page>
+ <page identifier="com.woltlab.wcf.UsersOnlineList">
+ <controller>wcf\page\UsersOnlineListPage</controller>
+ <name language="de"><![CDATA[Benutzer Online]]></name>
+ <name language="en"><![CDATA[Users Online]]></name>
+ <parent>com.woltlab.wcf.MembersList</parent>
+ </page>
+ <page identifier="com.woltlab.wcf.Team">
+ <controller>wcf\page\TeamPage</controller>
+ <name language="de"><![CDATA[Team]]></name>
+ <name language="en"><![CDATA[Team]]></name>
+ <parent>com.woltlab.wcf.MembersList</parent>
+ </page>
+ <page identifier="com.woltlab.wcf.UserSearch">
+ <controller>wcf\page\UserSearchForm</controller>
+ <name language="de"><![CDATA[Benutzer suchen]]></name>
+ <name language="en"><![CDATA[Search Users]]></name>
+ <parent>com.woltlab.wcf.MembersList</parent>
+ </page>
+
+ <!-- static -->
<page identifier="com.woltlab.wcf.CookiePolicy">
<name language="en">Cookie Policy</name>
<name language="de">Cookie-Richtlinie</name>
-{if $__wcf->getPageMenu()->getMenuItems('header')|count > 0}
+{@$__wcf->getBoxHandler()->getBoxes('mainMenu')[0]}
+{*if $__wcf->getPageMenu()->getMenuItems('header')|count > 0}
<nav id="mainMenu" class="mainMenu jsMobileNavigation" data-button-label="{lang}wcf.page.mainMenu{/lang}">
<ul>
+ {foreach from=$__wcf->getBoxHandler()->getBoxes('mainMenu') item=box}
+ {@$box}
+ {/foreach}
+
{foreach from=$__wcf->getPageMenu()->getMenuItems('header') item=menuItem}
<li class="{if $__wcf->getPageMenu()->getActiveMenuItem() == $menuItem->menuItem}active {/if}{if $__wcf->getPageMenu()->getMenuItems($menuItem->menuItem)|count > 0}subMenuItems{/if}" data-menu-item="{$menuItem->menuItem}">
<a href="{$menuItem->getProcessor()->getLink()}">{lang}{$menuItem->menuItem}{/lang}{if $menuItem->getProcessor()->getNotifications()} <span class="badge badgeUpdate">{#$menuItem->getProcessor()->getNotifications()}</span>{/if}</a>
{/foreach}
</ul>
</nav>
-{/if}
+{/if*}
*/
WCF.ACP.Application = { };
-/**
- * Provides the ability to set an application as primary.
- *
- * @param integer packageID
- */
-WCF.ACP.Application.SetAsPrimary = Class.extend({
- /**
- * application package id
- * @var integer
- */
- _packageID: 0,
-
- /**
- * Initializes the WCF.ACP.Application.SetAsPrimary class.
- *
- * @param integer packageID
- */
- init: function(packageID) {
- this._packageID = packageID;
-
- $('#setAsPrimary').click($.proxy(this._click, this));
- },
-
- /**
- * Shows a confirmation dialog to set current application as primary.
- */
- _click: function() {
- WCF.System.Confirmation.show(WCF.Language.get('wcf.acp.application.setAsPrimary.confirmMessage'), $.proxy(function(action) {
- if (action === 'confirm') {
- this._setAsPrimary();
- }
- }, this));
- },
-
- /**
- * Sets an application as primary.
- */
- _setAsPrimary: function() {
- new WCF.Action.Proxy({
- autoSend: true,
- data: {
- actionName: 'setAsPrimary',
- className: 'wcf\\data\\application\\ApplicationAction',
- objectIDs: [ this._packageID ]
- },
- success: $.proxy(function(data, textStatus, jqXHR) {
- var $notification = new WCF.System.Notification(WCF.Language.get('wcf.global.success'));
- $notification.show();
-
- // remove button
- $('#setAsPrimary').parent().remove();
-
- // insert icon
- $headline = $('.boxHeadline > h1');
- $headline.html($headline.html() + ' ');
- $('<span class="icon icon16 fa-home jsTooltip" title="' + WCF.Language.get('wcf.acp.application.primaryApplication') + '" />').appendTo($headline);
-
- WCF.DOMNodeInsertedHandler.execute();
- }, this)
- });
- }
-});
-
/**
* Namespace for ACP cronjob management.
*/
{include file='header' pageTitle='wcf.acp.application.edit'}
-{if $application->packageID != 1 && !$application->isPrimary}
- <script data-relocate="true">
- //<![CDATA[
- $(function() {
- WCF.Language.addObject({
- 'wcf.acp.application.primaryApplication': '{lang}wcf.acp.application.primaryApplication{/lang}',
- 'wcf.acp.application.setAsPrimary.confirmMessage': '{lang}wcf.acp.application.setAsPrimary.confirmMessage{/lang}'
- });
-
- new WCF.ACP.Application.SetAsPrimary({@$application->packageID});
- });
- //]]>
- </script>
-{/if}
-
<header class="boxHeadline">
- <h1>{lang}wcf.acp.application.edit.title{/lang}{if $application->isPrimary} <span class="icon icon16 icon-ok-sign jsTooltip" title="{lang}wcf.acp.application.primaryApplication{/lang}"></span>{/if}</h1>
+ <h1>{lang}wcf.acp.application.edit.title{/lang}</h1>
</header>
{include file='formError'}
<div class="contentNavigation">
<nav>
<ul>
- {if $application->packageID != 1 && !$application->isPrimary}
- <li><a id="setAsPrimary" class="button"><span class="icon icon16 fa-home"></span> <span>{lang}wcf.acp.application.setAsPrimary{/lang}</span></a></li>
- {/if}
<li><a href="{link controller='ApplicationManagement'}{/link}" class="button"><span class="icon icon16 fa-list"></span> <span>{lang}wcf.acp.menu.link.application.management{/lang}</span></a></li>
{event name='contentNavigationButtons'}
<tr>
<td class="columnIcon"><a href="{link controller='ApplicationEdit' id=$application->packageID}{/link}" class="jsTooltip" title="{lang}wcf.global.button.edit{/lang}"><span class="icon icon16 fa-pencil"></span></a></td>
<td class="columnID columnPackageID">{#$application->packageID}</td>
- <td class="columnText columnPackageName">
- <a href="{link controller='ApplicationEdit' id=$application->packageID}{/link}">{$application->getPackage()}</a>
- {if $application->isPrimary}
- <aside class="statusDisplay">
- <ul class="statusIcons">
- <li><span class="icon icon16 fa-home jsTooltip" title="{lang}wcf.acp.application.primaryApplication{/lang}"></span></li>
- </ul>
- </aside>
- {/if}
- </td>
+ <td class="columnText 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>
<div class="contentNavigation">
<nav>
<ul>
- <li><a href="{link controller='PageList'}{/link}" class="button"><span class="icon icon16 icon-list"></span> <span>{lang}wcf.acp.menu.link.cms.page.list{/lang}</span></a></li>
+ <li><a href="{link controller='PageList'}{/link}" class="button"><span class="icon icon16 fa-list"></span> <span>{lang}wcf.acp.menu.link.cms.page.list{/lang}</span></a></li>
{event name='contentNavigationButtons'}
</ul>
</div>
<div class="formSubmit">
- <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
- <input type="hidden" name="isMultilingual" value="{@$isMultilingual}" />
+ <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
+ <input type="hidden" name="isMultilingual" value="{@$isMultilingual}">
{@SECURITY_TOKEN_INPUT_TAG}
</div>
</form>
--- /dev/null
+{include file='header' pageTitle='wcf.acp.page.landing'}
+
+<header class="boxHeadline">
+ <h1>{lang}wcf.acp.page.landing{/lang}</h1>
+</header>
+
+{include file='formError'}
+
+{if $success|isset}
+ <p class="success">{lang}wcf.global.success.{$action}{/lang}</p>
+{/if}
+
+<div class="contentNavigation">
+ <nav>
+ <ul>
+ <li><a href="{link controller='PageList'}{/link}" class="button"><span class="icon icon16 fa-list"></span> <span>{lang}wcf.acp.menu.link.cms.page.list{/lang}</span></a></li>
+
+ {event name='contentNavigationButtons'}
+ </ul>
+ </nav>
+</div>
+
+<form method="post" action="{link controller='PageLanding'}{/link}">
+ <div class="tabularBox marginTop">
+ <table class="table">
+ <thead>
+ <tr>
+ <th class="columnText">{lang}wcf.acp.page.landing.application{/lang}</th>
+ <th class="columnURL">{lang}wcf.acp.page.landing.pageURL{/lang}</th>
+ <th class="columnText">{lang}wcf.acp.page.landing.landingPage{/lang}</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ {foreach from=$applications item=application}
+ <tr>
+ <td class="columnText">{$application->getPackage()}</td>
+ <td class="columnURL">{$application->getPageURL()}</td>
+ <td class="columnText">
+ <select name="landingPages[{@$application->packageID}]">
+ <option value="-1">{lang}wcf.acp.page.landing.applicationDefault{/lang}</option>
+ {foreach from=$pageNodeList item=pageNode}
+ <option value="{@$pageNode->getPage()->pageID}"{if $pageNode->getPage()->pageID == $application->landingPageID} selected{/if}>{if $pageNode->getDepth() > 1}{@" "|str_repeat:($pageNode->getDepth() - 1)}{/if}{$pageNode->getPage()}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ {/foreach}
+ </tbody>
+ </table>
+ </div>
+
+ <div class="formSubmit">
+ <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
+ {@SECURITY_TOKEN_INPUT_TAG}
+ </div>
+</form>
+
+{include file='footer'}
<nav>
<ul>
+ <li><a href="{link controller='PageLanding'}{/link}" class="button"><span class="icon icon16 fa-home"></span> {lang}wcf.acp.page.landing{/lang}</a></li>
<li><a href="{link controller='PageAdd'}{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.acp.page.add{/lang}</span></a></li>
<li><a href="{link controller='PageAdd'}isMultilingual=1{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.acp.page.addMultilingual{/lang}</span></a></li>
<nav>
<ul>
+ <li><a href="{link controller='PageLanding'}{/link}" class="button"><span class="icon icon16 fa-home"></span> {lang}wcf.acp.page.landing{/lang}</a></li>
<li><a href="{link controller='PageAdd'}{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.acp.page.add{/lang}</span></a></li>
<li><a href="{link controller='PageAdd'}isMultilingual=1{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.acp.page.addMultilingual{/lang}</span></a></li>
if (WCF::getUser()->userID) {
throw new PermissionDeniedException();
}
- else if (PACKAGE_ID == 1 && PACKAGE_ID != ApplicationHandler::getInstance()->getPrimaryApplication()->packageID) {
- $application = ApplicationHandler::getInstance()->getPrimaryApplication();
- HeaderUtil::redirect(RouteHandler::getProtocol() . $application->domainName . $application->domainPath . 'acp/?Login/');
- exit;
- }
parent::__run();
}
<?php
namespace wcf\acp\form;
+use wcf\data\application\Application;
use wcf\data\application\ApplicationList;
use wcf\data\page\Page;
use wcf\data\page\PageAction;
public $packageID = 1;
/**
- * list of available applications (standalone packages)
+ * list of available applications
* @var Application[]
*/
public $availableApplications = [];
/**
* page custom URL
- * @var array<string>
+ * @var string[]
*/
public $customURL = [];
/**
* page titles
- * @var array<string>
+ * @var string[]
*/
public $title = [];
/**
* page contents
- * @var array<string>
+ * @var string[]
*/
public $content = [];
/**
* page meta descriptions
- * @var array<string>
+ * @var string[]
*/
public $metaDescription = [];
/**
* page meta keywords
- * @var array<string>
+ * @var string[]
*/
public $metaKeywords = [];
public function assignVariables() {
parent::assignVariables();
- $pageNodeList = new PageNodeTree();
-
WCF::getTPL()->assign([
'action' => 'add',
'parentPageID' => $this->parentPageID,
'metaKeywords' => $this->metaKeywords,
'availableApplications' => $this->availableApplications,
'availableLanguages' => LanguageFactory::getInstance()->getLanguages(),
- 'pageNodeList' => $pageNodeList->getNodeList()
+ 'pageNodeList' => (new PageNodeTree())->getNodeList()
]);
}
}
--- /dev/null
+<?php
+namespace wcf\acp\form;
+use wcf\data\application\Application;
+use wcf\data\application\ApplicationAction;
+use wcf\data\application\ApplicationList;
+use wcf\data\page\Page;
+use wcf\data\page\PageList;
+use wcf\data\page\PageNodeTree;
+use wcf\form\AbstractForm;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\ArrayUtil;
+
+/**
+ * Shows the page add form.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage acp.form
+ * @category Community Framework
+ */
+class PageLandingForm extends AbstractForm {
+ /**
+ * @inheritDoc
+ */
+ public $activeMenuItem = 'wcf.acp.menu.link.cms.page.landing';
+
+ /**
+ * list of available applications
+ * @var Application[]
+ */
+ public $applications;
+
+ /**
+ * landing page id per application package id
+ * @var integer[]
+ */
+ public $landingPages = [];
+
+ /**
+ * @inheritDoc
+ */
+ public $neededPermissions = ['admin.content.cms.canManagePage'];
+
+ /**
+ * list of available pages
+ * @var Page[]
+ */
+ public $pages = [];
+
+ /**
+ * @inheritDoc
+ */
+ public function readParameters() {
+ parent::readParameters();
+
+ // get available applications and pages
+ $applicationList = new ApplicationList();
+ $applicationList->readObjects();
+ $this->applications = $applicationList->getObjects();
+
+ $pageList = new PageList();
+ $pageList->readObjects();
+ foreach ($pageList as $page) {
+ if (!isset($this->pages[$page->packageID])) $this->pages[$page->packageID] = [];
+
+ $this->pages[$page->packageID][$page->pageID] = $page;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readFormParameters() {
+ parent::readFormParameters();
+
+ if (isset($_POST['landingPages']) && is_array($_POST['landingPages'])) $this->landingPages = ArrayUtil::toIntegerArray($_POST['landingPages']);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validate() {
+ parent::validate();
+
+ foreach ($this->applications as $packageID => $application) {
+ if (empty($this->landingPages[$packageID])) {
+ throw new UserInputException('landingPage');
+ }
+
+ // handle application default
+ if ($this->landingPages[$packageID] === -1) {
+ $this->landingPages[$packageID] = null;
+
+ continue;
+ }
+
+ $page = new Page($this->landingPages[$packageID]);
+ if (!$page->pageID) {
+ throw new UserInputException('landingPage', 'notValid');
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function save() {
+ parent::save();
+
+ $this->objectAction = new ApplicationAction($this->applications, 'setLandingPage', ['landingPages' => $this->landingPages]);
+ $this->objectAction->executeAction();
+
+ // call saved event
+ $this->saved();
+
+ // show success
+ WCF::getTPL()->assign('success', true);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ WCF::getTPL()->assign([
+ 'applications' => $this->applications,
+ 'pageNodeList' => (new PageNodeTree())->getNodeList()
+ ]);
+ }
+}
<?php
namespace wcf\data\application;
use wcf\data\package\Package;
+use wcf\data\package\PackageCache;
use wcf\data\package\PackageList;
use wcf\data\DatabaseObject;
use wcf\system\application\ApplicationHandler;
* @category Community Framework
*/
class Application extends DatabaseObject {
+ /**
+ * related package object
+ * @var Package
+ */
+ protected $package;
+
/**
* absolute page URL
* @var string
return ApplicationHandler::getInstance()->getAbbreviation($this->packageID);
}
+ /**
+ * Returns related package object.
+ *
+ * @return Package related package object
+ */
+ public function getPackage() {
+ if ($this->package === null) {
+ $this->package = PackageCache::getInstance()->getPackage($this->packageID);
+ }
+
+ return $this->package;
+ }
+
/**
* Returns absolute page URL.
*
*/
class ApplicationAction extends AbstractDatabaseObjectAction {
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\application\ApplicationEditor';
+ protected $className = ApplicationEditor::class;
/**
* application editor object
- * @var \wcf\data\application\ApplicationEditor
+ * @var ApplicationEditor
*/
- public $applicationEditor = null;
-
- /**
- * @see \wcf\data\AbstractDatabaseObjectAction::$requireACP
- */
- protected $requireACP = array('setAsPrimary');
+ public $applicationEditor;
/**
* Assigns a list of applications to a group and computes cookie domain and path.
$statement = WCF::getDB()->prepareStatement($sql);
// calculate cookie path
- $domains = array();
+ $domains = [];
$regex = new Regex(':[0-9]+');
foreach ($this->objects as $application) {
$domainName = $application->domainName;
}
if (!isset($domains[$domainName])) {
- $domains[$domainName] = array();
+ $domains[$domainName] = [];
}
$domains[$domainName][$application->packageID] = explode('/', FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash($application->domainPath)));
$path = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash(implode('/', $path)));
foreach (array_keys($data) as $packageID) {
- $statement->execute(array(
+ $statement->execute([
$domainName,
$path,
$packageID
- ));
+ ]);
}
}
WCF::getDB()->commitTransaction();
}
/**
- * Validates parameters to set an application as primary.
+ * Sets landing pages for applications.
*/
- public function validateSetAsPrimary() {
- WCF::getSession()->checkPermissions(array('admin.system.canManageApplication'));
-
- $this->applicationEditor = $this->getSingleObject();
- if (!$this->applicationEditor->packageID || $this->applicationEditor->packageID == 1) {
- throw new UserInputException('objectIDs');
- }
- else if ($this->applicationEditor->isPrimary) {
- throw new PermissionDeniedException();
+ public function setLandingPage() {
+ /** @var ApplicationEditor $applicationEditor */
+ foreach ($this->objects as $applicationEditor) {
+ $applicationEditor->update([
+ 'landingPageID' => $this->parameters['landingPages'][$applicationEditor->packageID]
+ ]);
}
}
-
- /**
- * Sets an application as primary.
- */
- public function setAsPrimary() {
- $this->applicationEditor->setAsPrimary();
- }
}
use wcf\data\DatabaseObjectEditor;
use wcf\data\IEditableCachedObject;
use wcf\system\cache\builder\ApplicationCacheBuilder;
-use wcf\system\WCF;
/**
* Provides functions to edit applications.
*/
class ApplicationEditor extends DatabaseObjectEditor implements IEditableCachedObject {
/**
- * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\application\Application';
-
- /**
- * Sets current application as primary application.
- */
- public function setAsPrimary() {
- $sql = "UPDATE wcf".WCF_N."_application
- SET isPrimary = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(0));
-
- $sql = "UPDATE wcf".WCF_N."_application
- SET isPrimary = ?
- WHERE packageID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- 1,
- $this->packageID
- ));
-
- self::resetCache();
- }
-
- /**
- * Sets the first installed application as primary unless an other application already is primary.
- */
- public static function setup() {
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_application
- WHERE isPrimary = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(1));
- $row = $statement->fetchArray();
-
- if ($row['count']) {
- // there is already a primary application
- return;
- }
- else {
- // set first installed application as primary
- $sql = "SELECT packageID
- FROM wcf".WCF_N."_package
- WHERE packageID <> ?
- AND isApplication = ?
- ORDER BY installDate ASC";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- 1,
- 1
- ));
- $row = $statement->fetchArray();
-
- if ($row !== false) {
- $sql = "UPDATE wcf".WCF_N."_application
- SET isPrimary = ?
- WHERE packageID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- 1,
- $row['packageID']
- ));
- }
- }
- }
+ protected static $baseClass = Application::class;
/**
* @see \wcf\data\IEditableCachedObject::resetCache()
<?php
namespace wcf\data\box;
use wcf\data\DatabaseObject;
+use wcf\data\menu\Menu;
+use wcf\data\menu\MenuCache;
use wcf\system\WCF;
use wcf\util\StringUtil;
*/
public static $availablePositions = ['hero', 'headerBoxes', 'top', 'sidebarLeft', 'contentTop', 'sidebarRight', 'contentBottom', 'bottom', 'footerBoxes', 'footer'];
+ /**
+ * menu object
+ * @var Menu
+ */
+ protected $menu;
+
/**
* Returns true if the active user can delete this box.
*
else if ($this->boxType == 'menu') {
return $this->getMenu()->getContent();
}
+
+ $boxContent = $this->getBoxContent();
+ $content = '';
+ if ($this->isMultilingual) {
+ if (isset($boxContent[WCF::getLanguage()->languageID])) $content = $boxContent[WCF::getLanguage()->languageID]['content'];
+ }
else {
- $boxContent = $this->getBoxContent();
- $content = '';
- if ($this->isMultilingual) {
- if (isset($boxContent[WCF::getLanguage()->languageID])) $content = $boxContent[WCF::getLanguage()->languageID]['content'];
- }
- else {
- if (isset($boxContent[0])) $content = $boxContent[0]['content'];
- }
-
- if ($this->boxType == 'text') {
- // @todo parse text
- $content = StringUtil::encodeHTML($content);
- }
-
- return $content;
+ if (isset($boxContent[0])) $content = $boxContent[0]['content'];
}
- return '';
+ if ($this->boxType == 'text') {
+ // @todo parse text
+ $content = StringUtil::encodeHTML($content);
+ }
+
+ return $content;
}
/**
if (isset($boxContent[0])) $content = $boxContent[0]['content'];
}
- return ($content != '');
+ return !empty($content);
}
}
}
public function getMenu() {
- // @todo
+ if ($this->menu === null) {
+ $this->menu = MenuCache::getInstance()->getMenuByID($this->menuID);
+ }
+
+ return $this->menu;
}
/**
FROM wcf".WCF_N."_box
WHERE name = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($name));
- $row = $statement->fetchArray();
- if ($row !== false) return new Box(null, $row);
-
- return null;
+ $statement->execute([$name]);
+
+ return $statement->fetchObject(Box::class);
}
}
--- /dev/null
+<?php
+namespace wcf\data\menu;
+use wcf\data\menu\item\MenuItemNodeTree;
+use wcf\system\cache\builder\MenuCacheBuilder;
+use wcf\system\SingletonFactory;
+
+/**
+ * Manages the menu cache.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.menu
+ * @category Community Framework
+ */
+class MenuCache extends SingletonFactory {
+ /**
+ * @var Menu[]
+ */
+ protected $cachedMenus;
+
+ /**
+ * @var MenuItemNodeTree[]
+ */
+ protected $cachedMenuItems;
+
+ /**
+ * @inheritDoc
+ */
+ protected function init() {
+ $this->cachedMenus = MenuCacheBuilder::getInstance()->getData([], 'menus');
+ $this->cachedMenuItems = MenuCacheBuilder::getInstance()->getData([], 'menuItems');
+ }
+
+ public function getMenuByID($menuID) {
+ if (isset($this->cachedMenus[$menuID])) {
+ return $this->cachedMenus[$menuID];
+ }
+
+ return null;
+ }
+
+ public function getMenuItemsByMenuID($menuID) {
+ if (isset($this->cachedMenuItems[$menuID])) {
+ return $this->cachedMenuItems[$menuID];
+ }
+
+ return null;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\menu;
+use wcf\data\DatabaseObjectDecorator;
+use wcf\data\menu\item\MenuItemNodeTree;
+use wcf\system\WCF;
+
+class ViewableMenu extends DatabaseObjectDecorator {
+ /**
+ * @var MenuItemNodeTree
+ */
+ protected $menuItems;
+
+ public function hasContent() {
+ // TODO
+ return true;
+ }
+
+ public function getContent() {
+ return WCF::getTPL()->fetch('__menu', 'wcf', ['menuItems' => $this->menuItems->getNodeList()]);
+ }
+
+ protected function getMenuItems() {
+ if ($this->menuItems === null) {
+ $this->menuItems = MenuCache::getInstance()->getMenuItemsByMenuID($this->object->menuID);
+ }
+
+ return $this->menuItems;
+ }
+}
* menu id
* @var integer
*/
- public $menuID = null;
+ public $menuID;
/**
* list of menu items
* @var MenuItem[]
*/
- public $menuItems = array();
+ public $menuItems = [];
/**
* menu item structure
* @var mixed[]
*/
- public $menuItemStructure = array();
+ public $menuItemStructure = [];
/**
* root node
* @var MenuItemNode
*/
- public $node = null;
+ public $node;
/**
* Creates a new MenuItemNodeTree object.
/**
* Generates the node tree recursively
*
- * @param integer $parentID
- * @param MenuItemNode $parentNode
- * @param int[] $filter
- * @return MenuItemNode[]
+ * @param integer $parentID parent menu item id
+ * @param MenuItemNode $parentNode parent menu item object
+ * @return MenuItemNode[] nested menu item tree
*/
protected function generateNodeTree($parentID = null, MenuItemNode $parentNode = null) {
$nodes = array();
// @todo
}
+ /**
+ * Returns the page's internal name.
+ *
+ * @return string
+ */
+ public function __toString() {
+ return $this->name;
+ }
+
/**
* Returns the page with the given identifier.
*
}
if ($redirect) {
+ die("should redirect");
$redirectURL = $this->canonicalURL;
if (!empty($requestURL['query'])) {
$queryString = $requestURL['query'];
$loadedApplications = array();
// register WCF as application
- self::$applications['wcf'] = ApplicationHandler::getInstance()->getWCF();
+ self::$applications['wcf'] = ApplicationHandler::getInstance()->getApplicationByID(1);
+ // TODO: what exactly should the base href represent and how should it be calculated, also because
+ // defining it here eventually breaks the ACP due to tpl initialization occurs first
+ if (!class_exists(WCFACP::class, false)) {
+ $this->getTPL()->assign('baseHref', self::$applications['wcf']->getPageURL());
+ }
+
+ // TODO: this is required for the uninstallation of applications, find a different solution!
if (PACKAGE_ID == 1) {
- return;
+ //return;
}
// start main application
$application = ApplicationHandler::getInstance()->getActiveApplication();
- $loadedApplications[] = $this->loadApplication($application);
-
- // register primary application
- $abbreviation = ApplicationHandler::getInstance()->getAbbreviation($application->packageID);
- self::$applications[$abbreviation] = $application;
+ if ($application->packageID != 1) {
+ $loadedApplications[] = $this->loadApplication($application);
+
+ // register primary application
+ $abbreviation = ApplicationHandler::getInstance()->getAbbreviation($application->packageID);
+ self::$applications[$abbreviation] = $application;
+ }
// start dependent applications
$applications = ApplicationHandler::getInstance()->getDependentApplications();
foreach ($applications as $application) {
+ if ($application->packageID == 1) {
+ // ignore WCF
+ continue;
+ }
+
$loadedApplications[] = $this->loadApplication($application, true);
}
*/
public function getFavicon() {
$activeApplication = ApplicationHandler::getInstance()->getActiveApplication();
- $primaryApplication = ApplicationHandler::getInstance()->getPrimaryApplication();
+ $wcf = ApplicationHandler::getInstance()->getWCF();
- if ($activeApplication->domainName != $primaryApplication->domainName) {
+ if ($activeApplication->domainName !== $wcf->domainName) {
if (file_exists(WCF_DIR.'images/favicon.ico')) {
$favicon = file_get_contents(WCF_DIR.'images/favicon.ico');
class ApplicationHandler extends SingletonFactory {
/**
* application cache
- * @var array<array>
+ * @var Application[]
*/
- protected $cache = null;
+ protected $cache;
/**
* list of page URLs
- * @var array<string>
+ * @var string[]
*/
- protected $pageURLs = array();
+ protected $pageURLs = [];
/**
* Initializes cache.
$this->cache = ApplicationCacheBuilder::getInstance()->getData();
}
- /**
- * Returns the primary application.
- *
- * @return Application
- */
- public function getPrimaryApplication() {
- $packageID = ($this->cache['primary']) ?: PACKAGE_ID;
-
- if (isset($this->cache['application'][$packageID])) {
- return $this->cache['application'][$packageID];
- }
-
- return $this->cache['wcf'];
- }
-
/**
* Returns an application based upon it's abbreviation. Will return the
* primary application if $abbreviation equals to 'wcf'
* @return Application
*/
public function getApplication($abbreviation) {
- if ($abbreviation == 'wcf') {
- return $this->getPrimaryApplication();
- }
-
if (isset($this->cache['abbreviation'][$abbreviation])) {
$packageID = $this->cache['abbreviation'][$abbreviation];
* e.g. cross-domain files requestable through the webserver.
*
* @return Application
+ * @deprecated 2.2 please use `getApplication()` instead
*/
public function getWCF() {
- return $this->cache['wcf'];
+ return $this->getApplicationByID(1);
}
/**
<?php
namespace wcf\system\box;
+use wcf\data\box\Box;
use wcf\data\box\BoxList;
use wcf\system\SingletonFactory;
class BoxHandler extends SingletonFactory {
/**
* boxes grouped by position
- * @var array
+ * @var Box[][]
*/
protected $boxes = [];
* Returns boxes for the given position.
*
* @param string $position
- * @return \wcf\data\box\Box[]
+ * @return Box[]
*/
public function getBoxes($position) {
if (isset($this->boxes[$position])) {
<?php
namespace wcf\system\breadcrumb;
-use wcf\system\menu\page\PageMenu;
use wcf\system\SingletonFactory;
-use wcf\system\WCF;
/**
* Manages breadcrumbs.
class Breadcrumbs extends SingletonFactory implements \Countable, \Iterator {
/**
* list of breadcrumbs
- * @var array<\wcf\system\breadcrumb\Breadcrumb>
+ * @var Breadcrumb[]
*/
- protected $items = array();
+ protected $items = [];
/**
* Current iterator-index
protected $index = 0;
/**
- * @see \wcf\system\SingletonFactory::init()
+ * @inheritDoc
*/
protected function init() {
// add main breadcrumbs entry
- $this->add(new Breadcrumb(WCF::getLanguage()->get(PAGE_TITLE), PageMenu::getInstance()->getLandingPage()->getProcessor()->getLink()));
+ // TODO: there is no longer a global landing page, what should be displayed instead?
+ //$this->add(new Breadcrumb(WCF::getLanguage()->get(PAGE_TITLE), PageMenu::getInstance()->getLandingPage()->getProcessor()->getLink()));
}
/**
* Adds a breadcrumb (insertion order is crucial!).
*
- * @param \wcf\system\breadcrumb\Breadcrumb $item
+ * @param Breadcrumb $item
*/
public function add(Breadcrumb $item) {
$this->items[] = $item;
/**
* Returns the list of breadcrumbs.
*
- * @return array<\wcf\system\breadcrumb\Breadcrumb>
+ * @return Breadcrumb[]
*/
public function get() {
return $this->items;
/**
* Replaces a breadcrumb, returns true if replacement was successful.
*
- * @param \wcf\system\breadcrumb\Breadcrumb $item
- * @param integer $index
+ * @param Breadcrumb $item
+ * @param integer $index
* @return boolean
*/
public function replace(Breadcrumb $item, $index) {
}
/**
- * @see \Countable::count()
+ * @inheritDoc
*/
public function count() {
return count($this->items);
}
/**
- * @see \Iterator::current()
+ * @inheritDoc
*/
public function current() {
return $this->items[$this->index];
}
/**
- * @see \Iterator::key()
+ * @inheritDoc
*/
public function key() {
return $this->index;
}
/**
- * @see \Iterator::valid()
+ * @inheritDoc
*/
public function valid() {
return isset($this->items[$this->index]);
}
/**
- * @see \Iterator::rewind()
+ * @inheritDoc
*/
public function rewind() {
$this->index = 0;
}
/**
- * @see \Iterator::next()
+ * @inheritDoc
*/
public function next() {
$this->index++;
*/
class ApplicationCacheBuilder extends AbstractCacheBuilder {
/**
- * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
+ * @inheritDoc
*/
public function rebuild(array $parameters) {
- $data = array(
- 'abbreviation' => array(),
- 'application' => array(),
- 'primary' => 0,
- 'wcf' => null
- );
+ $data = [
+ 'abbreviation' => [],
+ 'application' => []
+ ];
// fetch applications
$applicationList = new ApplicationList();
$applicationList->readObjects();
- $applications = $applicationList->getObjects();
- foreach ($applications as $application) {
+ foreach ($applicationList as $application) {
$data['application'][$application->packageID] = $application;
-
- // save primary application's package id
- if ($application->isPrimary) {
- $data['primary'] = $application->packageID;
- }
}
// fetch abbreviations
$packageList = new PackageList();
- $packageList->getConditionBuilder()->add('package.isApplication = ?', array(1));
+ $packageList->getConditionBuilder()->add('package.isApplication = ?', [1]);
$packageList->readObjects();
- foreach ($packageList->getObjects() as $package) {
+ foreach ($packageList as $package) {
$data['abbreviation'][Package::getAbbreviation($package->package)] = $package->packageID;
}
- // assign wcf pseudo-application
- if (PACKAGE_ID) {
- $data['wcf'] = $data['application'][1];
- unset($data['application'][1]);
- }
-
return $data;
}
}
--- /dev/null
+<?php
+namespace wcf\system\cache\builder;
+use wcf\data\menu\item\MenuItemNodeTree;
+use wcf\data\menu\MenuList;
+
+/**
+ * Caches menus and menu item node trees.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.cache.builder
+ * @category Community Framework
+ */
+class MenuCacheBuilder extends AbstractCacheBuilder {
+ /**
+ * @inheritDoc
+ */
+ protected function rebuild(array $parameters) {
+ $data = [
+ 'menus' => [],
+ 'menuItems' => []
+ ];
+
+ $menuList = new MenuList();
+ $menuList->readObjects();
+ foreach ($menuList as $menu) {
+ $data['menus'][$menu->menuID] = $menu;
+ $data['menuItems'][$menu->menuID] = new MenuItemNodeTree($menu->menuID);
+ }
+
+ return $data;
+ }
+}
<?php
namespace wcf\system\cache\builder;
use wcf\data\application\Application;
+use wcf\data\page\Page;
use wcf\system\application\ApplicationHandler;
+use wcf\system\request\ControllerMap;
use wcf\system\WCF;
use wcf\util\FileUtil;
protected function rebuild(array $parameters) {
return [
'ciControllers' => $this->getCaseInsensitiveControllers(),
- 'customUrls' => $this->getCustomUrls()
+ 'customUrls' => $this->getCustomUrls(),
+ 'landingPages' => $this->getLandingPages()
];
}
return $data;
}
+
+ /**
+ * Returns the list of landing pages per application.
+ *
+ * @return string[]
+ */
+ protected function getLandingPages() {
+ $data = [];
+
+ if (!PACKAGE_ID) {
+ return $data;
+ }
+
+ foreach (ApplicationHandler::getInstance()->getApplications() as $application) {
+ if ($application->landingPageID) {
+ $page = new Page($application->landingPageID);
+ if ($page->controller) {
+ $controller = $page->controller;
+ }
+ else {
+ $controller = '__WCF_CMS__' . $page->pageID;
+ $controller = [$controller, $controller];
+ }
+ }
+ else if ($application->packageID == 1) {
+ // WCF has no default controller
+ $controller = ['', ''];
+ }
+ else {
+ $controller = preg_replace('~^.*?\\\([^\\\]+)(?:Action|Form|Page)$~', '\\1', WCF::getApplicationObject($application)->getPrimaryController());
+ $controller = [
+ $controller,
+ ControllerMap::transformController($controller)
+ ];
+ }
+
+ $data[ApplicationHandler::getInstance()->getAbbreviation($application->packageID)] = $controller;
+ }
+
+ return $data;
+ }
}
*/
class PageMenu extends TreeMenu {
/**
- * landing page menu item
- * @var \wcf\data\page\menu\item\PageMenuItem
- */
- protected $landingPage = null;
-
- /**
- * @see \wcf\system\SingletonFactory::init()
+ * @inheritDoc
* @throws SystemException
*/
protected function init() {
// call init event
EventHandler::getInstance()->fireAction($this, 'init');
-
- foreach ($this->menuItems as $menuItems) {
- foreach ($menuItems as $menuItem) {
- if ($menuItem->isLandingPage) {
- $this->landingPage = $menuItem;
- break 2;
- }
- }
- }
-
- if ($this->landingPage === null) {
- throw new SystemException("Missing landing page");
- }
-
- $this->setActiveMenuItem($this->landingPage->menuItem);
}
/**
- * Returns landing page menu item.
- *
- * @return \wcf\data\page\menu\item\PageMenuItem
- */
- public function getLandingPage() {
- return $this->landingPage;
- }
-
- /**
- * @see \wcf\system\menu\TreeMenu::loadCache()
+ * @inheritDoc
*/
protected function loadCache() {
parent::loadCache();
}
/**
- * @see \wcf\system\menu\TreeMenu::checkMenuItem()
+ * @inheritDoc
*/
protected function checkMenuItem(ITreeMenuItem $item) {
- // landing page must always be accessible
- if ($item->isLandingPage) {
- return true;
- }
-
if (!parent::checkMenuItem($item)) return false;
if ($item instanceof ProcessibleDatabaseObject && $item->getProcessor() instanceof IPageMenuItemProvider) {
}
/**
- * @see \wcf\system\menu\TreeMenu::setActiveMenuItem()
+ * @inheritDoc
*/
public function setActiveMenuItem($menuItem) {
if (isset($this->menuItemList[$menuItem]) && $this->menuItemList[$menuItem]->menuPosition == 'footer') {
use wcf\data\package\Package;
use wcf\data\package\PackageEditor;
use wcf\system\application\ApplicationHandler;
-use wcf\data\object\type\ObjectTypeCache;
use wcf\system\cache\builder\TemplateListenerCodeCacheBuilder;
use wcf\system\cache\CacheHandler;
use wcf\system\database\statement\PreparedStatement;
/**
* instance of PackageArchive
- * @var \wcf\system\package\PackageArchive
+ * @var PackageArchive
*/
- public $archive = null;
+ public $archive;
/**
* instance of PackageInstallationNodeBuilder
- * @var \wcf\system\package\PackageInstallationNodeBuilder
+ * @var PackageInstallationNodeBuilder
*/
- public $nodeBuilder = null;
+ public $nodeBuilder;
/**
* instance of Package
- * @var \wcf\data\package\Package
+ * @var Package
*/
- public $package = null;
+ public $package;
/**
* instance of PackageInstallationQueue
- * @var \wcf\system\package\PackageInstallationQueue
+ * @var PackageInstallationQueue
*/
- public $queue = null;
+ public $queue;
/**
* default name of the config file
/**
* data of previous package in queue
- * @var array<string>
+ * @var string[]
*/
- protected $previousPackageData = null;
+ protected $previousPackageData;
/**
* Creates a new instance of PackageInstallationDispatcher.
*
- * @param \wcf\data\package\installation\queue\PackageInstallationQueue $queue
+ * @param PackageInstallationQueue $queue
*/
public function __construct(PackageInstallationQueue $queue) {
$this->queue = $queue;
/**
* Sets data of previous package in queue.
*
- * @param array<string> $packageData
+ * @param string[] $packageData
*/
public function setPreviousPackage(array $packageData) {
$this->previousPackageData = $packageData;
* Installs node components and returns next node.
*
* @param string $node
- * @return \wcf\system\package\PackageInstallationStep
+ * @return PackageInstallationStep
*/
public function install($node) {
$nodes = $this->nodeBuilder->getNodeData($node);
// invoke node-specific actions
+ $step = null;
foreach ($nodes as $data) {
$nodeData = unserialize($data['nodeData']);
$this->nodeBuilder->completeNode($node);
// assign next node
- $tmp = $node;
$node = $this->nodeBuilder->getNextNode($node);
$step->setNode($node);
SET optionValue = ?
WHERE optionName = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
TIME_NOW,
'last_update_time'
- ));
+ ]);
// update options.inc.php
OptionEditor::resetCache();
WHERE optionName = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
StringUtil::getUUID(),
'wcf_uuid'
- ));
+ ]);
try {
$statement->execute([
}
if (WCF::getSession()->getVar('__wcfSetup_developerMode')) {
- $statement->execute(array(
+ $statement->execute([
1,
'enable_debug_mode'
- ));
- $statement->execute(array(
+ ]);
+ $statement->execute([
'public',
'exception_privacy'
- ));
+ ]);
}
// update options.inc.php
// rebuild application paths
ApplicationHandler::rebuild();
- ApplicationEditor::setup();
}
// remove template listener cache
AND package.packageID <> ?
AND package.isApplication = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
$this->queue->processNo,
1,
1
- ));
+ ]);
while ($row = $statement->fetchArray()) {
Package::writeConfigFile($row['packageID']);
}
FROM wcf".WCF_N."_package_installation_queue
WHERE processNo = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->queue->processNo));
+ $statement->execute([$this->queue->processNo]);
while ($row = $statement->fetchArray()) {
@unlink($row['archive']);
}
$sql = "DELETE FROM wcf".WCF_N."_package_installation_queue
WHERE processNo = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->queue->processNo));
+ $statement->execute([$this->queue->processNo]);
}
return $step;
/**
* Returns current package archive.
*
- * @return \wcf\system\package\PackageArchive
+ * @return PackageArchive
*/
public function getArchive() {
if ($this->archive === null) {
// package_installation_queue with this value
$archive = $this->archive->downloadArchive();
$queueEditor = new PackageInstallationQueueEditor($this->queue);
- $queueEditor->update(array(
- 'archive' => $archive
- ));
+ $queueEditor->update(['archive' => $archive]);
}
$this->archive->openArchive();
/**
* Installs current package.
*
- * @param array $nodeData
+ * @param mixed[] $nodeData
+ * @return PackageInstallationStep
*/
protected function installPackage(array $nodeData) {
$installationStep = new PackageInstallationStep();
FROM wcf".WCF_N."_package
WHERE packageID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($requirementData['packageID']));
+ $statement->execute([$requirementData['packageID']]);
}
else {
// try to find matching package
FROM wcf".WCF_N."_package
WHERE package = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($package));
+ $statement->execute([$package]);
}
$row = $statement->fetchArray();
$sql = "DELETE FROM wcf".WCF_N."_package_exclusion
WHERE packageID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->queue->packageID));
+ $statement->execute([$this->queue->packageID]);
// delete old requirements and dependencies
$sql = "DELETE FROM wcf".WCF_N."_package_requirement
WHERE packageID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->queue->packageID));
+ $statement->execute([$this->queue->packageID]);
}
else {
// create package entry
// update package id for current queue
$queueEditor = new PackageInstallationQueueEditor($this->queue);
- $queueEditor->update(array(
- 'packageID' => $package->packageID
- ));
+ $queueEditor->update(['packageID' => $package->packageID]);
// reload queue
$this->queue = new PackageInstallationQueue($this->queue->queueID);
if ($package->isApplication) {
$host = str_replace(RouteHandler::getProtocol(), '', RouteHandler::getHost());
- $path = RouteHandler::getPath(array('acp'));
+ $path = RouteHandler::getPath(['acp']);
// insert as application
- ApplicationEditor::create(array(
+ ApplicationEditor::create([
'domainName' => $host,
'domainPath' => $path,
'cookieDomain' => $host,
'cookiePath' => $path,
'packageID' => $package->packageID
- ));
+ ]);
}
}
$statement = WCF::getDB()->prepareStatement($sql);
foreach ($this->getArchive()->getExcludedPackages() as $excludedPackage) {
- $statement->execute(array($this->queue->packageID, $excludedPackage['name'], (!empty($excludedPackage['version']) ? $excludedPackage['version'] : '')));
+ $statement->execute([
+ $this->queue->packageID,
+ $excludedPackage['name'],
+ (!empty($excludedPackage['version']) ? $excludedPackage['version'] : '')
+ ]);
}
}
foreach ($requirements as $identifier => $possibleRequirements) {
$requirement = array_shift($possibleRequirements);
- $statement->execute(array($this->queue->packageID, $requirement['packageID']));
+ $statement->execute([
+ $this->queue->packageID,
+ $requirement['packageID']
+ ]);
}
}
/**
* Executes a package installation plugin.
*
- * @param array step
+ * @param mixed[] $nodeData
* @return boolean
*/
protected function executePIP(array $nodeData) {
FROM wcf".WCF_N."_package_installation_plugin
WHERE pluginName = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- $nodeData['pip']
- ));
+ $statement->execute([$nodeData['pip']]);
$row = $statement->fetchArray();
// PIP is unknown
// set default value
if (empty($nodeData['value'])) {
- $defaultValue = call_user_func(array($className, 'getDefaultFilename'));
+ $defaultValue = call_user_func([$className, 'getDefaultFilename']);
if ($defaultValue) {
$nodeData['value'] = $defaultValue;
}
$plugin = new $className($this, $nodeData);
if (!($plugin instanceof IPackageInstallationPlugin)) {
- throw new SystemException("'".$className."' does not implement 'wcf\system\package\plugin\IPackageInstallationPlugin'");
+ throw new SystemException("'".$className."' does not implement 'wcf\\system\\package\\plugin\\IPackageInstallationPlugin'");
}
// execute PIP
--- /dev/null
+<?php
+namespace wcf\system\package\plugin;
+use wcf\data\box\Box;
+use wcf\data\box\BoxEditor;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+
+/**
+ * Installs, updates and deletes boxes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage acp.package.plugin
+ * @category Community Framework
+ */
+class BoxPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+ /**
+ * @inheritDoc
+ */
+ public $className = BoxEditor::class;
+
+ /**
+ * @inheritDoc
+ */
+ public $tagName = 'box';
+
+ /**
+ * @inheritDoc
+ */
+ protected function handleDelete(array $items) {
+ $sql = "DELETE FROM wcf".WCF_N."_box
+ WHERE identifier = ?
+ AND packageID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($items as $item) {
+ $statement->execute([
+ $item['attributes']['identifier'],
+ $this->installation->getPackageID()
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+ }
+
+ /**
+ * @inheritDoc
+ * @throws SystemException
+ */
+ protected function getElement(\DOMXPath $xpath, array &$elements, \DOMElement $element) {
+ $nodeValue = $element->nodeValue;
+
+ if ($element->tagName === 'name' || $element->tagName === 'title') {
+ if (empty($element->getAttribute('language'))) {
+ throw new SystemException("Missing required attribute 'language' for '" . $element->tagName . "' element (box '" . $element->parentNode->getAttribute('identifier') . "')");
+ }
+
+ // element can occur multiple times using the `language` attribute
+ if (!isset($elements[$element->tagName])) $elements[$element->tagName] = [];
+
+ $elements[$element->tagName][$element->getAttribute('language')] = $element->nodeValue;
+ }
+ else if ($element->tagName === 'content') {
+ // content can occur multiple times using the `language` attribute
+ if (!isset($elements['content'])) $elements['content'] = [];
+
+ $children = [];
+ /** @var \DOMElement $child */
+ foreach ($xpath->query('child::*', $element) as $child) {
+ $children[$child->tagName] = $child->nodeValue;
+ }
+
+ if (empty($children['title'])) {
+ throw new SystemException("Expected non-empty child element 'title' for 'content' element (box '" . $element->parentNode->getAttribute('identifier') . "')");
+ }
+ if (empty($children['content'])) {
+ throw new SystemException("Expected non-empty child element 'content' for 'content' element (box '" . $element->parentNode->getAttribute('identifier') . "')");
+ }
+
+ $elements['content'][$element->getAttribute('language')] = [
+ 'content' => $children['content'],
+ 'title' => $children['title']
+ ];
+ }
+ else {
+ $elements[$element->tagName] = $nodeValue;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ * @throws SystemException
+ */
+ protected function prepareImport(array $data) {
+ $boxType = $data['elements']['boxtype'];
+ $className = '';
+ $identifier = $data['attributes']['identifier'];
+ $isMultilingual = false;
+ $position = $data['elements']['position'];
+
+ if (!in_array($position, ['bottom', 'contentBottom', 'contentTop', 'footer', 'footerBoxes', 'headerBoxes', 'hero', 'sidebarLeft', 'sidebarRight', 'top'])) {
+ throw new SystemException("Unknown box position '{$position}' for box '{$identifier}'");
+ }
+
+ switch ($boxType) {
+ case 'system':
+ if (empty($data['elements']['classname'])) {
+ throw new SystemException("Missing required element 'classname' for 'system'-type box '{$identifier}'");
+ }
+
+ $className = $data['elements']['classname'];
+ break;
+
+ case 'html':
+ case 'text':
+ if (empty($data['elements']['content'])) {
+ throw new SystemException("Missing required 'content' element(s) for box '{$identifier}'");
+ }
+
+ if (count($data['elements']['content']) === 1) {
+ if (!isset($data['elements']['content'][''])) {
+ throw new SystemException("Expected one 'content' element without a 'language' attribute for box '{$identifier}'");
+ }
+ }
+ else {
+ $isMultilingual = true;
+
+ if (isset($data['elements']['content'][''])) {
+ throw new SystemException("Cannot mix 'content' elements with and without 'language' attribute for box '{$identifier}'");
+ }
+ }
+
+ break;
+
+ default:
+ throw new SystemException("Unknown type '{$boxType}' for box '{$identifier}");
+ break;
+ }
+
+ return [
+ 'identifier' => $identifier,
+ 'name' => $this->getI18nValues($data['elements']['name'], true),
+ 'boxType' => $boxType,
+ 'position' => $position,
+ 'showOrder' => $this->getItemOrder($position),
+ 'visibleEverywhere' => (isset($data['elements']['visibleeverywhere']) && $data['elements']['visibleeverywhere'] === '1') ? '1' : '0',
+ 'isMultilingual' => ($isMultilingual) ? '1' : '0',
+ 'cssClassName' => (!empty($data['elements']['cssClassName'])) ? $data['elements']['cssClassName'] : '',
+ 'showHeader' => (isset($data['elements']['showheader']) && $data['elements']['showheader'] === '1') ? '1' : '0',
+ 'originIsSystem' => 1,
+ 'className' => $className
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function findExistingItem(array $data) {
+ $sql = "SELECT *
+ FROM wcf".WCF_N."_box
+ WHERE identifier = ?
+ AND packageID = ?";
+ $parameters = array(
+ $data['identifier'],
+ $this->installation->getPackageID()
+ );
+
+ return array(
+ 'sql' => $sql,
+ 'parameters' => $parameters
+ );
+ }
+
+ /**
+ * Returns the show order for a new item that will append it to the current
+ * menu or parent item.
+ *
+ * @param string $position box position
+ * @return integer
+ */
+ protected function getItemOrder($position) {
+ $sql = "SELECT MAX(showOrder) AS showOrder
+ FROM wcf".WCF_N."_box
+ WHERE position = ?";
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute([$position]);
+
+ $row = $statement->fetchSingleRow();
+
+ return (!$row['showOrder']) ? 1 : $row['showOrder'] + 1;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function import(array $row, array $data) {
+ // updating boxes is only supported for 'system' type boxes, all other
+ // types would potentially overwrite changes made by the user if updated
+ if (!empty($row) && $row['boxType'] !== 'system') {
+ return new Box(null, $row);
+ }
+
+ return parent::import($row, $data);
+ }
+}
<?php
namespace wcf\system\package\plugin;
+use wcf\data\box\Box;
+use wcf\data\box\BoxEditor;
use wcf\data\menu\Menu;
use wcf\data\menu\MenuEditor;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\SystemException;
use wcf\system\WCF;
* @category Community Framework
*/
class MenuPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+ /**
+ * box meta data per menu
+ * @var string[]
+ */
+ public $boxData = [];
+
/**
* @inheritDoc
*/
$elements['title'][$element->getAttribute('language')] = $element->nodeValue;
}
+ else if ($element->tagName === 'box') {
+ $elements['box'] = [];
+
+ /** @var \DOMElement $child */
+ foreach ($xpath->query('child::*', $element) as $child) {
+ if ($child->tagName === 'name') {
+ if (empty($child->getAttribute('language'))) {
+ throw new SystemException("Missing required attribute 'language' for box name (menu '" . $element->parentNode->getAttribute('identifier') . "')");
+ }
+
+ // <title> can occur multiple times using the `language` attribute
+ if (!isset($elements['box']['name'])) $elements['box']['name'] = [];
+
+ $elements['box']['name'][$element->getAttribute('language')] = $element->nodeValue;
+ }
+ else {
+ $elements['box'][$child->tagName] = $child->nodeValue;
+ }
+ }
+ }
else {
$elements[$element->tagName] = $nodeValue;
}
* @inheritDoc
*/
protected function prepareImport(array $data) {
+ $identifier = $data['attributes']['identifier'];
+
+ if (!empty($data['elements']['box'])) {
+ $position = $data['elements']['box']['position'];
+ $visibleEverywhere = false;
+
+ if ($identifier === 'com.woltlab.wcf.MainMenu') {
+ $position = 'mainMenu';
+ $visibleEverywhere = true;
+ }
+ else if (!in_array($position, ['bottom', 'contentBottom', 'contentTop', 'footer', 'footerBoxes', 'headerBoxes', 'hero', 'sidebarLeft', 'sidebarRight', 'top'])) {
+ throw new SystemException("Unknown box position '{$position}' for menu box '{$identifier}'");
+ }
+
+ $this->boxData[$identifier] = [
+ 'identifier' => $identifier,
+ 'name' => $this->getI18nValues($data['elements']['title'], true),
+ 'boxType' => 'menu',
+ 'position' => $position,
+ 'visibleEverywhere' => ($visibleEverywhere) ? 1 : 0,
+ 'cssClassName' => (!empty($data['elements']['box']['cssclassname'])),
+ 'originIsSystem' => 1,
+ 'packageID' => $this->installation->getPackageID()
+ ];
+
+ unset($data['elements']['box']);
+ }
+
return [
- 'identifier' => $data['attributes']['identifier'],
+ 'identifier' => $identifier,
'title' => $this->getI18nValues($data['elements']['title']),
'originIsSystem' => 1
];
return parent::import($row, $data);
}
+
+ /**
+ * @inheritDoc
+ */
+ protected function postImport() {
+ if (empty($this->boxData)) return;
+
+ // all boxes belonging to the identifiers
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("identifier IN (?)", [array_keys($this->boxData)]);
+ $conditions->add("packageID = ?", [$this->installation->getPackageID()]);
+
+ $sql = "SELECT *
+ FROM wcf".WCF_N."_box
+ ".$conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $boxes = [];
+ while ($box = $statement->fetchObject(Box::class)) {
+ $boxes[$box->identifier] = $box;
+ }
+
+ foreach ($this->boxData as $identifier => $data) {
+ if (isset($boxes[$identifier])) {
+ // skip both 'identifier' and 'packageID' as these properties are immutable
+ unset($data['identifier']);
+ unset($data['packageID']);
+
+ $boxEditor = new BoxEditor($boxes[$identifier]);
+ $boxEditor->update($data);
+ }
+ else {
+ BoxEditor::create($data);
+ }
+ }
+ }
}
*/
protected function handleDelete(array $items) {
$sql = "DELETE FROM wcf".WCF_N."_page
- WHERE name = ?
+ WHERE identifier = ?
AND packageID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
if (!empty($data['elements']['parent'])) {
$sql = "SELECT pageID
FROM wcf".WCF_N."_".$this->tableName."
- WHERE name = ?";
+ WHERE identifier = ?";
$statement = WCF::getDB()->prepareStatement($sql, 1);
$statement->execute([$data['elements']['parent']]);
$row = $statement->fetchSingleRow();
protected function findExistingItem(array $data) {
$sql = "SELECT *
FROM wcf".WCF_N."_".$this->tableName."
- WHERE name = ?
+ WHERE identifier = ?
AND packageID = ?";
$parameters = array(
$data['identifier'],
<?php
namespace wcf\system\request;
use wcf\page\CmsPage;
+use wcf\system\application\ApplicationHandler;
use wcf\system\cache\builder\RoutingCacheBuilder;
use wcf\system\exception\SystemException;
use wcf\system\SingletonFactory;
+use wcf\system\WCF;
/**
* Resolves incoming requests and performs lookups for controller to url mappings.
*/
protected $customUrls;
+ /**
+ * @var string[]
+ */
+ protected $landingPages;
+
/**
* list of <ControllerName> to <controller-name> mappings
* @var array<string>
protected function init() {
$this->ciControllers = RoutingCacheBuilder::getInstance()->getData([], 'ciControllers');
$this->customUrls = RoutingCacheBuilder::getInstance()->getData([], 'customUrls');
+ $this->landingPages = RoutingCacheBuilder::getInstance()->getData([], 'landingPages');
}
/**
$urlController = $this->customUrls['reverse'][$application][$controller];
}
else {
- $parts = preg_split('~([A-Z][a-z0-9]+)~', $controller, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
- $parts = array_map('strtolower', $parts);
-
- $urlController = implode('-', $parts);
+ $urlController = self::transformController($controller);
}
$this->lookupCache[$lookupKey] = $urlController;
return null;
}
+ /**
+ * Lookups default controller for given application.
+ *
+ * @param string $application application identifier
+ * @return null|string[] default controller
+ */
+ public function lookupDefaultController($application) {
+ $controller = $this->landingPages[$application][1];
+
+ if ($application === 'wcf' && empty($controller)) {
+ return null;
+ }
+ else if (preg_match('~^__WCF_CMS__(?P<pageID>\d+)$~', $controller, $matches)) {
+ $cmsPageData = $this->lookupCmsPage($matches['pageID'], 0);
+ if ($cmsPageData === null) {
+ // page is multilingual, use current language id to resolve request
+ $cmsPageData = $this->lookupCmsPage($matches['pageID'], WCF::getLanguage()->languageID);
+
+ if ($cmsPageData === null) {
+ throw new SystemException("Unable to resolve CMS page");
+ }
+ }
+
+ // different application, redirect instead
+ if ($cmsPageData['application'] !== $application) {
+ return ['redirect' => LinkHandler::getInstance()->getCmsLink($matches['pageID'])];
+ }
+ else {
+ return $this->resolveCustomController($cmsPageData['application'], $cmsPageData['controller']);
+ }
+ }
+
+ return [
+ 'application' => $application,
+ 'controller' => $controller
+ ];
+ }
+
+ /**
+ * Returns true if given controller is the application's default.
+ *
+ * @param string $application application identifier
+ * @param string $controller url controller name
+ * @return boolean true if controller is the application's default
+ */
+ public function isDefaultController($application, $controller) {
+ // lookup custom urls first
+ if (isset($this->customUrls['lookup'][$application], $this->customUrls['lookup'][$application][$controller])) {
+ $controller = $this->customUrls['lookup'][$application][$controller];
+ if (strpos($controller, '__WCF_CMS__') !== false) {
+ // remove language id component
+ $controller = preg_replace('~\-\d+$~', '', $controller);
+ }
+ }
+
+ if ($this->landingPages[$application][0] === $controller) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Returns the class data for the active request or null if for the given
* configuration no proper class exist.
* @param string $controller controller name
* @param boolean $isAcpRequest true if this is an ACP request
* @param string $pageType page type, e.g. 'form' or 'action'
- * @return array<string> className, controller and pageType
+ * @return string[] className, controller and pageType
*/
protected function getClassData($application, $controller, $isAcpRequest, $pageType) {
$className = $application . '\\' . ($isAcpRequest ? 'acp\\' : '') . $pageType . '\\' . $controller . ucfirst($pageType);
'pageType' => $pageType
];
}
+
+ /**
+ * Transforms a controller into its URL representation.
+ *
+ * @param string $controller controller, e.g. 'BoardList'
+ * @return string url representation, e.g. 'board-list'
+ */
+ public static function transformController($controller) {
+ $parts = preg_split('~([A-Z][a-z0-9]+)~', $controller, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+ $parts = array_map('strtolower', $parts);
+
+ return implode('-', $parts);
+ }
}
*/
protected $pattern = '';
- /**
- * primary application's abbreviation (e.g. "wbb")
- * @var string
- */
- protected $primaryApplication = '';
-
/**
* list of required components
* @var array<string>
if (!RequestHandler::getInstance()->isACPRequest()) {
$landingPage = PageMenu::getInstance()->getLandingPage();
- if ($this->primaryApplication === '') {
- $primaryApplication = ApplicationHandler::getInstance()->getPrimaryApplication();
- $this->primaryApplication = ApplicationHandler::getInstance()->getAbbreviation($primaryApplication->packageID);
- }
// check if this is the default controller
if (strcasecmp(RouteHandler::getInstance()->getDefaultController($application), $components['controller']) === 0) {
// check if this matches the primary application
- if ($this->primaryApplication === $application) {
+ /*
+ * TODO: what exactly is this doing?
+ */
+ /*if ($this->primaryApplication === $application) {
if (strcasecmp($landingPage->getController(), $components['controller']) === 0) {
// skip controller if it matches the default controller
$ignoreController = true;
// skip default controller
$ignoreController = true;
}
+ */
}
else if (strcasecmp($landingPage->getController(), $components['controller']) === 0) {
// landing page
class LinkHandler extends SingletonFactory {
/**
* regex object to filter title
- * @var \wcf\system\RegEx
+ * @var RegEx
*/
- protected $titleRegex = null;
+ protected $titleRegex;
/**
* title search strings
- * @var array<string>
+ * @var string[]
*/
- protected $titleSearch = array();
+ protected $titleSearch = [];
/**
* title replacement strings
- * @var array<string>
+ * @var string[]
*/
- protected $titleReplace = array();
+ protected $titleReplace = [];
/**
* @param string $url
* @return string
*/
- public function getLink($controller = null, array $parameters = array(), $url = '') {
+ public function getLink($controller = null, array $parameters = [], $url = '') {
$abbreviation = 'wcf';
$anchor = '';
$isACP = $originIsACP = RequestHandler::getInstance()->isACPRequest();
- $forceWCF = $isRaw = false;
+ $isRaw = false;
$appendSession = $encodeTitle = true;
// enforce a certain level of sanitation and protection for links embedded in emails
unset($parameters['forceFrontend']);
}
if (isset($parameters['forceWCF'])) {
- if ($parameters['forceWCF'] && $isACP) {
- $forceWCF = true;
- }
+ /** @deprecated 2.2 */
unset($parameters['forceWCF']);
}
$controller = 'Index';
}
else {
- return PageMenu::getInstance()->getLandingPage()->getProcessor()->getLink();
+ return '';// PageMenu::getInstance()->getLandingPage()->getProcessor()->getLink();
}
}
// encode certain characters
if (!empty($url)) {
- $url = str_replace(array('[', ']'), array('%5B', '%5D'), $url);
+ $url = str_replace(['[', ']'], ['%5B', '%5D'], $url);
}
$url = $routeURL . $url;
// handle applications
if (!PACKAGE_ID) {
- $url = RouteHandler::getHost() . RouteHandler::getPath(array('acp')) . ($isACP ? 'acp/' : '') . $url;
+ $url = RouteHandler::getHost() . RouteHandler::getPath(['acp']) . ($isACP ? 'acp/' : '') . $url;
}
else {
if (RequestHandler::getInstance()->inRescueMode()) {
- $pageURL = RouteHandler::getHost() . str_replace('//', '/', RouteHandler::getPath(array('acp')));
+ $pageURL = RouteHandler::getHost() . str_replace('//', '/', RouteHandler::getPath(['acp']));
}
else {
- // try to resolve abbreviation
- $application = null;
- if ($abbreviation != 'wcf') {
- $application = ApplicationHandler::getInstance()->getApplication($abbreviation);
- }
-
- // fallback to primary application if abbreviation is 'wcf' or unknown
- if ($forceWCF) {
- $application = ApplicationHandler::getInstance()->getWCF();
- }
- else if ($application === null) {
- $application = ApplicationHandler::getInstance()->getPrimaryApplication();
- }
-
- $pageURL = $application->getPageURL();
+ $pageURL = ApplicationHandler::getInstance()->getApplication($abbreviation)->getPageURL();
}
$url = $pageURL . ($isACP ? 'acp/' : '') . $url;
* @param integer $pageID page id
* @param integer $languageID language id, optional
* @return string full URL of empty string if `$pageID` is invalid
- * @throws \wcf\system\exception\SystemException
*/
public function getCmsLink($pageID, $languageID = -1) {
// use current language
$this->handleDefaultController($application, $routeData);
// check if accessing from the wrong domain (e.g. "www." omitted but domain was configured with)
- if (!defined('WCF_RUN_MODE') || WCF_RUN_MODE != 'embedded') {
+ if (!defined('WCF_RUN_MODE') || WCF_RUN_MODE !== 'embedded') {
$applicationObject = ApplicationHandler::getInstance()->getApplication($application);
if ($applicationObject->domainName != $_SERVER['HTTP_HOST']) {
// build URL, e.g. http://example.net/forum/
* Checks page access for possible mandatory redirects.
*
* @param string $application
- * @param array $routeData
+ * @param string[] $routeData
*/
protected function handleDefaultController($application, array &$routeData) {
if (!RouteHandler::getInstance()->isDefaultController()) {
return;
}
- $landingPage = PageMenu::getInstance()->getLandingPage();
- if ($landingPage === null) {
- return;
+ $data = ControllerMap::getInstance()->lookupDefaultController($application);
+ if ($data === null) {
+ // handle WCF which does not have a default controller
+ throw new IllegalLinkException();
}
-
- if (empty($routeData['controller'])) $routeData['isImplicitController'] = true;
-
- // resolve implicit application abbreviation for landing page controller
- $landingPageApplication = $landingPage->getApplication();
- $primaryApplication = ApplicationHandler::getInstance()->getPrimaryApplication();
- $primaryApplicationAbbr = ApplicationHandler::getInstance()->getAbbreviation($primaryApplication->packageID);
- if ($landingPageApplication == 'wcf') {
- $landingPageApplication = $primaryApplicationAbbr;
+ else if (!empty($data['redirect'])) {
+ // force a redirect
+ HeaderUtil::redirect($data['redirect'], true);
}
- // check if currently invoked application matches the landing page
- if ($landingPageApplication == $application) {
- $routeData['controller'] = $landingPage->getController();
- $routeData['controller'] = ControllerMap::getInstance()->lookup($application, $routeData['controller']);
-
- return;
+ // copy route data
+ foreach ($data as $key => $value) {
+ $routeData[$key] = $value;
}
-
- // redirect if this is the primary application
- if ($application === $primaryApplicationAbbr) {
- HeaderUtil::redirect($landingPage->getLink());
- exit;
- }
-
- // set default controller
- $applicationObj = WCF::getApplicationObject(ApplicationHandler::getInstance()->getApplication($application));
- $routeData['controller'] = preg_replace('~^.*?\\\([^\\\]+)(?:Action|Form|Page)$~', '\\1', $applicationObj->getPrimaryController());
- $routeData['controller'] = ControllerMap::getInstance()->lookup($application, $routeData['controller']);
}
/**
* Returns the active request object.
*
- * @return \wcf\system\request\Request
+ * @return Request
*/
public function getActiveRequest() {
return $this->activeRequest;
}
// check if this is the default controller of the requested application
+ /*
+ * TODO: what exactly is the check for the primary application doing?
if (!URL_LEGACY_MODE && !$ignoreController && $application !== null) {
if (isset(self::$defaultControllers[$application]) && self::$defaultControllers[$application] == $components['controller']) {
// check if this is the primary application and the landing page originates to the same application
}
}
}
+ */
}
// drops controller from route
*/
protected $pattern = '';
- /**
- * primary application's abbreviation (e.g. "wbb")
- * @var string
- */
- protected $primaryApplication = '';
-
/**
* list of required components
* @var array<string>
}
/**
- * @see IRoute::buildLink()
+ * @inheritDoc
*/
public function buildLink(array $components) {
$application = (isset($components['application'])) ? $components['application'] : null;
// handle default values for controller
$useBuildSchema = true;
if (count($components) == 1 && isset($components['controller'])) {
- $ignoreController = false;
-
- if (!RequestHandler::getInstance()->isACPRequest()) {
- $landingPage = PageMenu::getInstance()->getLandingPage();
- if ($this->primaryApplication === '') {
- $primaryApplication = ApplicationHandler::getInstance()->getPrimaryApplication();
- $this->primaryApplication = ApplicationHandler::getInstance()->getAbbreviation($primaryApplication->packageID);
- }
-
- // check if this is the default controller
- if (strcasecmp(RouteHandler::getInstance()->getDefaultController($application), $components['controller']) === 0) {
- // check if this matches the primary application
- if ($this->primaryApplication === $application) {
- if (strcasecmp($landingPage->getController(), $components['controller']) === 0) {
- // skip controller if it matches the default controller
- $ignoreController = true;
- }
- }
- else {
- // skip default controller
- $ignoreController = true;
- }
- }
- else if (strcasecmp($landingPage->getController(), $components['controller']) === 0) {
- // landing page
- $ignoreController = true;
- }
- }
-
- // drops controller from route
- if ($ignoreController) {
+ if (!RequestHandler::getInstance()->isACPRequest() && ControllerMap::getInstance()->isDefaultController($application, $components['controller'])) {
+ // drops controller from route
$useBuildSchema = false;
// unset the controller, since it would otherwise be added with http_build_query()
* Builds the actual link, the parameter $useBuildSchema can be set to false for
* empty routes, e.g. for the default page.
*
- * @param array $components
+ * @param string[] $components
* @param string $application
* @param boolean $useBuildSchema
* @return string
}
/**
- * @see IRoute::canHandle()
+ * @inheritDoc
*/
public function canHandle(array $components) {
if (!empty($this->requireComponents)) {
}
/**
- * @see IRoute::getRouteData()
+ * @inheritDoc
*/
public function getRouteData() {
return $this->routeData;
}
/**
- * @see IRoute::isACP()
+ * @inheritDoc
*/
public function isACP() {
return $this->isACP;
}
/**
- * @see IRoute::matches()
+ * @inheritDoc
*/
public function matches($requestURL) {
if (preg_match($this->pattern, $requestURL, $matches)) {
*/
class CryptoException extends \Exception {
/**
- * @see \Exception::__construct()
+ * @inheritDoc
*/
- public function __construct($message, $previous) {
+ public function __construct($message, $previous = null) {
parent::__construct($message, 0, $previous);
}
}
<item name="wcf.acp.application.edit"><![CDATA[Anwendung bearbeiten]]></item>
<item name="wcf.acp.application.edit.title"><![CDATA[Anwendung bearbeiten: „<a href="{link controller='Package' id=$application->packageID}{/link}">{$application->getPackage()->getName()}</a>“]]></item>
<item name="wcf.acp.application.list"><![CDATA[Installierte Anwendungen]]></item>
- <item name="wcf.acp.application.primaryApplication"><![CDATA[Primäre Anwendung]]></item>
- <item name="wcf.acp.application.setAsPrimary"><![CDATA[Als primäre Anwendung festlegen]]></item>
- <item name="wcf.acp.application.setAsPrimary.confirmMessage"><![CDATA[Wollen Sie „{$application->getPackage()->getName()}“ wirklich als primäre Anwendung festlegen?]]></item>
</category>
<category name="wcf.acp.attachment">
<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.list"><![CDATA[Installed Applications]]></item>
- <item name="wcf.acp.application.primaryApplication"><![CDATA[Primary Application]]></item>
- <item name="wcf.acp.application.setAsPrimary"><![CDATA[Set As Primary Application]]></item>
- <item name="wcf.acp.application.setAsPrimary.confirmMessage"><![CDATA[Do you really want to set “{$application->getPackage()->getName()}” as the primary application?]]></item>
</category>
<category name="wcf.acp.attachment">
domainPath VARCHAR(255) NOT NULL DEFAULT '/',
cookieDomain VARCHAR(255) NOT NULL,
cookiePath VARCHAR(255) NOT NULL DEFAULT '/',
- isPrimary TINYINT(1) NOT NULL DEFAULT 0
+ landingPageID INT(10) NULL
);
DROP TABLE IF EXISTS wcf1_attachment;
showHeader TINYINT(1) NOT NULL DEFAULT 1,
originIsSystem TINYINT(1) NOT NULL DEFAULT 0,
packageID INT(10) NOT NULL,
- className VARCHAR(255) NOT NULL DEFAULT ''
+ className VARCHAR(255) NOT NULL DEFAULT '',
+ menuID INT(10) NULL
);
DROP TABLE IF EXISTS wcf1_box_content;
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_attachment ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
ALTER TABLE wcf1_attachment ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE SET NULL;
ALTER TABLE wcf1_bbcode_attribute ADD FOREIGN KEY (bbcodeID) REFERENCES wcf1_bbcode (bbcodeID) ON DELETE CASCADE;
ALTER TABLE wcf1_box ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
+ALTER TABLE wcf1_box ADD FOREIGN KEY (menuID) REFERENCES wcf1_menu (menuID) ON DELETE CASCADE;
ALTER TABLE wcf1_box_content ADD FOREIGN KEY (boxID) REFERENCES wcf1_box (boxID) ON DELETE CASCADE;
ALTER TABLE wcf1_box_content ADD FOREIGN KEY (languageID) REFERENCES wcf1_language (languageID) ON DELETE CASCADE;