Add possibility to copy user groups
authorMatthias Schmidt <gravatronics@live.com>
Sun, 15 Jun 2014 18:03:13 +0000 (20:03 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Sun, 15 Jun 2014 18:03:13 +0000 (20:03 +0200)
wcfsetup/install/files/acp/js/WCF.ACP.js
wcfsetup/install/files/acp/templates/userGroupAdd.tpl
wcfsetup/install/files/lib/data/user/group/UserGroupAction.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 845c5b5c96bf17143ed06050ff936e1c838193c5..549baef027c5a79a1e8807fb514c99ef5633bd4a 100644 (file)
@@ -2090,6 +2090,64 @@ WCF.ACP.User.BanHandler = {
        }
 };
 
+/**
+ * Namespace for user group management.
+ */
+WCF.ACP.User.Group = { };
+
+/**
+ * Handles copying user groups.
+ */
+WCF.ACP.User.Group.Copy = Class.extend({
+       /**
+        * id of the copied group
+        * @var integer
+        */
+       _groupID: 0,
+       
+       /**
+        * Initializes a new instance of WCF.ACP.User.Group.Copy.
+        * 
+        * @param       integer         groupID
+        */
+       init: function(groupID) {
+               this._groupID = groupID;
+               
+               $('.jsButtonUserGroupCopy').click($.proxy(this._click, this));
+       },
+       
+       /**
+        * Handles clicking on a 'copy user group' button.
+        */
+       _click: function() {
+               var $template = $('<div />');
+               $template.append($('<dl class="wide marginTop"><dt /><dd><label><input type="checkbox" id="copyMembers" value="1" /> ' + WCF.Language.get('wcf.acp.group.copy.copyMembers') + '</label><small>' + WCF.Language.get('wcf.acp.group.copy.copyMembers.description') + '</small></dd></dl>'));
+               $template.append($('<dl class="wide marginTopSmall"><dt /><dd><label><input type="checkbox" id="copyUserGroupOptions" value="1" /> ' + WCF.Language.get('wcf.acp.group.copy.copyUserGroupOptions') + '</label><small>' + WCF.Language.get('wcf.acp.group.copy.copyUserGroupOptions.description') + '</small></dd></dl>'));
+               $template.append($('<dl class="wide marginTopSmall"><dt /><dd><label><input type="checkbox" id="copyACLOptions" value="1" /> ' + WCF.Language.get('wcf.acp.group.copy.copyACLOptions') + '</label><small>' + WCF.Language.get('wcf.acp.group.copy.copyACLOptions.description') + '</small></dd></dl>'));
+               
+               WCF.System.Confirmation.show(WCF.Language.get('wcf.acp.group.copy.confirmMessage'), $.proxy(function(action) {
+                       if (action === 'confirm') {
+                               new WCF.Action.Proxy({
+                                       autoSend: true,
+                                       data: {
+                                               actionName: 'copy',
+                                               className: 'wcf\\data\\user\\group\\UserGroupAction',
+                                               objectIDs: [ this._groupID ],
+                                               parameters: {
+                                                       copyACLOptions: $('#copyACLOptions').is(':checked'),
+                                                       copyMembers: $('#copyMembers').is(':checked'),
+                                                       copyUserGroupOptions: $('#copyUserGroupOptions').is(':checked')
+                                               }
+                                       },
+                                       success: function(data) {
+                                               window.location = data.returnValues.redirectURL;
+                                       }
+                               });
+                       }
+               }, this), '', $template);
+       }
+});
+
 /**
  * Generic implementation to enable users.
  */
index 7ec89d36541f335be6eb10b8bda26c4ba7ade448..293f02bf7896dbc179b077ef42f49dfe83ee1a82 100644 (file)
@@ -4,7 +4,22 @@
        //<![CDATA[
        $(function() {
                WCF.TabMenu.init();
+               
                new WCF.Option.Handler();
+               
+               {if $action == 'edit' && $group->groupType == 4 && $__wcf->session->getPermission('admin.user.canAddGroup')}
+                       WCF.Language.addObject({
+                               'wcf.acp.group.copy.confirmMessage': '{lang}wcf.acp.group.copy.confirmMessage{/lang}',
+                               'wcf.acp.group.copy.copyACLOptions': '{lang}wcf.acp.group.copy.copyACLOptions{/lang}',
+                               'wcf.acp.group.copy.copyACLOptions.description': '{lang}wcf.acp.group.copy.copyACLOptions.description{/lang}',
+                               'wcf.acp.group.copy.copyMembers': '{lang}wcf.acp.group.copy.copyMembers{/lang}',
+                               'wcf.acp.group.copy.copyMembers.description': '{lang}wcf.acp.group.copy.copyMembers.description{/lang}',
+                               'wcf.acp.group.copy.copyUserGroupOptions': '{lang}wcf.acp.group.copy.copyUserGroupOptions{/lang}',
+                               'wcf.acp.group.copy.copyUserGroupOptions.description': '{lang}wcf.acp.group.copy.copyUserGroupOptions.description{/lang}'
+                       });
+                       
+                       new WCF.ACP.User.Group.Copy({@$groupID});
+               {/if}
        });
        //]]>
 </script>
 <div class="contentNavigation">
        <nav>
                <ul>
