From: Matthias Schmidt Date: Sat, 24 May 2014 09:45:07 +0000 (+0200) Subject: Add notice implementation X-Git-Tag: 2.1.0_Alpha_1~798^2~5 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=20933e614b60957902d6726e41c90ab625f2b9e0;p=GitHub%2FWoltLab%2FWCF.git Add notice implementation --- diff --git a/com.woltlab.wcf/acpMenu.xml b/com.woltlab.wcf/acpMenu.xml index ff2be66be1..0c304a2093 100644 --- a/com.woltlab.wcf/acpMenu.xml +++ b/com.woltlab.wcf/acpMenu.xml @@ -493,6 +493,21 @@ admin.attachment.canManageAttachment + + wcf.acp.menu.link.content + 6 + + + + wcf.acp.menu.link.notice + admin.content.tag.canManageTag + + + + wcf.acp.menu.link.notice + admin.content.notice.canManageNotice + + 5 diff --git a/com.woltlab.wcf/coreObject.xml b/com.woltlab.wcf/coreObject.xml index c5e4c53cae..d02ca2b9c2 100644 --- a/com.woltlab.wcf/coreObject.xml +++ b/com.woltlab.wcf/coreObject.xml @@ -49,5 +49,9 @@ + + + + diff --git a/com.woltlab.wcf/objectType.xml b/com.woltlab.wcf/objectType.xml index 30ff78e09c..8597bdb9d2 100644 --- a/com.woltlab.wcf/objectType.xml +++ b/com.woltlab.wcf/objectType.xml @@ -594,5 +594,97 @@ + + + + com.woltlab.wcf.page.controller + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.page + + + + com.woltlab.wcf.user.username + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + + + com.woltlab.wcf.user.email + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + + + com.woltlab.wcf.user.userGroup + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + 1 + + + com.woltlab.wcf.user.languages + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + + + com.woltlab.wcf.user.registrationDate + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + + + com.woltlab.wcf.user.registrationDateInterval + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + + + com.woltlab.wcf.user.avatar + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + + + com.woltlab.wcf.user.state + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + general + + + com.woltlab.wcf.user.activityPoints + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + contents + activityPoints + 0 + + + com.woltlab.wcf.user.likesReceived + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + contents + likesReceived + 0 + + + com.woltlab.wcf.user.userOptions + com.woltlab.wcf.condition.notice + + com.woltlab.wcf.user + userOptions + + diff --git a/com.woltlab.wcf/objectTypeDefinition.xml b/com.woltlab.wcf/objectTypeDefinition.xml index 1366360596..e7793e3268 100644 --- a/com.woltlab.wcf/objectTypeDefinition.xml +++ b/com.woltlab.wcf/objectTypeDefinition.xml @@ -157,5 +157,10 @@ com.woltlab.wcf.page + + + com.woltlab.wcf.condition.notice + + diff --git a/com.woltlab.wcf/templates/headInclude.tpl b/com.woltlab.wcf/templates/headInclude.tpl index ee5e4ba692..ef500d988d 100644 --- a/com.woltlab.wcf/templates/headInclude.tpl +++ b/com.woltlab.wcf/templates/headInclude.tpl @@ -175,6 +175,7 @@ WCF.Date.Picker.init(); new WCF.User.ProfilePreview(); WCF.System.FlexibleMenu.init(); + new WCF.Notice.Dismiss(); {event name='javascriptInit'} diff --git a/com.woltlab.wcf/templates/userNotice.tpl b/com.woltlab.wcf/templates/userNotice.tpl index 8e0b6d20fe..a4ba26f6a9 100644 --- a/com.woltlab.wcf/templates/userNotice.tpl +++ b/com.woltlab.wcf/templates/userNotice.tpl @@ -18,5 +18,16 @@

{lang}wcf.user.register.needActivation{/lang}

{/if} + {* todo: styling/visual appearence *} + {foreach from=$__wcf->getNoticeHandler()->getVisibleNotices() item='notice'} +

+ {if $notice->isDismissible} + + {/if} + + {if $notice->noticeUseHtml}{@$notice->notice|language}{else}{$notice->notice|language}{/if} +

+ {/foreach} + {event name='userNotice'} - \ No newline at end of file + diff --git a/com.woltlab.wcf/userGroupOption.xml b/com.woltlab.wcf/userGroupOption.xml index 6c107425e2..b682efa5d1 100644 --- a/com.woltlab.wcf/userGroupOption.xml +++ b/com.woltlab.wcf/userGroupOption.xml @@ -100,6 +100,9 @@ admin.content + + admin.content + admin @@ -627,6 +630,13 @@ png]]> 0 1 + + diff --git a/wcfsetup/install/files/acp/templates/noticeAdd.tpl b/wcfsetup/install/files/acp/templates/noticeAdd.tpl new file mode 100644 index 0000000000..7b735be3f2 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/noticeAdd.tpl @@ -0,0 +1,146 @@ +{include file='header' pageTitle='wcf.acp.notice.'|concat:$action} + + + +
+

{lang}wcf.acp.notice.{$action}{/lang}

+
+ +{include file='formError'} + +{if $success|isset} +

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

