From 04488ea871de26ebbfd875c56a2aebcc5ab51b89 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Sun, 7 Jun 2015 21:30:10 +0200 Subject: [PATCH] Boolean user group options now support 'Never' The boolean option type allowed only for a simple true/false, which is sometimes quite difficult to work with. For example revoking group permissions is usually accomplished by fiddling with all groups. The 'Never' option solves this by using the unique value '-1' to revoke a permission regardless how often it was granted. --- .../templates/userGroupBooleanOptionType.tpl | 16 ++++ wcfsetup/install/files/js/WCF.js | 7 +- .../lib/data/user/group/UserGroup.class.php | 9 ++ .../UserGroupPermissionCacheBuilder.class.php | 91 +++++++++---------- .../lib/system/option/OptionHandler.class.php | 1 - .../BooleanUserGroupOptionType.class.php | 35 ++++++- .../group/IUserGroupGroupOptionType.class.php | 29 ++++++ .../user/group/TUserGroupOptionType.class.php | 35 +++++++ .../group/UserGroupOptionHandler.class.php | 13 +++ wcfsetup/install/files/style/form.less | 86 ++++++++++++++++++ wcfsetup/install/lang/de.xml | 3 + wcfsetup/install/lang/en.xml | 3 + 12 files changed, 275 insertions(+), 53 deletions(-) create mode 100644 wcfsetup/install/files/acp/templates/userGroupBooleanOptionType.tpl create mode 100644 wcfsetup/install/files/lib/system/option/user/group/IUserGroupGroupOptionType.class.php create mode 100644 wcfsetup/install/files/lib/system/option/user/group/TUserGroupOptionType.class.php diff --git a/wcfsetup/install/files/acp/templates/userGroupBooleanOptionType.tpl b/wcfsetup/install/files/acp/templates/userGroupBooleanOptionType.tpl new file mode 100644 index 0000000000..9d2cd5094c --- /dev/null +++ b/wcfsetup/install/files/acp/templates/userGroupBooleanOptionType.tpl @@ -0,0 +1,16 @@ +
    +
  1. + + +
  2. +
  3. + + +
  4. + {if $group === null || !$group->isEveryone()} +
  5. + + +
  6. + {/if} +
diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 328fbf8422..7998f980ee 100755 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -4578,7 +4578,12 @@ WCF.Option.Handler = Class.extend({ case 'radio': if (option.prop('checked')) { - this._execute(true, $disableOptions, $enableOptions); + var isActive = true; + if (option.data('isBoolean') && option.val() != 1) { + isActive = false; + } + + this._execute(isActive, $disableOptions, $enableOptions); } break; } diff --git a/wcfsetup/install/files/lib/data/user/group/UserGroup.class.php b/wcfsetup/install/files/lib/data/user/group/UserGroup.class.php index 8865be30c3..df45bdd820 100644 --- a/wcfsetup/install/files/lib/data/user/group/UserGroup.class.php +++ b/wcfsetup/install/files/lib/data/user/group/UserGroup.class.php @@ -156,6 +156,15 @@ class UserGroup extends DatabaseObject { return false; } + /** + * Returns true if this is the 'Everyone' group. + * + * @return boolean + */ + public function isEveryone() { + return $this->groupType == self::EVERYONE; + } + /** * Returns true if the given groups are accessible for the active user. * diff --git a/wcfsetup/install/files/lib/system/cache/builder/UserGroupPermissionCacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/builder/UserGroupPermissionCacheBuilder.class.php index 5a0623ca70..15d69df24d 100644 --- a/wcfsetup/install/files/lib/system/cache/builder/UserGroupPermissionCacheBuilder.class.php +++ b/wcfsetup/install/files/lib/system/cache/builder/UserGroupPermissionCacheBuilder.class.php @@ -21,69 +21,60 @@ class UserGroupPermissionCacheBuilder extends AbstractCacheBuilder { * list of used group option type objects * @var array<\wcf\system\option\group\IGroupOptionType> */ - protected $typeObjects = array(); + protected $typeObjects = []; /** * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild() */ public function rebuild(array $parameters) { - $data = array(); + $data = []; - // get all options - $sql = "SELECT optionName, optionID - FROM wcf".WCF_N."_user_group_option"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute(); + // get option values + $conditions = new PreparedStatementConditionBuilder(); + $conditions->add("option_value.groupID IN (?)", [ $parameters ]); - $options = array(); + $sql = "SELECT option_table.optionName, option_table.optionType, option_value.optionValue + FROM wcf".WCF_N."_user_group_option_value option_value + LEFT JOIN wcf".WCF_N."_user_group_option option_table + ON (option_table.optionID = option_value.optionID) + ".$conditions; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute($conditions->getParameters()); while ($row = $statement->fetchArray()) { - $options[$row['optionName']] = $row['optionID']; + if (!isset($data[$row['optionName']])) { + $data[$row['optionName']] = [ 'type' => $row['optionType'], 'values' => [] ]; + } + + $data[$row['optionName']]['values'][] = $row['optionValue']; } - if (!empty($options)) { - // get needed options - $conditions = new PreparedStatementConditionBuilder(); - $conditions->add("option_value.groupID IN (?)", array($parameters)); - $conditions->add("option_value.optionID IN (?)", array($options)); - - $sql = "SELECT option_table.optionName, option_table.optionType, option_value.optionValue - FROM wcf".WCF_N."_user_group_option_value option_value - LEFT JOIN wcf".WCF_N."_user_group_option option_table - ON (option_table.optionID = option_value.optionID) - ".$conditions; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute($conditions->getParameters()); - while ($row = $statement->fetchArray()) { - if (!isset($data[$row['optionName']])) { - $data[$row['optionName']] = array('type' => $row['optionType'], 'values' => array()); - } - - $data[$row['optionName']]['values'][] = $row['optionValue']; + // merge values + foreach ($data as $optionName => $option) { + if (count($option['values']) == 1) { + $result = $option['values'][0]; } - - // merge values - foreach ($data as $optionName => $option) { - if (count($option['values']) == 1) { - $result = $option['values'][0]; - } - else { - $typeObj = $this->getTypeObject($option['type']); - $result = array_shift($option['values']); - foreach ($option['values'] as $value) { - $newValue = $typeObj->merge($result, $value); - if ($newValue !== null) { - $result = $newValue; - } + else { + $typeObj = $this->getTypeObject($option['type']); + $result = array_shift($option['values']); + foreach ($option['values'] as $value) { + $newValue = $typeObj->merge($result, $value); + if ($newValue !== null) { + $result = $newValue; } } - - // unset false values - if ($result === false) { - unset($data[$optionName]); - } - else { - $data[$optionName] = $result; - } + } + + // handle special value 'Never' for boolean options + if ($option['type'] === 'boolean' && $result == -1) { + $result = 0; + } + + // unset false values + if ($result === false) { + unset($data[$optionName]); + } + else { + $data[$optionName] = $result; } } diff --git a/wcfsetup/install/files/lib/system/option/OptionHandler.class.php b/wcfsetup/install/files/lib/system/option/OptionHandler.class.php index dc3742d276..102a0e52be 100644 --- a/wcfsetup/install/files/lib/system/option/OptionHandler.class.php +++ b/wcfsetup/install/files/lib/system/option/OptionHandler.class.php @@ -7,7 +7,6 @@ use wcf\system\event\EventHandler; use wcf\system\exception\SystemException; use wcf\system\exception\UserInputException; use wcf\system\language\I18nHandler; -use wcf\system\WCF; use wcf\util\ClassUtil; use wcf\util\StringUtil; diff --git a/wcfsetup/install/files/lib/system/option/user/group/BooleanUserGroupOptionType.class.php b/wcfsetup/install/files/lib/system/option/user/group/BooleanUserGroupOptionType.class.php index c25dfa9ff8..3c72f32731 100644 --- a/wcfsetup/install/files/lib/system/option/user/group/BooleanUserGroupOptionType.class.php +++ b/wcfsetup/install/files/lib/system/option/user/group/BooleanUserGroupOptionType.class.php @@ -1,6 +1,8 @@ enableOptions); + + WCF::getTPL()->assign([ + 'disableOptions' => $options['disableOptions'], + 'enableOptions' => $options['enableOptions'], + 'group' => $this->userGroup, + 'option' => $option, + 'value' => $value + ]); + + return WCF::getTPL()->fetch('userGroupBooleanOptionType'); + } + + /** + * @see \wcf\system\option\IOptionType::getCSSClassName() + */ + public function getCSSClassName() { + return ''; + } + /** * @see \wcf\system\option\user\group\IUserGroupOptionType::merge() */ public function merge($defaultValue, $groupValue) { + // force value for 'Never' + if ($defaultValue == -1 || $groupValue == -1) { + return -1; + } + // don't save if values are equal or $defaultValue is better if ($defaultValue == $groupValue || $defaultValue && !$groupValue) { return null; diff --git a/wcfsetup/install/files/lib/system/option/user/group/IUserGroupGroupOptionType.class.php b/wcfsetup/install/files/lib/system/option/user/group/IUserGroupGroupOptionType.class.php new file mode 100644 index 0000000000..dfa1e4e6c2 --- /dev/null +++ b/wcfsetup/install/files/lib/system/option/user/group/IUserGroupGroupOptionType.class.php @@ -0,0 +1,29 @@ + + * @package com.woltlab.wcf + * @subpackage system.option.user.group + * @category Community Framework + */ +interface IUserGroupGroupOptionType { + /** + * Sets the active user group object. + * + * @param \wcf\data\user\group\UserGroup $group + */ + public function setUserGroup(UserGroup $group); + + /** + * Returns the active user group object or null. + * + * @return \wcf\data\user\group\UserGroup + */ + public function getUserGroup(); +} diff --git a/wcfsetup/install/files/lib/system/option/user/group/TUserGroupOptionType.class.php b/wcfsetup/install/files/lib/system/option/user/group/TUserGroupOptionType.class.php new file mode 100644 index 0000000000..0b1e9bfe68 --- /dev/null +++ b/wcfsetup/install/files/lib/system/option/user/group/TUserGroupOptionType.class.php @@ -0,0 +1,35 @@ + + * @package com.woltlab.wcf + * @subpackage system.option.user.group + * @category Community Framework + */ +trait TUserGroupOptionType { + /** + * user group object + * @var \wcf\data\user\group\UserGroup + */ + protected $userGroup = null; + + /** + * @see \wcf\system\option\user\group\IUserGroupGroupOptionType::setUserGroup() + */ + public function setUserGroup(UserGroup $group) { + $this->userGroup = $group; + } + + /** + * @see \wcf\system\option\user\group\IUserGroupGroupOptionType::getUserGroup() + */ + public function getUserGroup() { + return $this->userGroup; + } +} diff --git a/wcfsetup/install/files/lib/system/option/user/group/UserGroupOptionHandler.class.php b/wcfsetup/install/files/lib/system/option/user/group/UserGroupOptionHandler.class.php index 1e176f554c..5115a8f535 100644 --- a/wcfsetup/install/files/lib/system/option/user/group/UserGroupOptionHandler.class.php +++ b/wcfsetup/install/files/lib/system/option/user/group/UserGroupOptionHandler.class.php @@ -45,6 +45,19 @@ class UserGroupOptionHandler extends OptionHandler { $this->group = $group; } + /** + * @see \wcf\system\option\OptionHandler::getTypeObject() + */ + public function getTypeObject($type) { + $objectType = parent::getTypeObject($type); + + if ($this->group !== null && $objectType instanceof IUserGroupGroupOptionType) { + $objectType->setUserGroup($this->group); + } + + return $objectType; + } + /** * @see \wcf\system\option\OptionHandler::checkOption() */ diff --git a/wcfsetup/install/files/style/form.less b/wcfsetup/install/files/style/form.less index 75723b9996..f1d8c57a1b 100644 --- a/wcfsetup/install/files/style/form.less +++ b/wcfsetup/install/files/style/form.less @@ -543,4 +543,90 @@ select > option { .redactor-editor { font-size: 16px; } +} + +/* BooleanUserGroupOptionType */ +.optionTypeBoolean { + display: flex; + + > li { + border: 1px solid @wcfContainerBorderColor; + display: flex; + flex: 0 1 100px; + + &:not(:last-child) { + border-right-width: 0; + } + + &:first-child { + border-radius: 3px 0 0 3px; + } + + &:last-child { + border-radius: 0 3px 3px 0; + } + + &:hover > label { + opacity: 1 !important; + } + + > input { + display: none; + + &:not(:checked) + label { + opacity: .6; + } + + &:checked + label { + opacity: 1; + + &.yes { + background-color: rgb(223, 240, 216); + color: rgb(60, 118, 61); + + > .icon { + color: rgb(60, 118, 61); + } + } + + &.no { + background-color: rgb(242, 222, 222); + color: rgb(169, 68, 66); + + > .icon { + color: rgb(169, 68, 66); + } + } + + &.never { + background-color: rgb(252, 248, 227); + color: rgb(138, 109, 59); + + > .icon { + color: rgb(138, 109, 59); + } + } + } + } + + > label { + cursor: pointer; + flex: 1 auto; + font-size: .85rem; + padding: @wcfGapTiny; + text-align: center; + + transition: all .3s linear; + + > .icon { + cursor: pointer !important; + } + } + } +} + +@media only screen and (max-width: 800px) { + .optionTypeBoolean > li { + flex: 1; + } } \ No newline at end of file diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index f62663f69d..4cb6967bd2 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -440,6 +440,9 @@ + + + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 012cdb0d79..d0a22231ce 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -439,6 +439,9 @@ Examples for medium ID detection: + + + -- 2.20.1