-                       {if $action == 'edit' && $availableUserGroups|count > 1}
-                               <li class="dropdown">
-                                       <a class="button dropdownToggle"><span class="icon icon16 icon-sort"></span> <span>{lang}wcf.acp.group.button.choose{/lang}</span></a>
-                                       <div class="dropdownMenu">
-                                               <ul class="scrollableDropdownMenu">
-                                                       {foreach from=$availableUserGroups item='availableUserGroup'}
-                                                               <li{if $availableUserGroup->groupID == $groupID} class="active"{/if}><a href="{link controller='UserGroupEdit' id=$availableUserGroup->groupID}{/link}">{$availableUserGroup->getName()}</a></li>
-                                                       {/foreach}
-                                               </ul>
-                                       </div>
-                               </li>
+                       {if $action == 'edit'}
+                               {if $availableUserGroups|count > 1}
+                                       <li class="dropdown">
+                                               <a class="button dropdownToggle"><span class="icon icon16 icon-sort"></span> <span>{lang}wcf.acp.group.button.choose{/lang}</span></a>
+                                               <div class="dropdownMenu">
+                                                       <ul class="scrollableDropdownMenu">
+                                                               {foreach from=$availableUserGroups item='availableUserGroup'}
+                                                                       <li{if $availableUserGroup->groupID == $groupID} class="active"{/if}><a href="{link controller='UserGroupEdit' id=$availableUserGroup->groupID}{/link}">{$availableUserGroup->getName()}</a></li>
+                                                               {/foreach}
+                                                       </ul>
+                                               </div>
+                                       </li>
+                               {/if}
+                               
+                               {if $__wcf->session->getPermission('admin.user.canAddGroup') && $group->groupType == 4}
+                                       <li><a class="jsButtonUserGroupCopy button"><span class="icon icon16 icon-copy"></span> <span>{lang}wcf.acp.group.button.copy{/lang}</span></a></li>
+                               {/if}
                        {/if}
                        
                        <li><a href="{link controller='UserGroupList'}{/link}" class="button"><span class="icon icon16 icon-list"></span> <span>{lang}wcf.acp.menu.link.group.list{/lang}</span></a></li>
index 42577493d7899f79b2f30200119c974a56a4dcb7..7d0cf3c3eecea7f4adcd2177352150f4edb13f42 100644 (file)
@@ -1,6 +1,12 @@
 <?php
 namespace wcf\data\user\group;
 use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\cache\CacheHandler;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\language\LanguageFactory;
+use wcf\system\request\LinkHandler;
+use wcf\system\user\storage\UserStorageHandler;
+use wcf\system\WCF;
 
 /**
  * Executes user group-related actions.
@@ -18,6 +24,12 @@ class UserGroupAction extends AbstractDatabaseObjectAction {
         */
        public $className = 'wcf\data\user\group\UserGroupEditor';
        
+       /**
+        * editor object for the copied user group
+        * @var \wcf\data\user\group\UserGroupEditor
+        */
+       public $groupEditor = null;
+       
        /**
         * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsCreate
         */
