From: Alexander Ebert Date: Sun, 4 Nov 2012 02:11:37 +0000 (+0100) Subject: Added first draft for application management X-Git-Tag: 2.0.0_Beta_1~821^2~3 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=668cf125c131e6700e77b062f28421463f204083;p=GitHub%2FWoltLab%2FWCF.git Added first draft for application management --- diff --git a/wcfsetup/install/files/acp/templates/applicationGroupAdd.tpl b/wcfsetup/install/files/acp/templates/applicationGroupAdd.tpl new file mode 100644 index 0000000000..873adf73ef --- /dev/null +++ b/wcfsetup/install/files/acp/templates/applicationGroupAdd.tpl @@ -0,0 +1,107 @@ +{include file='header' pageTitle='wcf.acp.application.group.add'} + +
+
+

{lang}wcf.acp.application.group.add{/lang}

+
+
+ +{if $errorField} +

{lang}wcf.global.form.error{/lang}

+{/if} + +{if $success|isset} +

{lang}wcf.global.form.{$action}.success{/lang}

+{/if} + +
+ +
+ +
+
+
+ {lang}wcf.acp.application.group.data{/lang} + +
+
+ + {if $errorField == 'groupName'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {else} + {lang}wcf.acp.application.group.groupName.error.{$errorType}{/lang} + {/if} + + {/if} +
+ +
+ + + {lang}wcf.acp.application.group.availableApplications{/lang} + +
+ + + + + + + + + + + {event name='headColumns'} + + + + + {foreach from=$availableApplications item=application} + + + + + + + + + + {event name='columns'} + + {/foreach} + +
{lang}wcf.global.objectID{/lang}{lang}wcf.acp.package.name{/lang}{lang}wcf.acp.application.domainName{/lang}{lang}wcf.acp.application.domainPath{/lang}{lang}wcf.acp.application.cookieDomain{/lang}{lang}wcf.acp.application.cookiePath{/lang}
{#$application->packageID}{lang}{$application->packageName}{/lang}{$application->domainName}{$application->domainPath}{$application->cookieDomain}{$application->cookiePath}
+
+ + {if $errorField == 'applications'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {else} + {lang}wcf.acp.application.group.applications.error.{$errorType}{/lang} + {/if} + + {/if} + + +
+ +
+ +
+ +
+ +
+ +{include file='footer'} diff --git a/wcfsetup/install/files/acp/templates/applicationManagement.tpl b/wcfsetup/install/files/acp/templates/applicationManagement.tpl new file mode 100644 index 0000000000..01d78b3e7a --- /dev/null +++ b/wcfsetup/install/files/acp/templates/applicationManagement.tpl @@ -0,0 +1,100 @@ +{include file='header' pageTitle='wcf.acp.application.management'} + +{foreach from=$applicationGroups item=applicationGroup} +
+
+

{lang}wcf.acp.application.group.title{/lang} {#$applicationGroup|count}

+
+
+ +
+ + + + + + + + + + + {event name='headColumns'} + + + + + {foreach from=$applicationGroup item=application} + + + + + + + + + + {/foreach} + +
{lang}wcf.global.objectID{/lang}{lang}wcf.acp.package.name{/lang}{lang}wcf.acp.application.domainName{/lang}{lang}wcf.acp.application.domainPath{/lang}{lang}wcf.acp.application.cookieDomain{/lang}{lang}wcf.acp.application.cookiePath{/lang}
{#$application->packageID}{lang}{$application->packageName}{/lang}{$application->domainName}{$application->domainPath}{$application->cookieDomain}{$application->cookiePath}
+
+ +
+ +
+{/foreach} + +{hascontent} +
+
+

{lang}wcf.acp.application.independentApplications{/lang} {#$applications|count}

+
+
+ +
+ + + + + + + + + + + {event name='headColumns'} + + + + + {content} + {foreach from=$applications item=application} + + + + + + + + + + {/foreach} + {/content} + +
{lang}wcf.global.objectID{/lang}{lang}wcf.acp.package.name{/lang}{lang}wcf.acp.application.domainName{/lang}{lang}wcf.acp.application.domainPath{/lang}{lang}wcf.acp.application.cookieDomain{/lang}{lang}wcf.acp.application.cookiePath{/lang}
{#$application->packageID}{lang}{$application->packageName}{/lang}{$application->domainName}{$application->domainPath}{$application->cookieDomain}{$application->cookiePath}
+
+ +
+ +
+{/hascontent} + +{include file='footer'} diff --git a/wcfsetup/install/files/lib/acp/form/ApplicationGroupAddForm.class.php b/wcfsetup/install/files/lib/acp/form/ApplicationGroupAddForm.class.php new file mode 100644 index 0000000000..c24d409a99 --- /dev/null +++ b/wcfsetup/install/files/lib/acp/form/ApplicationGroupAddForm.class.php @@ -0,0 +1,177 @@ + + * @package com.woltlab.wcf + * @subpackage acp.form + * @category Community Framework + */ +class ApplicationGroupAddForm extends ACPForm { + /** + * @see wcf\acp\form\ACPForm::$activeMenuItem + */ + public $activeMenuItem = 'wcf.acp.menu.link.application'; + + /** + * list of application package ids + * @var array + */ + public $applications = array(); + + /** + * list of available applications + * @var array + */ + public $availableApplications = array(); + + /** + * group name + * @var string + */ + public $groupName = ''; + + /** + * @see wcf\page\AbstractPage::$neededPermissions + */ + public $neededPermissions = array('admin.system.canManageApplication'); + + /** + * @see wcf\page\IPage::readParameters() + */ + public function readParameters() { + parent::readParameters(); + + $this->readAvailableApplications(); + } + + /** + * Reads the list of available applications. + */ + protected function readAvailableApplications() { + $applicationList = new ApplicationList(); + $applicationList->sqlSelects = "package.package, package.packageName"; + $applicationList->sqlJoins = "LEFT JOIN wcf".WCF_N."_package package ON (package.packageID = application.packageID)"; + $applicationList->getConditionBuilder()->add("application.groupID IS NULL"); + $applicationList->getConditionBuilder()->add("application.packageID <> ? ", array(1)); + $applicationList->sqlLimit = 0; + $applicationList->readObjects(); + + $this->availableApplications = $applicationList->getObjects(); + } + + /** + * @see wcf\form\IForm::readFormParameters() + */ + public function readFormParameters() { + parent::readFormParameters(); + + if (isset($_POST['applications']) && is_array($_POST['applications'])) $this->applications = ArrayUtil::toIntegerArray($_POST['applications']); + if (isset($_POST['groupName'])) $this->groupName = StringUtil::trim($_POST['groupName']); + } + + /** + * @see wcf\form\IForm::validate() + */ + public function validate() { + parent::validate(); + + // validate group name + if (empty($this->groupName)) { + throw new UserInputException('groupName'); + } + else { + // check for duplicates + $sql = "SELECT COUNT(*) AS count + FROM wcf".WCF_N."_application_group + WHERE groupName = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(array($this->groupName)); + $row = $statement->fetchArray(); + if ($row['count']) { + throw new UserInputException('groupName', 'notUnique'); + } + } + + // validate application package ids + if (empty($this->applications)) { + throw new UserInputException('applications'); + } + else { + $this->applications = array_unique($this->applications); + + // require at least two applications + if (count($this->applications) == 1) { + throw new UserInputException('applications', 'single'); + } + + $packages = array(); + foreach ($this->applications as $packageID) { + // unknown package id + if (!isset($this->availableApplications[$packageID])) { + throw new UserInputException('applications', 'notValid'); + } + + $application = $this->availableApplications[$packageID]; + + // cannot group two or more applications of the same type + if (in_array($application->package, $packages)) { + throw new UserInputException('applications', 'duplicate'); + } + + $packages[] = $application->package; + } + } + } + + /** + * @see wcf\form\IForm::save() + */ + public function save() { + parent::save(); + + // save group + $this->objectAction = new ApplicationGroupAction(array(), 'create', array( + 'applications' => $this->applications, + 'data' => array( + 'groupName' => $this->groupName + ) + )); + $this->objectAction->executeAction(); + $this->saved(); + + // reset values + $this->applications = array(); + $this->groupName = ''; + + // show success. + WCF::getTPL()->assign(array( + 'success' => true + )); + } + + /** + * @see wcf\page\IPage::assignVariables() + */ + public function assignVariables() { + parent::assignVariables(); + + WCF::getTPL()->assign(array( + 'action' => 'add', + 'applications' => $this->applications, + 'availableApplications' => $this->availableApplications, + 'groupName' => $this->groupName + )); + } +} diff --git a/wcfsetup/install/files/lib/acp/page/ApplicationManagementPage.class.php b/wcfsetup/install/files/lib/acp/page/ApplicationManagementPage.class.php new file mode 100644 index 0000000000..a4a40703c7 --- /dev/null +++ b/wcfsetup/install/files/lib/acp/page/ApplicationManagementPage.class.php @@ -0,0 +1,90 @@ + + * @package com.woltlab.wcf + * @subpackage acp.page + * @category Community Framework + */ +class ApplicationManagementPage extends AbstractPage { + /** + * list of ungrouped applications + * @var array + */ + public $applications = null; + + /** + * list of viewable application groups + * @var array + */ + public $applicationGroups = null; + + /** + * number of ungrouped applications + * @var integer + */ + public $ungroupedApplications = 0; + + /** + * @see wcf\page\IPage::readData() + */ + public function readData() { + parent::readData(); + + $applicationList = new ApplicationList(); + $applicationList->sqlSelects = "package.packageName"; + $applicationList->sqlJoins = "LEFT JOIN wcf".WCF_N."_package package ON (package.packageID = application.packageID)"; + $applicationList->getConditionBuilder()->add("application.packageID <> ?", array(1)); // exclude WCF pseudo-application + $applicationList->sqlLimit = 0; + $applicationList->readObjects(); + + $applicationGroupList = new ApplicationGroupList(); + $applicationGroupList->sqlLimit = 0; + $applicationGroupList->readObjects(); + foreach ($applicationGroupList as $applicationGroup) { + $this->applicationGroups[$applicationGroup->groupID] = new ViewableApplicationGroup($applicationGroup); + } + + foreach ($applicationList as $application) { + if (!$application->groupID) { + $this->applications[$application->packageID] = $application; + } + else { + $this->applicationGroups[$application->groupID]->addApplication($application); + } + } + } + + /** + * @see wcf\page\IPage::assignVariables() + */ + public function assignVariables() { + parent::assignVariables(); + + WCF::getTPL()->assign(array( + 'applications' => $this->applications, + 'applicationGroups' => $this->applicationGroups + )); + } + + /** + * @see wcf\page\IPage::show() + */ + public function show() { + // enable menu item + ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.application.management'); + + parent::show(); + } +} diff --git a/wcfsetup/install/files/lib/data/application/ApplicationAction.class.php b/wcfsetup/install/files/lib/data/application/ApplicationAction.class.php index 6292309e6c..2fa25a99a6 100644 --- a/wcfsetup/install/files/lib/data/application/ApplicationAction.class.php +++ b/wcfsetup/install/files/lib/data/application/ApplicationAction.class.php @@ -1,6 +1,8 @@ objects)) { + $this->readObjects(); + } + + $sql = "UPDATE wcf".WCF_N."_application + SET groupID = ?, + cookieDomain = ?, + cookiePath = ? + WHERE packageID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + // calculate cookie path + $domains = array(); + foreach ($this->objects as $application) { + if (!isset($domains[$application->domainName])) { + $domains[$application->domainName] = array(); + } + + $domains[$application->domainName][$application->packageID] = explode('/', FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash($application->domainPath))); + } + + WCF::getDB()->beginTransaction(); + foreach ($domains as $domainName => $data) { + $path = null; + foreach ($data as $domainPath) { + if ($path === null) { + $path = $domainPath; + } + else { + foreach ($path as $i => $part) { + if (!isset($domainPath[$i]) || $domainPath[$i] != $part) { + // remove all following elements including current one + foreach ($path as $j => $innerPart) { + if ($j >= $i) { + unset($path[$j]); + } + } + + // skip to next domain + continue 2; + } + } + } + } + + $path = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash(implode('/', $path))); + + foreach (array_keys($data) as $packageID) { + $statement->execute(array( + $this->parameters['groupID'], + $domainName, + $path, + $packageID + )); + } + } + WCF::getDB()->commitTransaction(); + } + + /** + * Removes a list of applications from their group and resets the cookie domain and path. + */ + public function ungroup() { + if (empty($this->objects)) { + $this->readObjects(); + } + + $sql = "UPDATE wcf".WCF_N."_application + SET groupID = ?, + cookieDomain = domainName, + cookiePath = domainPath + WHERE packageID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + WCF::getDB()->beginTransaction(); + foreach ($this->objects as $application) { + $statement->execute(array( + null, + $application->packageID + )); + } + WCF::getDB()->commitTransaction(); + } } diff --git a/wcfsetup/install/files/lib/data/application/group/ApplicationGroupAction.class.php b/wcfsetup/install/files/lib/data/application/group/ApplicationGroupAction.class.php index 2451e3c23c..dba0c9ba3c 100644 --- a/wcfsetup/install/files/lib/data/application/group/ApplicationGroupAction.class.php +++ b/wcfsetup/install/files/lib/data/application/group/ApplicationGroupAction.class.php @@ -1,5 +1,6 @@ parameters['applications'])) { + $applicationAction = new ApplicationAction($this->parameters['applications'], 'group', array('groupID' => $applicationGroup->groupID)); + $applicationAction->executeAction(); + } + + return $applicationGroup; + } } diff --git a/wcfsetup/install/files/lib/data/application/group/ViewableApplicationGroup.class.php b/wcfsetup/install/files/lib/data/application/group/ViewableApplicationGroup.class.php new file mode 100644 index 0000000000..d7b7a79d27 --- /dev/null +++ b/wcfsetup/install/files/lib/data/application/group/ViewableApplicationGroup.class.php @@ -0,0 +1,86 @@ + + * @package com.woltlab.wcf + * @subpackage data.application.group + * @category Community Framework + */ +class ViewableApplicationGroup extends DatabaseObjectDecorator implements \Countable, \Iterator { + /** + * @see wcf\data\DatabaseObjectDecorator::$baseClass + */ + protected static $baseClass = 'wcf\data\application\group\ApplicationGroup'; + + /** + * list of applications + * @var array + */ + protected $applications = array(); + + /** + * current iterator index + * @var integer + */ + protected $index = 0; + + /** + * Assigns an application to this group. + * + * @param wcf\data\application\Application $application + */ + public function addApplication(Application $application) { + if ($this->groupID == $application->groupID) { + $this->applications[] = $application; + } + } + + /** + * @see \Countable::count() + */ + public function count() { + return count($this->applications); + } + + /** + * @see \Iterator::current() + */ + public function current() { + return $this->applications[$this->index]; + } + + /** + * @see \Iterator::key() + */ + public function key() { + return $this->applications[$this->index]; + } + + /** + * @see \Iterator::next() + */ + public function next() { + ++$this->index; + } + + /** + * @see \Iterator::rewind() + */ + public function rewind() { + $this->index = 0; + } + + /** + * @see \Iterator::valid() + */ + public function valid() { + return isset($this->applications[$this->index]); + } +} diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 90764aac82..5bb1ba2720 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -4,6 +4,26 @@ + + + + + + + + + + + + + + + + groupName}“]]> + + + + @@ -139,9 +159,9 @@ - + - + diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index 259a24a0ac..ff153f5094 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -80,6 +80,8 @@ CREATE TABLE wcf1_application ( packageID INT(10) NOT NULL PRIMARY KEY, domainName VARCHAR(255) NOT NULL, domainPath VARCHAR(255) NOT NULL DEFAULT '/', + cookieDomain VARCHAR(255) NOT NULL, + cookieDomainPath VARCHAR(255) NOT NULL DEFAULT '/', groupID INT(10), isPrimary TINYINT(1) NOT NULL DEFAULT 0 );