+{/if} + +
+ +
+ +
+
+
+ {lang}wcf.global.form.data{/lang} + + +
+
+ + {if $errorField == 'noticeName'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {else} + {lang}wcf.acp.notice.noticeName.error.{$errorType}{/lang} + {/if} + + {/if} +
+ + + +
+
+ + {if $errorField == 'notice'} + + {if $errorType == 'empty'} + {lang}wcf.global.form.error.empty{/lang} + {elseif $errorType == 'multilingual'} + {lang}wcf.global.form.error.multilingual{/lang} + {else} + {lang}wcf.acp.notice.notice.error.{$errorType}{/lang} + {/if} + + {/if} +
+ + {include file='multipleLanguageInputJavascript' elementIdentifier='notice' forceSelection=false} + +
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+
+ + {lang}wcf.acp.notice.showOrder.description{/lang} +
+
+ +
+
+
+ + {lang}wcf.acp.notice.isDismissible.description{/lang} +
+
+ + {if $action == 'edit' && $notice->isDismissible} +
+
+
+ + {lang}wcf.acp.notice.resetIsDismissed.description{/lang} +
+
+ {/if} + + {event name='dataFields'} +
+ + {event name='fieldsets'} +
+ +
+

{lang}wcf.acp.notice.conditions{/lang}

+ {lang}wcf.acp.notice.conditions.description{/lang} +
+ +
+
+ {lang}wcf.acp.notice.conditions.page{/lang} + {lang}wcf.acp.notice.conditions.page.description{/lang} + + {foreach from=$groupedConditionObjectTypes['com.woltlab.wcf.page'] item='pageConditionObjectType'} + {@$pageConditionObjectType->getProcessor()->getHtml()} + {/foreach} +
+
+ +
+

{lang}wcf.acp.notice.conditions.user{/lang}

+ {lang}wcf.acp.notice.conditions.user.description{/lang} +
+ + {include file='userConditions' groupedObjectTypes=$groupedConditionObjectTypes['com.woltlab.wcf.user']} + +
+ + {@SECURITY_TOKEN_INPUT_TAG} +
+
+ +{include file='footer'} diff --git a/wcfsetup/install/files/acp/templates/noticeList.tpl b/wcfsetup/install/files/acp/templates/noticeList.tpl new file mode 100644 index 0000000000..60bcb6af56 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/noticeList.tpl @@ -0,0 +1,69 @@ +{include file='header' pageTitle='wcf.acp.notice.list'} + + + +
+

{lang}wcf.acp.notice.list{/lang}

+
+ +
+ {pages print=true assign=pagesLinks controller="NoticeList" link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"} + + +
+ +{if $objects|count} +
+
    + {foreach from=$objects item='notice'} +
  1. + + {$notice->noticeName} + + + + + + + {event name='itemButtons'} + + +
  2. + {/foreach} +
+ +
+ +
+
+ +
+ {@$pagesLinks} + + +
+{else} +

{lang}wcf.global.noItems{/lang}

+{/if} + +{include file='footer'} diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 5a107aaca8..d73ba015bf 100755 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -10754,6 +10754,136 @@ WCF.Category.NestedList = Class.extend({ } }); +/** + * Initializes WCF.Condition namespace. + */ +WCF.Condition = { }; + +/** + * Handles displaying the a form element whose visibility depends on the selected + * page controllers. + */ +WCF.Condition.PageControllerDependence = Class.extend({ + /** + * select list with the available page controllers + * @var jQuery + */ + _pageControllerSelection: null, + + /** + * ids of page object types that support the form element + * @var array + */ + _supportedPageObjectTypeIDs: [], + + /** + * Initializes a new WCF.Condition.PageControllerDependence object. + * + * @param string inputIdentifier + * @param array supportedPageObjectTypeIDs + */ + init: function(inputIdentifier, supportedPageObjectTypeIDs) { + this._supportedPageObjectTypeIDs = supportedPageObjectTypeIDs; + + this._pageControllerSelection = $('#pageControllers').change($.proxy(this._checkVisibility, this)); + this._pageControllerContainer = this._pageControllerSelection.parents('dl:eq(0)'); + + this._input = $('#' + inputIdentifier); + this._inputContainer = this._input.parents('dl:eq(0)'); + + this._checkVisibility(); + }, + + /** + * Checks the visibility based on the selected page controllers. + */ + _checkVisibility: function() { + var $selectedPageIDs = this._pageControllerSelection.val() || [ ]; + + var $display = true; + if ($selectedPageIDs.length) { + for (var $i = 0, $length = $selectedPageIDs.length; $i < $length; $i++) { + if (this._supportedPageObjectTypeIDs.indexOf(parseInt($selectedPageIDs[$i])) == -1) { + $display = false; + break; + } + } + } + else { + $display = false; + } + + if ($display) { + this._inputContainer.show(); + this._input.enable(); + } + else { + this._inputContainer.hide(); + this._input.disable(); + } + } +}); + +/** + * Initialize WCF.Notice namespace. + */ +WCF.Notice = { }; + +/** + * Handles dismissing notices. + */ +WCF.Notice.Dismiss = Class.extend({ + /** + * list with notices + * @var jQuery + */ + _notices: { }, + + /** + * action proxy object + * @var WCF.Action.Proxy + */ + _proxy: null, + + /** + * Initializes a new WCF.Notice.Dismiss object. + */ + init: function() { + this._proxy = new WCF.Action.Proxy({ + success: $.proxy(this._success, this) + }); + + var $dismissButtons = $('.jsDismissNoticeButton').click($.proxy(this._click, this)); + + $dismissButtons.each($.proxy(function(index, element) { + this._notices[$(element).data('objectID')] = $(element).parent(); + }, this)); + }, + + /** + * Handles clicking on + */ + _click: function(event) { + this._proxy.setOption('data', { + actionName: 'dismiss', + className: 'wcf\\data\\notice\\NoticeAction', + objectIDs: [ $(event.currentTarget).data('objectID') ] + }); + this._proxy.sendRequest(); + }, + + /** + * Handles successfull AJAX request. + * + * @param object data + * @param string textStatus + * @param jQuery jqXHR + */ + _success: function(data, textStatus, jqXHR) { + this._notices[data.returnValues.noticeID].wcfFadeOut(); + } +}); + /** * Encapsulate eval() within an own function to prevent problems * with optimizing and minifiny JS. diff --git a/wcfsetup/install/files/lib/acp/form/NoticeAddForm.class.php b/wcfsetup/install/files/lib/acp/form/NoticeAddForm.class.php new file mode 100644 index 0000000000..f394ec3d94 --- /dev/null +++ b/wcfsetup/install/files/lib/acp/form/NoticeAddForm.class.php @@ -0,0 +1,245 @@ + + * @package com.woltlab.wcf + * @subpackage acp.form + * @category Community Framework + */ +class NoticeAddForm extends AbstractForm { + /** + * @see \wcf\page\AbstractPage::$activeMenuItem + */ + public $activeMenuItem = 'wcf.acp.menu.link.notice.add'; + + /** + * grouped notice condition object types + * @var array + */ + public $groupedConditionObjectTypes = array(); + + /** + * 1 if the notice is disabled + * @var integer + */ + public $isDisabled = 0; + + /** + * 1 if the notice is dismissible + * @var integer + */ + public $isDismissible = 0; + + /** + * @see \wcf\page\AbstractPage::$neededPermissions + */ + public $neededPermissions = array('admin.content.notice.canManageNotice'); + + /** + * name of the notice + * @var string + */ + public $noticeName = ''; + + /** + * 1 if html is used in the notice text + * @var integer + */ + public $noticeUseHtml = 0; + + /** + * order used to the show the notices + * @var integer + */ + public $showOrder = 0; + + /** + * @see \wcf\page\IPage::assignVariables() + */ + public function assignVariables() { + parent::assignVariables(); + + I18nHandler::getInstance()->assignVariables(); + + WCF::getTPL()->assign(array( + 'action' => 'add', + 'isDisabled' => $this->isDisabled, + 'isDismissible' => $this->isDismissible, + 'groupedConditionObjectTypes' => $this->groupedConditionObjectTypes, + 'noticeName' => $this->noticeName, + 'noticeUseHtml' => $this->noticeUseHtml, + 'showOrder' => $this->showOrder + )); + } + + /** + * @see \wcf\page\IPage::readData() + */ + public function readData() { + $objectTypes = ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.condition.notice'); + foreach ($objectTypes as $objectType) { + if (!$objectType->conditionobject) continue; + + if (!isset($this->groupedConditionObjectTypes[$objectType->conditionobject])) { + $this->groupedConditionObjectTypes[$objectType->conditionobject] = array(); + } + + if ($objectType->conditiongroup) { + if (!isset($this->groupedConditionObjectTypes[$objectType->conditionobject][$objectType->conditiongroup])) { + $this->groupedConditionObjectTypes[$objectType->conditionobject][$objectType->conditiongroup] = array(); + } + + $this->groupedConditionObjectTypes[$objectType->conditionobject][$objectType->conditiongroup][$objectType->objectTypeID] = $objectType; + } + else { + $this->groupedConditionObjectTypes[$objectType->conditionobject][$objectType->objectTypeID] = $objectType; + } + } + + parent::readData(); + } + + /** + * @see \wcf\form\IForm::readFormParameters() + */ + public function readFormParameters() { + parent::readFormParameters(); + + I18nHandler::getInstance()->readValues(); + + if (isset($_POST['isDisabled'])) $this->isDisabled = 1; + if (isset($_POST['isDismissible'])) $this->isDismissible = 1; + if (isset($_POST['noticeName'])) $this->noticeName = StringUtil::trim($_POST['noticeName']); + if (isset($_POST['noticeUseHtml'])) $this->noticeUseHtml = 1; + if (isset($_POST['showOrder'])) $this->showOrder = intval($_POST['showOrder']); + + foreach ($this->groupedConditionObjectTypes as $groupedObjectTypes) { + foreach ($groupedObjectTypes as $objectTypes) { + if (is_array($objectTypes)) { + foreach ($objectTypes as $objectType) { + $objectType->getProcessor()->readFormParameters(); + } + } + else { + $objectTypes->getProcessor()->readFormParameters(); + } + } + } + } + + /** + * @see \wcf\page\IPage::readParameters() + */ + public function readParameters() { + parent::readParameters(); + + I18nHandler::getInstance()->register('notice'); + } + + /** + * @see \wcf\form\IForm::save() + */ + public function save() { + parent::save(); + + $this->objectAction = new NoticeAction(array(), 'create', array( + 'data' => array( + 'isDisabled' => $this->isDisabled, + 'isDismissible' => $this->isDismissible, + 'notice' => I18nHandler::getInstance()->isPlainValue('notice') ? I18nHandler::getInstance()->getValue('notice') : '', + 'noticeName' => $this->noticeName, + 'noticeUseHtml' => $this->noticeUseHtml, + 'showOrder' => $this->showOrder + ) + )); + $returnValues = $this->objectAction->executeAction(); + + if (!I18nHandler::getInstance()->isPlainValue('notice')) { + I18nHandler::getInstance()->save('notice', 'wcf.notice.notice.notice'.$returnValues['returnValues']->noticeID, 'wcf.notice', 1); + + // update notice name + $noticeEditor = new NoticeEditor($returnValues['returnValues']); + $noticeEditor->update(array( + 'notice' => 'wcf.notice.notice.notice'.$returnValues['returnValues']->noticeID + )); + } + + // transform conditions array into one-dimensional array + $conditions = array(); + foreach ($this->groupedConditionObjectTypes as $groupedObjectTypes) { + foreach ($groupedObjectTypes as $objectTypes) { + if (is_array($objectTypes)) { + $conditions = array_merge($conditions, $objectTypes); + } + else { + $conditions[] = $objectTypes; + } + } + } + + ConditionHandler::getInstance()->createConditions($returnValues['returnValues']->noticeID, $conditions); + + $this->saved(); + + // reset values + $this->isDisabled = 0; + $this->isDismissible = 0; + $this->noticeName = ''; + $this->noticeUseHtml = 0; + $this->showOrder = 0; + I18nHandler::getInstance()->reset(); + + foreach ($conditions as $condition) { + $condition->getProcessor()->reset(); + } + + WCF::getTPL()->assign('success', true); + } + + /** + * @see \wcf\form\IForm::validate() + */ + public function validate() { + parent::validate(); + + if (empty($this->noticeName)) { + throw new UserInputException('noticeName'); + } + + if (!I18nHandler::getInstance()->validateValue('notice')) { + if (I18nHandler::getInstance()->isPlainValue('notice')) { + throw new UserInputException('notice'); + } + else { + throw new UserInputException('notice', 'multilingual'); + } + } + + foreach ($this->groupedConditionObjectTypes as $groupedObjectTypes) { + foreach ($groupedObjectTypes as $objectTypes) { + if (is_array($objectTypes)) { + foreach ($objectTypes as $objectType) { + $objectType->getProcessor()->validate(); + } + } + else { + $objectTypes->getProcessor()->validate(); + } + } + } + } +} diff --git a/wcfsetup/install/files/lib/acp/form/NoticeEditForm.class.php b/wcfsetup/install/files/lib/acp/form/NoticeEditForm.class.php new file mode 100644 index 0000000000..6fd4a18254 --- /dev/null +++ b/wcfsetup/install/files/lib/acp/form/NoticeEditForm.class.php @@ -0,0 +1,184 @@ + + * @package com.woltlab.wcf + * @subpackage acp.form + * @category Community Framework + */ +class NoticeEditForm extends NoticeAddForm { + /** + * @see \wcf\page\AbstractPage::$activeMenuItem + */ + public $activeMenuItem = 'wcf.acp.menu.link.notice'; + + /** + * edited notice object + * @var \wcf\data\notice\Notice + */ + public $notice = null; + + /** + * id of the edited notice object + * @var integer + */ + public $noticeID = 0; + + /** + * 1 if the notice will be displayed for all users again + * @var unknown + */ + public $resetIsDismissed = 0; + + /** + * @see \wcf\page\IPage::assignVariables() + */ + public function assignVariables() { + parent::assignVariables(); + + I18nHandler::getInstance()->assignVariables(!empty($_POST)); + + WCF::getTPL()->assign(array( + 'action' => 'edit', + 'notice' => $this->notice, + 'resetIsDismissed' => $this->resetIsDismissed + )); + } + + /** + * @see \wcf\page\IPage::readData() + */ + public function readData() { + parent::readData(); + + if (empty($_POST)) { + I18nHandler::getInstance()->setOptions('notice', 1, $this->notice->notice, 'wcf.notice.notice.notice\d+'); + + $this->isDisabled = $this->notice->isDisabled; + $this->isDismissible = $this->notice->isDismissible; + $this->noticeName = $this->notice->noticeName; + $this->noticeUseHtml = $this->notice->noticeUseHtml; + $this->showOrder = $this->notice->showOrder; + + $conditions = $this->notice->getConditions(); + $conditionsByObjectTypeID = array(); + foreach ($conditions as $condition) { + $conditionsByObjectTypeID[$condition->objectTypeID] = $condition; + } + + foreach ($this->groupedConditionObjectTypes as $objectTypes1) { + foreach ($objectTypes1 as $objectTypes2) { + if (is_array($objectTypes2)) { + foreach ($objectTypes2 as $objectType) { + if (isset($conditionsByObjectTypeID[$objectType->objectTypeID])) { + $conditionsByObjectTypeID[$objectType->objectTypeID]->getObjectType()->getProcessor()->setData($conditionsByObjectTypeID[$objectType->objectTypeID]); + } + } + } + else if (isset($conditionsByObjectTypeID[$objectTypes2->objectTypeID])) { + $conditionsByObjectTypeID[$objectTypes2->objectTypeID]->getObjectType()->getProcessor()->setData($conditionsByObjectTypeID[$objectTypes2->objectTypeID]); + } + } + } + } + } + + /** + * @see \wcf\form\IForm::readFormParameters() + */ + public function readFormParameters() { + parent::readFormParameters(); + + if (isset($_POST['resetIsDismissed'])) $this->resetIsDismissed = 1; + } + + /** + * @see \wcf\page\IPage::readParameters() + */ + public function readParameters() { + parent::readParameters(); + + if (isset($_REQUEST['id'])) $this->noticeID = intval($_REQUEST['id']); + $this->notice = new Notice($this->noticeID); + if (!$this->notice->noticeID) { + throw new IllegalLinkException(); + } + } + + /** + * @see \wcf\form\IForm::save() + */ + public function save() { + AbstractForm::save(); + + $this->objectAction = new NoticeAction(array($this->notice), 'update', array( + 'data' => array( + 'isDisabled' => $this->isDisabled, + 'isDismissible' => $this->isDismissible, + 'notice' => I18nHandler::getInstance()->isPlainValue('notice') ? I18nHandler::getInstance()->getValue('notice') : 'wcf.notice.notice.notice'.$this->notice->noticeID, + 'noticeName' => $this->noticeName, + 'noticeUseHtml' => $this->noticeUseHtml, + 'showOrder' => $this->showOrder + ) + )); + $this->objectAction->executeAction(); + + if (I18nHandler::getInstance()->isPlainValue('notice')) { + if ($this->notice->notice == 'wcf.notice.notice.notice'.$this->notice->noticeID) { + I18nHandler::getInstance()->remove($this->notice->notice); + } + } + else { + I18nHandler::getInstance()->save('notice', 'wcf.notice.notice.notice'.$this->notice->noticeID, 'wcf.notice', 1); + } + + // transform conditions array into one-dimensional array + $conditions = array(); + foreach ($this->groupedConditionObjectTypes as $groupedObjectTypes) { + foreach ($groupedObjectTypes as $objectTypes) { + if (is_array($objectTypes)) { + $conditions = array_merge($conditions, $objectTypes); + } + else { + $conditions[] = $objectTypes; + } + } + } + + ConditionHandler::getInstance()->updateConditions($this->notice->noticeID, $this->notice->getConditions(), $conditions); + + if ($this->resetIsDismissed) { + $sql = "DELETE FROM wcf".WCF_N."_notice_dismissed + WHERE noticeID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(array( + $this->notice->noticeID + )); + + $this->resetIsDismissed = 0; + + UserStorageHandler::getInstance()->resetAll('dismissedNotices'); + } + + $this->saved(); + + // reload notice object for proper 'isDismissible' value + $this->notice = new Notice($this->noticeID); + + WCF::getTPL()->assign('success', true); + } +} diff --git a/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentAddForm.class.php b/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentAddForm.class.php index 6897fda914..45eeed64aa 100644 --- a/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentAddForm.class.php @@ -128,7 +128,13 @@ class UserGroupAssignmentAddForm extends AbstractForm { )); $returnValues = $this->objectAction->executeAction(); - ConditionHandler::getInstance()->createConditions($returnValues['returnValues']->assignmentID, $this->conditions); + // transform conditions array into one-dimensional array + $conditions = array(); + foreach ($this->conditions as $groupedObjectTypes) { + $conditions = array_merge($conditions, $groupedObjectTypes); + } + + ConditionHandler::getInstance()->createConditions($returnValues['returnValues']->assignmentID, $conditions); $this->saved(); diff --git a/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentEditForm.class.php b/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentEditForm.class.php index 9e5fa51675..939ef6a82c 100644 --- a/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/UserGroupAssignmentEditForm.class.php @@ -87,7 +87,13 @@ class UserGroupAssignmentEditForm extends UserGroupAssignmentAddForm { )); $returnValues = $this->objectAction->executeAction(); - ConditionHandler::getInstance()->updateConditions($this->assignment->assignmentID, $this->assignment->getConditions(), $this->conditions); + // transform conditions array into one-dimensional array + $conditions = array(); + foreach ($this->conditions as $groupedObjectTypes) { + $conditions = array_merge($conditions, $groupedObjectTypes); + } + + ConditionHandler::getInstance()->updateConditions($this->assignment->assignmentID, $this->assignment->getConditions(), $conditions); $this->saved(); diff --git a/wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php b/wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php new file mode 100644 index 0000000000..11dde8b71a --- /dev/null +++ b/wcfsetup/install/files/lib/acp/page/NoticeListPage.class.php @@ -0,0 +1,40 @@ + + * @package com.woltlab.wcf + * @subpackage acp.page + * @category Community Framework + */ +class NoticeListPage extends SortablePage { + /** + * @see \wcf\page\AbstractPage::$activeMenuItem + */ + public $activeMenuItem = 'wcf.acp.menu.link.notice.list'; + + /** + * @see \wcf\page\SortablePage::$defaultSortField + */ + public $defaultSortField = 'showOrder'; + + /** + * @see \wcf\page\AbstractPage::$neededPermissions + */ + public $neededPermissions = array('admin.content.notice.canManageNotice'); + + /** + * @see \wcf\page\MultipleLinkPage::$objectListClassName + */ + public $objectListClassName = 'wcf\data\notice\NoticeList'; + + /** + * @see \wcf\page\SortablePage::$objectListClassName + */ + public $validSortFields = array('noticeID', 'noticeName', 'showOrder'); +} diff --git a/wcfsetup/install/files/lib/data/notice/Notice.class.php b/wcfsetup/install/files/lib/data/notice/Notice.class.php new file mode 100644 index 0000000000..8e4f7cf6ad --- /dev/null +++ b/wcfsetup/install/files/lib/data/notice/Notice.class.php @@ -0,0 +1,103 @@ + + * @package com.woltlab.wcf + * @subpackage data.notice + * @category Community Framework + */ +class Notice extends DatabaseObject implements IRouteController { + /** + * true if the active user has dismissed the notice + * @var boolean + */ + protected $isDismissed = null; + + /** + * @see \wcf\data\DatabaseObject::$databaseTableName + */ + protected static $databaseTableName = 'notice'; + + /** + * @see \wcf\data\DatabaseObject::$databaseIndexName + */ + protected static $databaseTableIndexName = 'noticeID'; + + /** + * Returns the conditions of the notice. + * + * @return array<\wcf\data\condition\Condition> + */ + public function getConditions() { + return ConditionHandler::getInstance()->getConditions('com.woltlab.wcf.condition.notice', $this->noticeID); + } + + /** + * @see \wcf\data\ITitledObject::getTitle() + */ + public function getTitle() { + return $this->noticeName; + } + + /** + * Returns true if the active user has dismissed the notice. + * + * @return boolean + */ + public function isDismissed() { + if (!$this->isDismissible) return false; + + if ($this->isDismissed === null) { + if (WCF::getUser()->userID) { + UserStorageHandler::getInstance()->loadStorage(array(WCF::getUser()->userID)); + $dismissedNotices = UserStorageHandler::getInstance()->getStorage(array(WCF::getUser()->userID), 'dismissedNotices'); + if ($dismissedNotices[WCF::getUser()->userID] === null) { + $sql = "SELECT noticeID + FROM wcf".WCF_N."_notice_dismissed + WHERE userID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(array( + WCF::getUser()->userID + )); + + $noticeIDs = array(); + while ($noticeID = $statement->fetchColumn()) { + $noticeIDs[] = $noticeID; + + if ($noticeID == $this->noticeID) { + $this->isDismissed = true; + } + } + + UserStorageHandler::getInstance()->update(WCF::getUser()->userID, 'dismissedNotices', serialize($noticeIDs)); + } + else { + $dismissedNoticeIDs = @unserialize($dismissedNotices[WCF::getUser()->userID]); + $this->isDismissed = isset($dismissedNoticeIDs[$this->noticeID]); + } + } + else { + $dismissedNotices = WCF::getSession()->getVar('dismissedNotices'); + if ($dismissedNotices !== null) { + $dismissedNotices = @unserialize($dismissedNotices); + $this->isDismissed = in_array($this->noticeID, $dismissedNotices); + } + else { + $this->isDismissed = false; + } + } + } + + return $this->isDismissed; + } +} diff --git a/wcfsetup/install/files/lib/data/notice/NoticeAction.class.php b/wcfsetup/install/files/lib/data/notice/NoticeAction.class.php new file mode 100644 index 0000000000..21a2ac19cb --- /dev/null +++ b/wcfsetup/install/files/lib/data/notice/NoticeAction.class.php @@ -0,0 +1,170 @@ + + * @package com.woltlab.wcf + * @subpackage data.notice + * @category Community Framework + */ +class NoticeAction extends AbstractDatabaseObjectAction implements ISortableAction, IToggleAction { + /** + * @see \wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess + */ + protected $allowGuestAccess = array('dismiss'); + + /** + * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsDelete + */ + protected $permissionsDelete = array('admin.content.notice.canManageNotice'); + + /** + * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsUpdate + */ + protected $permissionsUpdate = array('admin.content.notice.canManageNotice'); + + /** + * @see \wcf\data\AbstractDatabaseObjectAction::$requireACP + */ + protected $requireACP = array('create', 'delete', 'toggle', 'update', 'updatePosition'); + + /** + * @see \wcf\data\AbstractDatabaseObjectAction::create() + */ + public function create() { + $showOrder = 0; + if (isset($this->parameters['data']['showOrder'])) { + $showOrder = $this->parameters['data']['showOrder']; + unset($this->parameters['data']['showOrder']); + } + + $notice = parent::create(); + $noticeEditor = new NoticeEditor($notice); + $noticeEditor->setShowOrder($showOrder); + + return new Notice($notice->noticeID); + } + + /** + * Dismisses a certain notice. + * + * @return array + */ + public function dismiss() { + if (WCF::getUser()->userID) { + $sql = "INSERT INTO wcf".WCF_N."_notice_dismissed + (noticeID, userID) + VALUES (?, ?)"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(array( + reset($this->objectIDs), + WCF::getUser()->userID + )); + + UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'dismissedNotices'); + } + else { + $dismissedNotices = WCF::getSession()->getVar('dismissedNotices'); + if ($dismissedNotices !== null) { + $dismissedNotices = @unserialize($dismissedNotices); + $dismissedNotices[] = reset($this->objectIDs); + } + else { + $dismissedNotices = array( + reset($this->objectIDs) + ); + } + + WCF::getSession()->register('dismissedNotices', serialize($dismissedNotices)); + } + + return array( + 'noticeID' => reset($this->objectIDs) + ); + } + + /** + * @see \wcf\data\IToggleAction::toggle() + */ + public function toggle() { + foreach ($this->objects as $notice) { + $notice->update(array( + 'isDisabled' => $notice->isDisabled ? 0 : 1 + )); + } + } + + /** + * Validates the 'dismiss' action. + */ + public function validateDismiss() { + $this->getSingleObject(); + } + + /** + * @see \wcf\data\IToggleAction::validateToggle() + */ + public function validateToggle() { + parent::validateUpdate(); + } + + /** + * @see \wcf\data\ISortableAction::validateUpdatePosition() + */ + public function validateUpdatePosition() { + WCF::getSession()->checkPermissions($this->permissionsUpdate); + + if (!isset($this->parameters['data']['structure']) || !is_array($this->parameters['data']['structure'])) { + throw new UserInputException('structure'); + } + + $noticeList = new NoticeList(); + $noticeList->getConditionBuilder()->add('notice.noticeID IN (?)', array($this->parameters['data']['structure'][0])); + if ($noticeList->countObjects() != count($this->parameters['data']['structure'][0])) { + throw new UserInputException('structure'); + } + + $this->readInteger('offset', true, 'data'); + } + + /** + * @see \wcf\data\AbstractDatabaseObjectAction::update() + */ + public function update() { + parent::update(); + + if (count($this->objects) == 1 && isset($this->parameters['data']['showOrder']) && $this->parameters['data']['showOrder'] != reset($this->objects)->showOrder) { + reset($this->objects)->setShowOrder($this->parameters['data']['showOrder']); + } + } + + /** + * @see \wcf\data\ISortableAction::updatePosition() + */ + public function updatePosition() { + $sql = "UPDATE wcf".WCF_N."_notice + SET showOrder = ? + WHERE noticeID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + $showOrder = $this->parameters['data']['offset']; + WCF::getDB()->beginTransaction(); + foreach ($this->parameters['data']['structure'][0] as $noticeID) { + $statement->execute(array( + $showOrder++, + $noticeID + )); + } + WCF::getDB()->commitTransaction(); + } +} diff --git a/wcfsetup/install/files/lib/data/notice/NoticeEditor.class.php b/wcfsetup/install/files/lib/data/notice/NoticeEditor.class.php new file mode 100644 index 0000000000..1c3944fff8 --- /dev/null +++ b/wcfsetup/install/files/lib/data/notice/NoticeEditor.class.php @@ -0,0 +1,71 @@ + + * @package com.woltlab.wcf + * @subpackage data.notice + * @category Community Framework + */ +class NoticeEditor extends DatabaseObjectEditor implements IEditableCachedObject { + /** + * @see \wcf\data\DatabaseObjectDecorator::$baseClass + */ + protected static $baseClass = 'wcf\data\notice\Notice'; + + /** + * Sets the show order of the notice. + * + * @param integer $showOrder + */ + public function setShowOrder($showOrder = 0) { + $newShowOrder = 1; + + $sql = "SELECT MAX(showOrder) + FROM wcf".WCF_N."_notice"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(); + $maxShowOrder = $statement->fetchColumn(); + if (!$maxShowOrder) $maxShowOrder = 0; + + if (!$showOrder || $showOrder > $maxShowOrder) { + $newShowOrder = $maxShowOrder + 1; + } + else { + // shift other notices + $sql = "UPDATE wcf".WCF_N."_notice + SET showOrder = showOrder + 1 + WHERE showOrder >= ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(array( + $showOrder + )); + + $newShowOrder = $showOrder; + } + + $this->update(array( + 'showOrder' => $newShowOrder + )); + } + + /** + * @see \wcf\data\IEditableCachedObject::resetCache() + */ + public static function resetCache() { + NoticeCacheBuilder::getInstance()->reset(); + ConditionCacheBuilder::getInstance()->reset(array( + 'definitionID' => ObjectTypeCache::getInstance()->getDefinitionByName('com.woltlab.wcf.condition.notice')->definitionID + )); + } +} diff --git a/wcfsetup/install/files/lib/data/notice/NoticeList.class.php b/wcfsetup/install/files/lib/data/notice/NoticeList.class.php new file mode 100644 index 0000000000..6eeac4fc13 --- /dev/null +++ b/wcfsetup/install/files/lib/data/notice/NoticeList.class.php @@ -0,0 +1,15 @@ + + * @package com.woltlab.wcf + * @subpackage data.notice + * @category Community Framework + */ +class NoticeList extends DatabaseObjectList { } diff --git a/wcfsetup/install/files/lib/system/cache/builder/NoticeCacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/builder/NoticeCacheBuilder.class.php new file mode 100644 index 0000000000..20bc0e5ff0 --- /dev/null +++ b/wcfsetup/install/files/lib/system/cache/builder/NoticeCacheBuilder.class.php @@ -0,0 +1,27 @@ + + * @package com.woltlab.wcf + * @subpackage system.cache.builder + * @category Community Framework + */ +class NoticeCacheBuilder extends AbstractCacheBuilder { + /** + * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild() + */ + protected function rebuild(array $parameters) { + $noticeList = new NoticeList(); + $noticeList->getConditionBuilder()->add('isDisabled = ?', array(0)); + $noticeList->sqlOrderBy = 'showOrder ASC'; + $noticeList->readObjects(); + + return $noticeList->getObjects(); + } +} diff --git a/wcfsetup/install/files/lib/system/condition/AbstractMultiSelectCondition.class.php b/wcfsetup/install/files/lib/system/condition/AbstractMultiSelectCondition.class.php new file mode 100644 index 0000000000..3910e4daea --- /dev/null +++ b/wcfsetup/install/files/lib/system/condition/AbstractMultiSelectCondition.class.php @@ -0,0 +1,79 @@ + + * @package com.woltlab.wcf + * @subpackage system.condition + * @category Community Framework + */ +abstract class AbstractMultiSelectCondition extends AbstractSelectCondition { + /** + * @see \wcf\system\condition\AbstractSelectCondition::$fieldValue + */ + protected $fieldValue = array(); + + /** + * @see \wcf\system\condition\ICondition::getData() + */ + public function getData() { + if (!empty($this->fieldValue)) { + return array( + $this->fieldName => $this->fieldValue + ); + } + + return null; + } + + /** + * @see \wcf\system\condition\AbstractSingleFieldCondition::getFieldElement() + */ + protected function getFieldElement() { + $options = $this->getOptions(); + + $fieldElement = '"; + + return $fieldElement; + } + + /** + * @see \wcf\system\condition\ICondition::readFormParameters() + */ + public function readFormParameters() { + if (isset($_POST[$this->fieldName]) && is_array($_POST[$this->fieldName])) $this->fieldValue = ArrayUtil::toIntegerArray($_POST[$this->fieldName]); + } + + /** + * @see \wcf\system\condition\ICondition::validate() + */ + public function reset() { + $this->fieldValue = array(); + } + + /** + * @see \wcf\system\condition\ICondition::validate() + */ + public function validate() { + $options = $this->getOptions(); + foreach ($this->fieldValue as $value) { + if (!isset($options[$value])) { + $this->errorMessage = 'wcf.global.form.error.noValidSelection'; + + throw new UserInputException($this->fieldName, 'noValidSelection'); + } + } + } +} diff --git a/wcfsetup/install/files/lib/system/condition/ConditionHandler.class.php b/wcfsetup/install/files/lib/system/condition/ConditionHandler.class.php index 2651641ad1..edda4c856b 100644 --- a/wcfsetup/install/files/lib/system/condition/ConditionHandler.class.php +++ b/wcfsetup/install/files/lib/system/condition/ConditionHandler.class.php @@ -28,23 +28,21 @@ class ConditionHandler extends SingletonFactory { * Creates condition objects for the object with the given id and based * on the given condition object types. * - * @param integer $objectID - * @param array $conditionObjectTypes + * @param integer $objectID + * @param array<\wcf\data\object\type\ObjectType> $conditionObjectTypes */ public function createConditions($objectID, array $conditionObjectTypes) { - foreach ($conditionObjectTypes as $objectTypes) { - foreach ($objectTypes as $objectType) { - $conditionData = $objectType->getProcessor()->getData(); - if ($conditionData !== null) { - $conditionAction = new ConditionAction(array(), 'create', array( - 'data' => array( - 'conditionData' => serialize($conditionData), - 'objectID' => $objectID, - 'objectTypeID' => $objectType->objectTypeID - ) - )); - $conditionAction->executeAction(); - } + foreach ($conditionObjectTypes as $objectType) { + $conditionData = $objectType->getProcessor()->getData(); + if ($conditionData !== null) { + $conditionAction = new ConditionAction(array(), 'create', array( + 'data' => array( + 'conditionData' => serialize($conditionData), + 'objectID' => $objectID, + 'objectTypeID' => $objectType->objectTypeID + ) + )); + $conditionAction->executeAction(); } } } @@ -74,7 +72,7 @@ class ConditionHandler extends SingletonFactory { return $this->conditions[$definition->definitionID][$objectID]; } - return null; + return array(); } /** @@ -82,7 +80,7 @@ class ConditionHandler extends SingletonFactory { * * @param integer $objectID * @param array<\wcf\data\condition\Condition> $oldConditions - * @param array $conditionObjectTypes + * @param array<\wcf\data\object\type\ObjectType> $conditionObjectTypes */ public function updateConditions($objectID, array $oldConditions, array $conditionObjectTypes) { // delete old conditions first diff --git a/wcfsetup/install/files/lib/system/condition/INoticeCondition.class.php b/wcfsetup/install/files/lib/system/condition/INoticeCondition.class.php new file mode 100644 index 0000000000..05f90cabe1 --- /dev/null +++ b/wcfsetup/install/files/lib/system/condition/INoticeCondition.class.php @@ -0,0 +1,26 @@ + + * @package com.woltlab.wcf + * @subpackage system.condition + * @category Community Framework + */ +interface INoticeCondition extends ICondition { + /** + * Returns true if a notice with the given condition will be shown. + * + * All necessary data to check the condition needs to be globally available + * like the active user object via WCF::getUser(). + * + * @param \wcf\data\condition\Condition $condition + * @return boolean + */ + public function showNotice(Condition $condition); +} diff --git a/wcfsetup/install/files/lib/system/condition/MultiPageControllerCondition.class.php b/wcfsetup/install/files/lib/system/condition/MultiPageControllerCondition.class.php new file mode 100644 index 0000000000..1abce2aaa9 --- /dev/null +++ b/wcfsetup/install/files/lib/system/condition/MultiPageControllerCondition.class.php @@ -0,0 +1,58 @@ + + * @package com.woltlab.wcf + * @subpackage system.condition + * @category Community Framework + */ +class MultiPageControllerCondition extends AbstractMultiSelectCondition implements INoticeCondition { + /** + * @see \wcf\system\condition\AbstractSingleFieldCondition::$label + */ + protected $description = 'wcf.global.multiSelect'; + + /** + * @see \wcf\system\condition\AbstractSelectCondition::$fieldName + */ + protected $fieldName = 'pageControllers'; + + /** + * @see \wcf\system\condition\AbstractSingleFieldCondition::$label + */ + protected $label = 'wcf.page.requestedPage'; + + /** + * @see \wcf\system\condition\AbstractSelectCondition::getOptions() + */ + protected function getOptions() { + return PageManager::getInstance()->getSelection(); + } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + $requestClassName = RequestHandler::getInstance()->getActiveRequest()->getClassName(); + $pageControllers = $condition->pageControllers; + foreach ($pageControllers as $objectTypeID) { + $objectType = ObjectTypeCache::getInstance()->getObjectType($objectTypeID); + if ($objectType === null) return false; + + if ($requestClassName == $objectType->className) { + return true; + } + } + + return false; + } +} diff --git a/wcfsetup/install/files/lib/system/condition/UserAvatarCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserAvatarCondition.class.php index 26eb24925b..0d4170a547 100644 --- a/wcfsetup/install/files/lib/system/condition/UserAvatarCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserAvatarCondition.class.php @@ -16,7 +16,7 @@ use wcf\system\WCF; * @subpackage system.condition * @category Community Framework */ -class UserAvatarCondition extends AbstractSelectCondition implements IUserCondition { +class UserAvatarCondition extends AbstractSelectCondition implements INoticeCondition, IUserCondition { /** * @see wcf\system\condition\AbstractSelectCondition::$fieldName */ @@ -94,4 +94,13 @@ class UserAvatarCondition extends AbstractSelectCondition implements IUserCondit self::GRAVATAR => 'wcf.user.condition.avatar.gravatar' ); } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserEmailCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserEmailCondition.class.php index f6bf199872..f441422e67 100644 --- a/wcfsetup/install/files/lib/system/condition/UserEmailCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserEmailCondition.class.php @@ -3,6 +3,7 @@ namespace wcf\system\condition; use wcf\data\condition\Condition; use wcf\data\user\User; use wcf\data\user\UserList; +use wcf\system\WCF; /** * Condition implementation for the email address of a user. @@ -14,7 +15,7 @@ use wcf\data\user\UserList; * @subpackage system.condition * @category Community Framework */ -class UserEmailCondition extends AbstractTextCondition implements IUserCondition { +class UserEmailCondition extends AbstractTextCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractTextCondition::$fieldName */ @@ -38,4 +39,13 @@ class UserEmailCondition extends AbstractTextCondition implements IUserCondition public function checkUser(Condition $condition, User $user) { return mb_strpos($user->email, $condition->email) !== false; } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserGroupCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserGroupCondition.class.php index 4cb3a0e238..c41b249df2 100644 --- a/wcfsetup/install/files/lib/system/condition/UserGroupCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserGroupCondition.class.php @@ -5,6 +5,7 @@ use wcf\data\user\group\UserGroup; use wcf\data\user\User; use wcf\data\user\UserList; use wcf\system\exception\UserInputException; +use wcf\system\WCF; use wcf\util\ArrayUtil; /** @@ -18,7 +19,7 @@ use wcf\util\ArrayUtil; * @subpackage system.condition * @category Community Framework */ -class UserGroupCondition extends AbstractMultipleFieldsCondition implements IUserCondition { +class UserGroupCondition extends AbstractMultipleFieldsCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractMultipleFieldsCondition::$descriptions */ @@ -70,11 +71,11 @@ class UserGroupCondition extends AbstractMultipleFieldsCondition implements IUse */ public function checkUser(Condition $condition, User $user) { $groupIDs = $user->getGroupIDs(); - if (!empty($condition->groupIDs) && count(array_diff($condition->groupIDs, $groupIDs))) { + if (!empty($condition->conditionData['groupIDs']) && count(array_diff($condition->conditionData['groupIDs'], $groupIDs))) { return false; } - if (!empty($condition->notGroupIDs) && count(array_intersect($condition->notGroupIDs, $groupIDs))) { + if (!empty($condition->conditionData['notGroupIDs']) && count(array_intersect($condition->conditionData['notGroupIDs'], $groupIDs))) { return false; } @@ -149,7 +150,12 @@ HTML; */ protected function getUserGroups() { if ($this->userGroups == null) { - $this->userGroups = UserGroup::getGroupsByType(array(UserGroup::OTHER)); + $groupTypes = array(UserGroup::OTHER); + if ($this->includeguests) { + $groupTypes[] = UserGroup::GUESTS; + } + + $this->userGroups = UserGroup::getGroupsByType($groupTypes); foreach ($this->userGroups as $key => $userGroup) { if (!$userGroup->isAccessible()) { unset($this->userGroups[$key]); @@ -218,4 +224,11 @@ HTML; throw new UserInputException('notGroupIDs', 'groupIDsIntersection'); } } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserIntegerPropertyCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserIntegerPropertyCondition.class.php index 0b34358253..09070c5779 100644 --- a/wcfsetup/install/files/lib/system/condition/UserIntegerPropertyCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserIntegerPropertyCondition.class.php @@ -17,7 +17,7 @@ use wcf\system\WCF; * @subpackage system.condition * @category Community Framework */ -class UserIntegerPropertyCondition extends AbstractIntegerCondition implements IUserCondition { +class UserIntegerPropertyCondition extends AbstractIntegerCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractIntegerCondition::$maxValueErrorMessage */ @@ -76,4 +76,13 @@ class UserIntegerPropertyCondition extends AbstractIntegerCondition implements I protected function getLabel($identifier) { return WCF::getLanguage()->get('wcf.user.condition.'.$this->getDecoratedObject()->propertyname.'.'.$identifier); } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserLanguageCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserLanguageCondition.class.php index ba9e0f571c..eeeb8c589f 100644 --- a/wcfsetup/install/files/lib/system/condition/UserLanguageCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserLanguageCondition.class.php @@ -18,7 +18,7 @@ use wcf\util\ArrayUtil; * @subpackage system.condition * @category Community Framework */ -class UserLanguageCondition extends AbstractSingleFieldCondition implements IUserCondition { +class UserLanguageCondition extends AbstractSingleFieldCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractSingleFieldCondition::$label */ @@ -41,7 +41,7 @@ class UserLanguageCondition extends AbstractSingleFieldCondition implements IUse * @see \wcf\system\condition\IUserCondition::checkUser() */ public function checkUser(Condition $condition, User $user) { - if (!empty($condition->languageIDs) && !in_array($user->languageID, $condition->languageIDs)) { + if (!empty($condition->conditionData['languageIDs']) && !in_array($user->languageID, $condition->languageIDs)) { return false; } @@ -108,4 +108,11 @@ class UserLanguageCondition extends AbstractSingleFieldCondition implements IUse } } } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserOptionsCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserOptionsCondition.class.php index 812f1e584d..1d637cdcd0 100644 --- a/wcfsetup/install/files/lib/system/condition/UserOptionsCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserOptionsCondition.class.php @@ -17,7 +17,7 @@ use wcf\system\WCF; * @subpackage system.condition * @category Community Framework */ -class UserOptionsCondition extends AbstractMultipleFieldsCondition implements IUserCondition { +class UserOptionsCondition extends AbstractMultipleFieldsCondition implements INoticeCondition, IUserCondition { /** * user option handler object * @var \wcf\system\option\user\UserOptionHandler @@ -127,4 +127,13 @@ class UserOptionsCondition extends AbstractMultipleFieldsCondition implements IU public function setData(Condition $condition) { $this->optionHandler->setOptionValues($condition->conditionData['optionValues']); } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserRegistrationDateCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserRegistrationDateCondition.class.php index b0a95eeee7..97070225b7 100644 --- a/wcfsetup/install/files/lib/system/condition/UserRegistrationDateCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserRegistrationDateCondition.class.php @@ -16,7 +16,7 @@ use wcf\system\WCF; * @subpackage system.condition * @category Community Framework */ -class UserRegistrationDateCondition extends AbstractSingleFieldCondition implements IUserCondition { +class UserRegistrationDateCondition extends AbstractSingleFieldCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractSingleFieldCondition::$label */ @@ -149,4 +149,13 @@ HTML; throw new UserInputException($this->fieldName, 'endBeforeStart'); } } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserRegistrationDateIntervalCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserRegistrationDateIntervalCondition.class.php index 4b989eae27..0d41d86d50 100644 --- a/wcfsetup/install/files/lib/system/condition/UserRegistrationDateIntervalCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserRegistrationDateIntervalCondition.class.php @@ -18,7 +18,7 @@ use wcf\system\WCF; * @subpackage system.condition * @category Community Framework */ -class UserRegistrationDateIntervalCondition extends AbstractIntegerCondition implements IUserCondition { +class UserRegistrationDateIntervalCondition extends AbstractIntegerCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractMultipleFieldsCondition::$languageItemPrefix */ @@ -86,4 +86,13 @@ class UserRegistrationDateIntervalCondition extends AbstractIntegerCondition imp protected function getLabel($identifier) { return WCF::getLanguage()->get('wcf.user.condition.registrationDateInterval.'.$identifier); } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserStateCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserStateCondition.class.php index 919a444468..e2cfffab69 100644 --- a/wcfsetup/install/files/lib/system/condition/UserStateCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserStateCondition.class.php @@ -16,7 +16,7 @@ use wcf\system\WCF; * @subpackage system.condition * @category Community Framework */ -class UserStateCondition extends AbstractSingleFieldCondition implements IUserCondition { +class UserStateCondition extends AbstractSingleFieldCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractSingleFieldCondition::$label */ @@ -191,4 +191,13 @@ HTML; throw new UserInputException('userisEnabled', 'conflict'); } } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/condition/UserUsernameCondition.class.php b/wcfsetup/install/files/lib/system/condition/UserUsernameCondition.class.php index 61ea094fb6..7b7ccd1d5d 100644 --- a/wcfsetup/install/files/lib/system/condition/UserUsernameCondition.class.php +++ b/wcfsetup/install/files/lib/system/condition/UserUsernameCondition.class.php @@ -16,7 +16,7 @@ use wcf\util\StringUtil; * @subpackage system.condition * @category Community Framework */ -class UserUsernameCondition extends AbstractTextCondition implements IUserCondition { +class UserUsernameCondition extends AbstractTextCondition implements INoticeCondition, IUserCondition { /** * @see \wcf\system\condition\AbstractTextCondition::$fieldName */ @@ -40,4 +40,13 @@ class UserUsernameCondition extends AbstractTextCondition implements IUserCondit public function checkUser(Condition $condition, User $user) { return mb_strpos($user->username, $condition->username) !== false; } + + /** + * @see \wcf\system\condition\INoticeCondition::showNotice() + */ + public function showNotice(Condition $condition) { + if (!WCF::getUser()->userID) return; + + return $this->checkUser($condition, WCF::getUser()); + } } diff --git a/wcfsetup/install/files/lib/system/notice/NoticeHandler.class.php b/wcfsetup/install/files/lib/system/notice/NoticeHandler.class.php new file mode 100644 index 0000000000..b9583eee4d --- /dev/null +++ b/wcfsetup/install/files/lib/system/notice/NoticeHandler.class.php @@ -0,0 +1,54 @@ + + * @package com.woltlab.wcf + * @subpackage system.notice + * @category Community Framework + */ +class NoticeHandler extends SingletonFactory { + /** + * list with all enabled notices + * @var array<\wcf\data\notice\Notice> + */ + protected $notices = array(); + + /** + * @see \wcf\system\SingletonFacetory::init() + */ + protected function init() { + $this->notices = NoticeCacheBuilder::getInstance()->getData(); + } + + /** + * Returns the notices which are visible for the active user. + * + * @return array<\wcf\data\notice\Notice> + */ + public function getVisibleNotices() { + $notices = array(); + foreach ($this->notices as $notice) { + $checkFailed = false; + $conditions = $notice->getConditions(); + foreach ($conditions as $condition) { + if (!$condition->getObjectType()->getProcessor()->showNotice($condition)) { + $checkFailed = true; + break; + } + } + + if (!$checkFailed && !$notice->isDismissed()) { + $notices[$notice->noticeID] = $notice; + } + } + + return $notices; + } +} diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 6672c72d4d..86cab947d5 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -386,6 +386,8 @@ + +
@@ -580,6 +582,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2023,6 +2050,10 @@ Fehler sind beispielsweise: + + + + @@ -2031,6 +2062,7 @@ Fehler sind beispielsweise: + Datenschutz

Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index 0745050ef6..b3c3d92647 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -491,6 +491,24 @@ CREATE TABLE wcf1_modification_log ( additionalData MEDIUMTEXT ); +DROP TABLE IF EXISTS wcf1_notice; +CREATE TABLE wcf1_notice ( + noticeID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY, + noticeName VARCHAR(255) NOT NULL, + notice MEDIUMTEXT, + noticeUseHtml TINYINT(1) NOT NULL DEFAULT 0, + showOrder INT(10) NOT NULL DEFAULT 0, + isDisabled TINYINT(1) NOT NULL DEFAULT 0, + isDismissible TINYINT(1) NOT NULL DEFAULT 0 +); + +DROP TABLE IF EXISTS wcf1_notice_dismissed; +CREATE TABLE wcf1_notice_dismissed ( + noticeID INT(10) NOT NULL, + userID INT(10) NOT NULL, + PRIMARY KEY (noticeID, userID) +); + DROP TABLE IF EXISTS wcf1_object_type; CREATE TABLE wcf1_object_type ( objectTypeID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -1590,6 +1608,9 @@ ALTER TABLE wcf1_poll_option_vote ADD FOREIGN KEY (pollID) REFERENCES wcf1_poll ALTER TABLE wcf1_poll_option_vote ADD FOREIGN KEY (optionID) REFERENCES wcf1_poll_option (optionID) ON DELETE CASCADE; ALTER TABLE wcf1_poll_option_vote ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE; +ALTER TABLE wcf1_notice_dismissed ADD FOREIGN KEY (noticeID) REFERENCES wcf1_notice (noticeID) ON DELETE CASCADE; +ALTER TABLE wcf1_notice_dismissed ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE; + /* SQL_PARSER_OFFSET */ /* default inserts */