@@ -36,7 +48,7 @@ class UserGroupAction extends AbstractDatabaseObjectAction {
        /**
         * @see \wcf\data\AbstractDatabaseObjectAction::$requireACP
         */
-       protected $requireACP = array('create', 'delete', 'update');
+       protected $requireACP = array('copy', 'create', 'delete', 'update');
        
        /**
         * @see \wcf\data\AbstractDatabaseObjectAction::create()
@@ -65,4 +77,140 @@ class UserGroupAction extends AbstractDatabaseObjectAction {
                        $object->updateGroupOptions($this->parameters['options']);
                }
        }
+       
+       /**
+        * Validates the 'copy' action.
+        */
+       public function validateCopy() {
+               WCF::getSession()->checkPermissions(array(
+                       'admin.user.canAddGroup',
+                       'admin.user.canEditGroup'
+               ));
+               
+               $this->readBoolean('copyACLOptions');
+               $this->readBoolean('copyMembers');
+               $this->readBoolean('copyUserGroupOptions');
+               
+               $this->groupEditor = $this->getSingleObject();
+               if (!$this->groupEditor->isAccessible() || $this->groupEditor->groupType != UserGroup::OTHER) {
+                       throw new PermissionDeniedException();
+               }
+       }
+       
+       /**
+        * Copies a user group.
+        */
+       public function copy() {
+               // fetch user group option values
+               if ($this->parameters['copyUserGroupOptions']) {
+                       $sql = "SELECT  optionID, optionValue
+                               FROM    wcf".WCF_N."_user_group_option_value
+                               WHERE   groupID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->groupEditor->groupID));
+               }
+               else {
+                       $sql = "SELECT  optionID, defaultValue AS optionValue
+                               FROM    wcf".WCF_N."_user_group_option";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute();
+               }
+               
+               $optionValues = array();
+               while ($row = $statement->fetchArray()) {
+                       $optionValues[$row['optionID']] = $row['optionValue'];
+               }
+               
+               $groupAction = new UserGroupAction(array(), 'create', array(
+                       'data' => array(
+                               'groupName' => $this->groupEditor->groupName,
+                               'groupDescription' => $this->groupEditor->groupDescription,
+                               'priority' => $this->groupEditor->priority,
+                               'userOnlineMarking' => $this->groupEditor->userOnlineMarking,
+                               'showOnTeamPage' => $this->groupEditor->showOnTeamPage
+                       ),
+                       'options' => $optionValues
+               ));
+               $returnValues = $groupAction->executeAction();
+               $group = $returnValues['returnValues'];
+               $groupEditor = new UserGroupEditor($group);
+               
+               // update group name
+               $groupName = $this->groupEditor->groupName;
+               if (preg_match('~^wcf\.acp\.group\.group\d+$~', $this->groupEditor->groupName)) {
+                       $groupName = 'wcf.acp.group.group'.$group->groupID;
+                       
+                       // create group name language item
+                       $sql = "INSERT INTO     wcf".WCF_N."_language_item
+                                               (languageID, languageItem, languageItemValue, languageItemOriginIsSystem, languageCategoryID, packageID)
+                               SELECT          languageID, '".$groupName."', CONCAT(languageItemValue, ' (2)'), 0, languageCategoryID, packageID
+                               FROM            wcf".WCF_N."_language_item
+                               WHERE           languageItem = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->groupEditor->groupName));
+               }
+               else {
+                       $groupName .= ' (2)';
+               }
+               
+               // update group name
+               $groupDescription = $this->groupEditor->groupName;
+               if (preg_match('~^wcf\.acp\.group\.groupDescription\d+$~', $this->groupEditor->groupDescription)) {
+                       $groupDescription = 'wcf.acp.group.groupDescription'.$group->groupID;
+                       
+                       // create group name language item
+                       $sql = "INSERT INTO     wcf".WCF_N."_language_item
+                                               (languageID, languageItem, languageItemValue, languageItemOriginIsSystem, languageCategoryID, packageID)
+                               SELECT          languageID, '".$groupDescription."', languageItemValue, 0, languageCategoryID, packageID
+                               FROM            wcf".WCF_N."_language_item
+                               WHERE           languageItem = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->groupEditor->groupDescription));
+               }
+               
+               $groupEditor->update(array(
+                       'groupDescription' => $groupDescription,
+                       'groupName' => $groupName
+               ));
+               
+               // copy members
+               if ($this->parameters['copyMembers']) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_user_to_group
+                                               (userID, groupID)
+                               SELECT          userID, ".$group->groupID."
+                               FROM            wcf".WCF_N."_user_to_group
+                               WHERE           groupID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->groupEditor->groupID));
+               }
+               
+               // copy acl options
+               if ($this->parameters['copyACLOptions']) {
+                       $sql = "INSERT INTO     wcf".WCF_N."_acl_option_to_group
+                                               (optionID, objectID, groupID, optionValue)
+                               SELECT          optionID, objectID, ".$group->groupID.", optionValue
+                               FROM            wcf".WCF_N."_acl_option_to_group
+                               WHERE           groupID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($this->groupEditor->groupID));
+                       
+                       // it is likely that applications or plugins use caches
+                       // for acl option values like for the labels which have
+                       // to be renewed after copying the acl options; because
+                       // there is no other way to delete these caches, we simply
+                       // delete all caches
+                       CacheHandler::getInstance()->flushAll();
+               }
+               
+               // reset language cache
+               LanguageFactory::getInstance()->deleteLanguageCache();
+               
+               UserGroupEditor::resetCache();
+               
+               return array(
+                       'redirectURL' => LinkHandler::getInstance()->getLink('UserGroupEdit', array(
+                               'id' => $group->groupID
+                       ))
+               );
+       }
 }
