From 7f77ebf1d53c820a92b7cd2bf63c89ea5d424971 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Wed, 28 Aug 2019 18:00:29 +0200 Subject: [PATCH] ignore disabled permissions in cache builder Closes #3061 --- .../UserGroupPermissionCacheBuilder.class.php | 31 ++++++++++++-- .../option/AbstractOptionType.class.php | 7 ++++ .../system/option/BooleanOptionType.class.php | 20 +++++++++ .../lib/system/option/IOptionType.class.php | 12 +++++- .../option/RadioButtonOptionType.class.php | 41 +++++++++++++++++++ 5 files changed, 106 insertions(+), 5 deletions(-) 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 d61aa563ca..e8b582adfb 100644 --- a/wcfsetup/install/files/lib/system/cache/builder/UserGroupPermissionCacheBuilder.class.php +++ b/wcfsetup/install/files/lib/system/cache/builder/UserGroupPermissionCacheBuilder.class.php @@ -53,7 +53,8 @@ class UserGroupPermissionCacheBuilder extends AbstractCacheBuilder { $conditions = new PreparedStatementConditionBuilder(); $conditions->add("option_value.groupID IN (?)", [$parameters]); - $sql = "SELECT option_table.optionName, option_table.optionType, option_value.optionValue + $optionData = []; + $sql = "SELECT option_table.optionName, option_table.optionType, option_value.optionValue, option_value.groupID, option_table.enableOptions 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) @@ -61,11 +62,33 @@ class UserGroupPermissionCacheBuilder extends AbstractCacheBuilder { $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); while ($row = $statement->fetchArray()) { - if (!isset($data[$row['optionName']])) { - $data[$row['optionName']] = ['type' => $row['optionType'], 'values' => []]; + $optionData[$row['groupID']][$row['optionName']] = $row; + } + + foreach ($optionData as $groupID => $options) { + $optionBlacklist = []; + + foreach ($options as $option) { + if ($option['enableOptions']) { + $typeObj = $this->getTypeObject($option['optionType']); + $disabledOptions = $typeObj->getDisabledOptionNames($option['optionValue'], $option['enableOptions']); + if (!empty($disabledOptions)) { + $optionBlacklist = array_merge($optionBlacklist, $disabledOptions); + } + } } - $data[$row['optionName']]['values'][] = $row['optionValue']; + $options = array_filter($options, function($optionName) use (&$optionBlacklist) { + return !in_array($optionName, $optionBlacklist); + }, ARRAY_FILTER_USE_KEY); + + foreach ($options as $option) { + if (!isset($data[$option['optionName']])) { + $data[$option['optionName']] = ['type' => $option['optionType'], 'values' => []]; + } + + $data[$option['optionName']]['values'][] = $option['optionValue']; + } } $includesOwnerGroup = false; diff --git a/wcfsetup/install/files/lib/system/option/AbstractOptionType.class.php b/wcfsetup/install/files/lib/system/option/AbstractOptionType.class.php index 9a8762004b..d0f3ffbfa5 100644 --- a/wcfsetup/install/files/lib/system/option/AbstractOptionType.class.php +++ b/wcfsetup/install/files/lib/system/option/AbstractOptionType.class.php @@ -56,4 +56,11 @@ abstract class AbstractOptionType implements IOptionType { public function hideLabelInSearch() { return false; } + + /** + * @inheritDoc + */ + public function getDisabledOptionNames($value, $enableOptions) { + return []; + } } diff --git a/wcfsetup/install/files/lib/system/option/BooleanOptionType.class.php b/wcfsetup/install/files/lib/system/option/BooleanOptionType.class.php index 651598580f..0836bd7c85 100644 --- a/wcfsetup/install/files/lib/system/option/BooleanOptionType.class.php +++ b/wcfsetup/install/files/lib/system/option/BooleanOptionType.class.php @@ -5,6 +5,7 @@ use wcf\data\user\User; use wcf\data\user\UserList; use wcf\system\database\util\PreparedStatementConditionBuilder; use wcf\system\WCF; +use wcf\util\ArrayUtil; /** * Option type implementation for boolean values. @@ -102,4 +103,23 @@ class BooleanOptionType extends AbstractOptionType implements ISearchableConditi return $value1 ? 1 : -1; } + + /** + * @inheritDoc + */ + public function getDisabledOptionNames($value, $enableOptions) { + $options = ArrayUtil::trim(explode(',', $enableOptions)); + $result = []; + + foreach ($options as $item) { + if ($item{0} == '!') { + if ($value) $result[] = $item; + } + else { + if (!$value) $result[] = $item; + } + } + + return $result; + } } diff --git a/wcfsetup/install/files/lib/system/option/IOptionType.class.php b/wcfsetup/install/files/lib/system/option/IOptionType.class.php index 6b32fa1c77..6c9c105e74 100644 --- a/wcfsetup/install/files/lib/system/option/IOptionType.class.php +++ b/wcfsetup/install/files/lib/system/option/IOptionType.class.php @@ -48,7 +48,7 @@ interface IOptionType { public function getCSSClassName(); /** - * Returns true if options supports internationalization . + * Returns true if options supports internationalization. * * @return boolean */ @@ -74,4 +74,14 @@ interface IOptionType { * @return boolean */ public function hideLabelInSearch(); + + /** + * Determines disabled options by given option value. + * + * @param mixed $value + * @param string $enableOptions + * @return string[] + * @since 5.2 + */ + public function getDisabledOptionNames($value, $enableOptions); } diff --git a/wcfsetup/install/files/lib/system/option/RadioButtonOptionType.class.php b/wcfsetup/install/files/lib/system/option/RadioButtonOptionType.class.php index 5e60c1b05c..9acc7c532c 100644 --- a/wcfsetup/install/files/lib/system/option/RadioButtonOptionType.class.php +++ b/wcfsetup/install/files/lib/system/option/RadioButtonOptionType.class.php @@ -6,6 +6,7 @@ use wcf\data\user\UserList; use wcf\system\database\util\PreparedStatementConditionBuilder; use wcf\system\exception\UserInputException; use wcf\system\WCF; +use wcf\util\ArrayUtil; use wcf\util\StringUtil; /** @@ -128,4 +129,44 @@ class RadioButtonOptionType extends AbstractOptionType implements ISearchableCon public function getCSSClassName() { return 'checkboxList'; } + + /** + * @inheritDoc + */ + public function getDisabledOptionNames($value, $enableOptions) { + $valueToOptions = explode("\n", StringUtil::trim(StringUtil::unifyNewlines($enableOptions))); + + $i = 0; + foreach ($valueToOptions as $valueToOption) { + if (mb_strpos($valueToOption, ':') !== false) { + $optionData = explode(':', $valueToOption); + $key = array_shift($optionData); + $enableOptionValues = implode(':', $optionData); + } + else { + $key = $i; + $enableOptionValues = $valueToOption; + } + + if ($key == $value) { + $options = ArrayUtil::trim(explode(',', $enableOptionValues)); + $result = []; + + foreach ($options as $item) { + if ($item{0} == '!') { + $result[] = $item; + } + else { + $result[] = $item; + } + } + + return $result; + } + + $i++; + } + + return []; + } } -- 2.20.1