Merge branch '5.3'
authorTim Düsterhus <duesterhus@woltlab.com>
Mon, 12 Apr 2021 10:55:11 +0000 (12:55 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Mon, 12 Apr 2021 10:55:11 +0000 (12:55 +0200)
1  2 
com.woltlab.wcf/mediaProvider.xml
wcfsetup/install/files/acp/templates/userOptionList.tpl
wcfsetup/install/files/acp/templates/userSearch.tpl
wcfsetup/install/files/lib/data/user/group/UserGroupEditor.class.php

Simple merge
index 717a9282c6b0de7dd02967f30f0e39a53885bc88,d56e678135e33755dd347096eca94224870076e4..85999a84bcd7d19bbdb165754fd0f7c9b6facf3a
@@@ -1,9 -1,8 +1,10 @@@
  <?php
 +
  namespace wcf\data\user\group;
 +
  use wcf\data\DatabaseObjectEditor;
  use wcf\data\IEditableCachedObject;
+ use wcf\system\cache\builder\UserGroupAssignmentCacheBuilder;
  use wcf\system\cache\builder\UserGroupCacheBuilder;
  use wcf\system\cache\builder\UserGroupPermissionCacheBuilder;
  use wcf\system\exception\SystemException;
@@@ -12,200 -11,185 +13,203 @@@ use wcf\system\WCF
  
  /**
   * Provides functions to edit user groups.
 - * 
 - * @author    Alexander Ebert
 - * @copyright 2001-2019 WoltLab GmbH
 - * @license   GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 - * @package   WoltLabSuite\Core\Data\User\Group
 - * 
 - * @method    UserGroup       getDecoratedObject()
 - * @mixin     UserGroup
 + *
 + * @author  Alexander Ebert
 + * @copyright   2001-2019 WoltLab GmbH
 + * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 + * @package WoltLabSuite\Core\Data\User\Group
 + *
 + * @method  UserGroup   getDecoratedObject()
 + * @mixin   UserGroup
   */
 -class UserGroupEditor extends DatabaseObjectEditor implements IEditableCachedObject {
 -      /**
 -       * @inheritDoc
 -       */
 -      protected static $baseClass = UserGroup::class;
 -      
 -      /**
 -       * @inheritDoc
 -       * @return      UserGroup
 -       */
 -      public static function create(array $parameters = []) {
 -              /** @var UserGroup $group */
 -              $group = parent::create($parameters);
 -              
 -              // update accessible groups
 -              self::updateAccessibleGroups($group->groupID);
 -              
 -              return $group;
 -      }
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      public static function deleteAll(array $objectIDs = []) {
 -              $returnValue = parent::deleteAll($objectIDs);
 -              
 -              // remove user to group assignments
 -              self::removeGroupAssignments($objectIDs);
 -              
 -              // remove group option values
 -              self::removeOptionValues($objectIDs);
 -              
 -              foreach ($objectIDs as $objectID) {
 -                      self::updateAccessibleGroups($objectID, true);
 -              }
 -              
 -              return $returnValue;
 -      }
 -      
 -      /**
 -       * Removes user to group assignments.
 -       * 
 -       * @param       array           $groupIDs
 -       */
 -      protected static function removeGroupAssignments(array $groupIDs) {
 -              if (empty($groupIDs)) return;
 -              
 -              $sql = "DELETE FROM     wcf".WCF_N."_user_to_group
 -                      WHERE           groupID = ?";
 -              $statement = WCF::getDB()->prepareStatement($sql);
 -              foreach ($groupIDs as $groupID) {
 -                      $statement->execute([$groupID]);
 -              }
 -      }
 -      
 -      /**
 -       * Removes group option values.
 -       * 
 -       * @param       array           $groupIDs
 -       */
 -      protected static function removeOptionValues(array $groupIDs) {
 -              if (empty($groupIDs)) return;
 -              
 -              $sql = "DELETE FROM     wcf".WCF_N."_user_group_option_value
 -                      WHERE           groupID = ?";
 -              $statement = WCF::getDB()->prepareStatement($sql);
 -              foreach ($groupIDs as $groupID) {
 -                      $statement->execute([$groupID]);
 -              }
 -      }
 -      
 -      /**
 -       * Updates group options.
 -       * 
 -       * @param       array           $groupOptions
 -       */
 -      public function updateGroupOptions(array $groupOptions = []) {
 -              WCF::getDB()->beginTransaction();
 -              // delete old group options
 -              $sql = "DELETE FROM     wcf".WCF_N."_user_group_option_value
 -                      WHERE           groupID = ?";
 -              $statement = WCF::getDB()->prepareStatement($sql);
 -              $statement->execute([$this->groupID]);
 -              
 -              // insert new options
 -              $sql = "INSERT INTO     wcf".WCF_N."_user_group_option_value
 -                                      (groupID, optionID, optionValue)
 -                      VALUES          (?, ?, ?)";
 -              $statement = WCF::getDB()->prepareStatement($sql);
 -              foreach ($groupOptions as $id => $value) {
 -                      $statement->execute([$this->groupID, $id, $value]);
 -              }
 -              WCF::getDB()->commitTransaction();
 -      }
 -      
 -      /**
 -       * Updates the value from the accessiblegroups option.
 -       * 
 -       * @param       integer         $groupID        this group is added or deleted in the value
 -       * @param       boolean         $delete         flag for group deletion
 -       * @throws      SystemException
 -       */
 -      protected static function updateAccessibleGroups($groupID, $delete = false) {
 -              $sql = "SELECT  optionID
 -                      FROM    wcf".WCF_N."_user_group_option
 -                      WHERE   optionName = ?";
 -              $statement = WCF::getDB()->prepareStatement($sql);
 -              $statement->execute(['admin.user.accessibleGroups']);
 -              $optionID = $statement->fetchSingleColumn();
 -              
 -              if (!$optionID) throw new SystemException("Unable to find 'admin.user.accessibleGroups' user option");
 -              
 -              $ownerGroupID = UserGroup::getOwnerGroupID();
 -              
 -              $userGroupList = new UserGroupList();
 -              $userGroupList->getConditionBuilder()->add('user_group.groupID <> ?', [$groupID]);
 -              if ($ownerGroupID) $userGroupList->getConditionBuilder()->add('user_group.groupID <> ?', [$ownerGroupID]);
 -              $userGroupList->readObjects();
 -              $groupIDs = [];
 -              foreach ($userGroupList as $userGroup) {
 -                      $groupIDs[] = $userGroup->groupID;
 -              }
 -              
 -              $sql = "UPDATE  wcf".WCF_N."_user_group_option_value
 -                      SET     optionValue = ?
 -                      WHERE           groupID = ?
 -                              AND     optionID = ?";
 -              $updateStatement = WCF::getDB()->prepareStatement($sql);
 -              
 -              $sql = "SELECT          groupID, optionValue
 -                      FROM            wcf".WCF_N."_user_group_option_value
 -                      WHERE           optionID = ?";
 -              $statement = WCF::getDB()->prepareStatement($sql);
 -              $statement->execute([$optionID]);
 -              while ($row = $statement->fetchArray()) {
 -                      $valueIDs = array_filter(explode(',', $row['optionValue']), function ($groupID) use ($ownerGroupID) {
 -                              return $groupID != $ownerGroupID;
 -                      });
 -                      
 -                      if ($delete) {
 -                              $valueIDs = array_filter($valueIDs, function ($item) use ($groupID) {
 -                                      return $item != $groupID;
 -                              });
 -                      }
 -                      else {
 -                              if (count(array_diff($groupIDs, $valueIDs)) == 0) {
 -                                      $valueIDs[] = $groupID;
 -                              }
 -                      }
 -                      
 -                      if ($row['groupID'] == $ownerGroupID) {
 -                              $valueIDs[] = $ownerGroupID;
 -                      }
 -                      
 -                      $updateStatement->execute([implode(',', $valueIDs), $row['groupID'], $optionID]);
 -              }
 -      }
 -      
 -      /**
 -       * @inheritDoc
 -       */
 -      public static function resetCache() {
 -              // clear cache
 -              UserGroupCacheBuilder::getInstance()->reset();
 -              UserGroupPermissionCacheBuilder::getInstance()->reset();
 -
 -              // https://github.com/WoltLab/WCF/issues/4045
 -              UserGroupAssignmentCacheBuilder::getInstance()->reset();
 -              
 -              // clear sessions
 -              SessionHandler::resetSessions();
 -      }
 +class UserGroupEditor extends DatabaseObjectEditor implements IEditableCachedObject
 +{
 +    /**
 +     * @inheritDoc
 +     */
 +    protected static $baseClass = UserGroup::class;
 +
 +    /**
 +     * @inheritDoc
 +     * @return  UserGroup
 +     */
 +    public static function create(array $parameters = [])
 +    {
 +        /** @var UserGroup $group */
 +        $group = parent::create($parameters);
 +
 +        // update accessible groups
 +        self::updateAccessibleGroups($group->groupID);
 +
 +        return $group;
 +    }
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    public static function deleteAll(array $objectIDs = [])
 +    {
 +        $returnValue = parent::deleteAll($objectIDs);
 +
 +        // remove user to group assignments
 +        self::removeGroupAssignments($objectIDs);
 +
 +        // remove group option values
 +        self::removeOptionValues($objectIDs);
 +
 +        foreach ($objectIDs as $objectID) {
 +            self::updateAccessibleGroups($objectID, true);
 +        }
 +
 +        return $returnValue;
 +    }
 +
 +    /**
 +     * Removes user to group assignments.
 +     *
 +     * @param array $groupIDs
 +     */
 +    protected static function removeGroupAssignments(array $groupIDs)
 +    {
 +        if (empty($groupIDs)) {
 +            return;
 +        }
 +
 +        $sql = "DELETE FROM wcf" . WCF_N . "_user_to_group
 +                WHERE       groupID = ?";
 +        $statement = WCF::getDB()->prepareStatement($sql);
 +        foreach ($groupIDs as $groupID) {
 +            $statement->execute([$groupID]);
 +        }
 +    }
 +
 +    /**
 +     * Removes group option values.
 +     *
 +     * @param array $groupIDs
 +     */
 +    protected static function removeOptionValues(array $groupIDs)
 +    {
 +        if (empty($groupIDs)) {
 +            return;
 +        }
 +
 +        $sql = "DELETE FROM wcf" . WCF_N . "_user_group_option_value
 +                WHERE       groupID = ?";
 +        $statement = WCF::getDB()->prepareStatement($sql);
 +        foreach ($groupIDs as $groupID) {
 +            $statement->execute([$groupID]);
 +        }
 +    }
 +
 +    /**
 +     * Updates group options.
 +     *
 +     * @param array $groupOptions
 +     */
 +    public function updateGroupOptions(array $groupOptions = [])
 +    {
 +        WCF::getDB()->beginTransaction();
 +        // delete old group options
 +        $sql = "DELETE FROM wcf" . WCF_N . "_user_group_option_value
 +                WHERE       groupID = ?";
 +        $statement = WCF::getDB()->prepareStatement($sql);
 +        $statement->execute([$this->groupID]);
 +
 +        // insert new options
 +        $sql = "INSERT INTO wcf" . WCF_N . "_user_group_option_value
 +                            (groupID, optionID, optionValue)
 +                VALUES      (?, ?, ?)";
 +        $statement = WCF::getDB()->prepareStatement($sql);
 +        foreach ($groupOptions as $id => $value) {
 +            $statement->execute([$this->groupID, $id, $value]);
 +        }
 +        WCF::getDB()->commitTransaction();
 +    }
 +
 +    /**
 +     * Updates the value from the accessiblegroups option.
 +     *
 +     * @param int $groupID this group is added or deleted in the value
 +     * @param bool $delete flag for group deletion
 +     * @throws  SystemException
 +     */
 +    protected static function updateAccessibleGroups($groupID, $delete = false)
 +    {
 +        $sql = "SELECT  optionID
 +                FROM    wcf" . WCF_N . "_user_group_option
 +                WHERE   optionName = ?";
 +        $statement = WCF::getDB()->prepareStatement($sql);
 +        $statement->execute(['admin.user.accessibleGroups']);
 +        $optionID = $statement->fetchSingleColumn();
 +
 +        if (!$optionID) {
 +            throw new SystemException("Unable to find 'admin.user.accessibleGroups' user option");
 +        }
 +
 +        $ownerGroupID = UserGroup::getOwnerGroupID();
 +
 +        $userGroupList = new UserGroupList();
 +        $userGroupList->getConditionBuilder()->add('user_group.groupID <> ?', [$groupID]);
 +        if ($ownerGroupID) {
 +            $userGroupList->getConditionBuilder()->add('user_group.groupID <> ?', [$ownerGroupID]);
 +        }
 +        $userGroupList->readObjects();
 +        $groupIDs = [];
 +        foreach ($userGroupList as $userGroup) {
 +            $groupIDs[] = $userGroup->groupID;
 +        }
 +
 +        $sql = "UPDATE  wcf" . WCF_N . "_user_group_option_value
 +                SET     optionValue = ?
 +                WHERE   groupID = ?
 +                    AND optionID = ?";
 +        $updateStatement = WCF::getDB()->prepareStatement($sql);
 +
 +        $sql = "SELECT  groupID, optionValue
 +                FROM    wcf" . WCF_N . "_user_group_option_value
 +                WHERE   optionID = ?";
 +        $statement = WCF::getDB()->prepareStatement($sql);
 +        $statement->execute([$optionID]);
 +        while ($row = $statement->fetchArray()) {
 +            $valueIDs = \array_filter(
 +                \explode(',', $row['optionValue']),
 +                static function ($groupID) use ($ownerGroupID) {
 +                    return $groupID != $ownerGroupID;
 +                }
 +            );
 +
 +            if ($delete) {
 +                $valueIDs = \array_filter($valueIDs, static function ($item) use ($groupID) {
 +                    return $item != $groupID;
 +                });
 +            } else {
 +                if (\count(\array_diff($groupIDs, $valueIDs)) == 0) {
 +                    $valueIDs[] = $groupID;
 +                }
 +            }
 +
 +            if ($row['groupID'] == $ownerGroupID) {
 +                $valueIDs[] = $ownerGroupID;
 +            }
 +
 +            $updateStatement->execute([\implode(',', $valueIDs), $row['groupID'], $optionID]);
 +        }
 +    }
 +
 +    /**
 +     * @inheritDoc
 +     */
 +    public static function resetCache()
 +    {
 +        // Clear group cache.
 +        UserGroupCacheBuilder::getInstance()->reset();
 +        UserGroupPermissionCacheBuilder::getInstance()->reset();
 +
++        // https://github.com/WoltLab/WCF/issues/4045
++        UserGroupAssignmentCacheBuilder::getInstance()->reset();
++
 +        // Clear cached group assignments.
 +        UserStorageHandler::getInstance()->resetAll('groupIDs');
 +    }
  }