index 3ba64121781c24bc70201b88269c6940525fdd7d..e8a9cf58aacc16e94d51d73e537882dc598c9669 100644 (file)
                <item name="wcf.acp.group.option.user.profile.canReportContent"><![CDATA[Kann Inhalte melden]]></item>
                <item name="wcf.acp.group.option.admin.captcha.canManageCaptchaQuestion"><![CDATA[Kann Captcha-Fragen verwalten]]></item>
                <item name="wcf.acp.group.category.admin.display.captcha"><![CDATA[Captchas]]></item>
+               <item name="wcf.acp.group.button.copy"><![CDATA[Benutzergruppe kopieren]]></item>
+               <item name="wcf.acp.group.copy.confirmMessage"><![CDATA[Wollen Sie diese Benutzergruppe wirklich kopieren?]]></item>
+               <item name="wcf.acp.group.copy.copyACLOptions"><![CDATA[Objekt-Berechtigungen kopieren]]></item>
+               <item name="wcf.acp.group.copy.copyACLOptions.description"><![CDATA[Berechtigungen, die für bestimmte Objekte wie Labelgruppen gesetzt wurden, werden auch für die neue Benutzergruppe übernommen.]]></item>
+               <item name="wcf.acp.group.copy.copyMembers"><![CDATA[Mitglieder kopieren]]></item>
+               <item name="wcf.acp.group.copy.copyMembers.description"><![CDATA[Mitglieder der kopierten Benutzergruppe werden automatisch auch Mitglied der neuen Benutzergruppe sein.]]></item>
+               <item name="wcf.acp.group.copy.copyUserGroupOptions"><![CDATA[Berechtigungen kopieren]]></item>
+               <item name="wcf.acp.group.copy.copyUserGroupOptions.description"><![CDATA[Die neue Benutzergruppe wird die gleichen Berechtigungen besitzen wie die kopierte Benutzergruppe.]]></item>
        </category>
        
        <category name="wcf.acp.index">
index bf4341374751565d28b7f1f9bb5c05382c5f81f6..70a2cdaeb14b97cf4a6ece05a43247862d40bdd2 100644 (file)
@@ -433,6 +433,14 @@ Examples for medium ID detection:
                <item name="wcf.acp.group.option.user.profile.canReportContent"><![CDATA[Can report content]]></item>
                <item name="wcf.acp.group.option.admin.captcha.canManageCaptchaQuestion"><![CDATA[Can manage captcha questions]]></item>
                <item name="wcf.acp.group.category.admin.display.captcha"><![CDATA[Captchas]]></item>
+               <item name="wcf.acp.group.button.copy"><![CDATA[Copy User Group]]></item>
+               <item name="wcf.acp.group.copy.confirmMessage"><![CDATA[Do you really want to copy this user group?]]></item>
+               <item name="wcf.acp.group.copy.copyACLOptions"><![CDATA[Copy Object Permissions]]></item>
+               <item name="wcf.acp.group.copy.copyACLOptions.description"><![CDATA[Permissions set for certain objects like for label groups will also be set for the new user group.]]></item>
+               <item name="wcf.acp.group.copy.copyMembers"><![CDATA[Copy Members]]></item>
+               <item name="wcf.acp.group.copy.copyMembers.description"><![CDATA[Members of the copied user group will automatically be members of the new user group.]]></item>
+               <item name="wcf.acp.group.copy.copyUserGroupOptions"><![CDATA[Copy Permissions]]></item>
+               <item name="wcf.acp.group.copy.copyUserGroupOptions.description"><![CDATA[The new user group will have the same permissions as the copied user group.]]></item>
        </category>
        
        <category name="wcf.acp.index">