…and replace the current user bulk processing form with the new system.
<definitionname>com.woltlab.wcf.payment.type</definitionname>
<classname><![CDATA[wcf\system\payment\type\PaidSubscriptionPaymentType]]></classname>
</type>
+
+ <!-- bulk processable objects -->
+ <type>
+ <name>com.woltlab.wcf.bulkProcessing.user</name>
+ <definitionname>com.woltlab.wcf.bulkProcessableObject</definitionname>
+ <classname><![CDATA[wcf\system\bulk\processing\user\UserBulkProcessableObjectType]]></classname>
+ </type>
+ <!-- /bulk processable objects -->
+
+ <!-- user bulk processing actions -->
+ <type>
+ <name>com.woltlab.wcf.delete</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.action</definitionname>
+ <classname><![CDATA[wcf\system\bulk\processing\user\DeleteUserBulkProcessingAction]]></classname>
+ <action>delete</action>
+ <permissions>admin.user.canDeleteUser</permissions>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.assignToUserGroups</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.action</definitionname>
+ <classname><![CDATA[wcf\system\bulk\processing\user\AssignToUserGroupsUserBulkProcessingAction]]></classname>
+ <action>assignToUserGroups</action>
+ <permissions>admin.user.canEditUser</permissions>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.removeFromUserGroups</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.action</definitionname>
+ <classname><![CDATA[wcf\system\bulk\processing\user\RemoveFromUserGroupsUserBulkProcessingAction]]></classname>
+ <action>removeFromUserGroups</action>
+ <permissions>admin.user.canEditUser</permissions>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.sendMail</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.action</definitionname>
+ <classname><![CDATA[wcf\system\bulk\processing\user\SendMailUserBulkProcessingAction]]></classname>
+ <action>sendMail</action>
+ <permissions>admin.user.canMailUser</permissions>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.exportMailAddress</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.action</definitionname>
+ <classname><![CDATA[wcf\system\bulk\processing\user\ExportMailAddressUserBulkProcessingAction]]></classname>
+ <action>exportMailAddress</action>
+ <permissions>admin.user.canMailUser</permissions>
+ </type>
+ <!-- /user bulk processing actions -->
+
+ <!-- user bulk processing conditions -->
+ <type>
+ <name>com.woltlab.wcf.username</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserUsernameCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.email</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserEmailCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.userGroup</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserGroupCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.languages</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserLanguageCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.registrationDate</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserRegistrationDateCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.registrationDateInterval</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserRegistrationDateIntervalCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.lastActivityTime</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserTimestampPropertyCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ <propertyname>lastActivityTime</propertyname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.avatar</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserAvatarCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.state</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserStateCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.activityPoints</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserIntegerPropertyCondition]]></classname>
+ <conditiongroup>contents</conditiongroup>
+ <propertyname>activityPoints</propertyname>
+ <minvalue>0</minvalue>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.likesReceived</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserIntegerPropertyCondition]]></classname>
+ <conditiongroup>contents</conditiongroup>
+ <propertyname>likesReceived</propertyname>
+ <minvalue>0</minvalue>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.userOptions</name>
+ <definitionname>com.woltlab.wcf.bulkProcessing.user.condition</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserOptionsCondition]]></classname>
+ <conditiongroup>userOptions</conditiongroup>
+ </type>
+ <!-- /user bulk processing conditions -->
</import>
</data>
<name>com.woltlab.wcf.payment.type</name>
<interfacename><![CDATA[wcf\system\payment\type\IPaymentType]]></interfacename>
</definition>
+
+ <definition>
+ <name>com.woltlab.wcf.bulkProcessableObject</name>
+ <interfacename><![CDATA[wcf\system\bulk\processing\IBulkProcessableObjectType]]></interfacename>
+ </definition>
+
+ <definition>
+ <name>com.woltlab.wcf.bulkProcessing.user.condition</name>
+ <interfacename><![CDATA[wcf\system\condition\IObjectListCondition]]></interfacename>
+ </definition>
+
+ <definition>
+ <name>com.woltlab.wcf.bulkProcessing.user.action</name>
+ <interfacename><![CDATA[wcf\system\bulk\processing\IBulkProcessingAction]]></interfacename>
+ </definition>
</import>
<delete>
--- /dev/null
+{include file='header' pageTitle=$objectType->getProcessor()->getLanguageItemPrefix()}
+
+<script data-relocate="true">
+ require(['WoltLab/WCF/UI/TabMenu'], function(UITabMenu) {
+ UITabMenu.setup();
+
+ function toggleActionOptions(event) {
+ var actionName = event.currentTarget.getAttribute('value');
+ var actionSettings = document.getElementsByClassName('jsBulkProcessingActionSettings');
+ for (var i = 0, length = actionSettings.length; i < length; i++) {
+ var settings = actionSettings[i];
+
+ if (settings.getAttribute('data-action') === actionName) {
+ settings.style.removeProperty('display');
+ }
+ else {
+ settings.style.setProperty('display', 'none');
+ }
+ }
+ };
+
+ var actions = document.querySelectorAll('input[name=action]');
+ for (var i = 0, length = actions.length; i < length; i++) {
+ actions[i].addEventListener('change', toggleActionOptions);
+ }
+ });
+</script>
+
+<header class="boxHeadline">
+ <h1>{lang}{$objectType->getProcessor()->getLanguageItemPrefix()}{/lang}</h1>
+</header>
+
+{include file='formError'}
+
+<p class="warning">{hascontent}{content}{lang __optional=true}{$objectType->getProcessor()->getLanguageItemPrefix()}.warning{/lang}{/content}{hascontentelse}{lang}wcf.global.bulkProcessing.warning{/lang}{/hascontent}</p>
+
+{if $success|isset}
+ <p class="success">{lang}{$objectType->getProcessor()->getLanguageItemPrefix()}.success{/lang}</p>
+{/if}
+
+<form method="post" action="{link controller=$controller}{/link}">
+ <div class="container containerPadding marginTop">
+ <fieldset>
+ <legend>{lang}{$objectType->getProcessor()->getLanguageItemPrefix()}.action{/lang}</legend>
+
+ <dl>
+ <dt></dt>
+ <dd>
+ {foreach from=$actions item=actionObjectType}
+ <label><input type="radio" name="action" value="{@$actionObjectType->action}" {if $actionObjectType->action == $action}checked="checked" {/if}/> {lang}{$objectType->getProcessor()->getLanguageItemPrefix()}.{@$actionObjectType->action}{/lang}</label>
+ {/foreach}
+
+ {if $errorField == 'action'}
+ <small class="innerError">
+ {lang}wcf.global.form.error.{@$errorType}{/lang}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+ </fieldset>
+
+ {foreach from=$actions item=actionObjectType}
+ {if $actionObjectType->getProcessor()->getHTML()}
+ <fieldset class="jsBulkProcessingActionSettings" data-action="{@$actionObjectType->action}" {if $actionObjectType->action != $action}style="display: none;"{/if}>
+ <legend>{lang}{$objectType->getProcessor()->getLanguageItemPrefix()}.{@$actionObjectType->action}{/lang}</legend>
+
+ {@$actionObjectType->getProcessor()->getHTML()}
+ </fieldset>
+ {/if}
+ {/foreach}
+ </div>
+
+ <header class="boxHeadline boxSubHeadline">
+ <h2>{lang}{$objectType->getProcessor()->getLanguageItemPrefix()}.conditions{/lang}</h2>
+ {hascontent}<small>{content}{lang __optional=true}{$objectType->getProcessor()->getLanguageItemPrefix()}.conditions.descriptions{/lang}{/content}</small>{/hascontent}
+ </header>
+
+ {@$objectType->getProcessor()->getConditionHTML()}
+
+ <div class="formSubmit">
+ <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
+ {@SECURITY_TOKEN_INPUT_TAG}
+ </div>
+</form>
+
+{include file='footer'}
--- /dev/null
+<dl>
+ <dt><label>{lang}wcf.acp.user.exportEmailAddress.fileType{/lang}</label></dt>
+ <dd>
+ <label><input type="radio" name="fileType" value="csv" {if $fileType == 'csv'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.csv{/lang}</label>
+ <label><input type="radio" name="fileType" value="xml" {if $fileType == 'xml'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.xml{/lang}</label>
+ </dd>
+</dl>
+
+<dl id="separatorDiv"{if $fileType == 'xml'} style="display: none;"{/if}>
+ <dt><label for="separator">{lang}wcf.acp.user.exportEmailAddress.separator{/lang}</label></dt>
+ <dd>
+ <input type="text" id="separator" name="separator" value="{$separator}" class="medium" />
+ </dd>
+</dl>
+
+<dl id="textSeparatorDiv"{if $fileType == 'xml'} style="display: none;"{/if}>
+ <dt><label for="textSeparator">{lang}wcf.acp.user.exportEmailAddress.textSeparator{/lang}</label></dt>
+ <dd>
+ <input type="text" id="textSeparator" name="textSeparator" value="{$textSeparator}" class="medium" />
+ </dd>
+</dl>
+
+<script data-relocate="true">
+ function toggleExportOptions(event) {
+ var fileType = event.currentTarget.getAttribute('value');
+ if (fileType === 'csv') {
+ document.getElementById('separatorDiv').style.removeProperty('display');
+ document.getElementById('textSeparatorDiv').style.removeProperty('display');
+ }
+ else {
+ document.getElementById('separatorDiv').style.setProperty('display', 'none');
+ document.getElementById('textSeparatorDiv').style.setProperty('display', 'none');
+ }
+ };
+
+ var fileTypes = document.querySelectorAll('input[name=fileType]');
+ for (var i = 0, length = fileTypes.length; i < length; i++) {
+ fileTypes[i].addEventListener('change', toggleExportOptions);
+ }
+</script>
--- /dev/null
+<dl{if $errorField == 'subject'} class="formError"{/if}>
+ <dt><label for="subject">{lang}wcf.acp.user.sendMail.subject{/lang}</label></dt>
+ <dd>
+ <input type="text" id="subject" name="subject" value="{$subject}" class="long" />
+ {if $errorField == 'subject'}
+ <small class="innerError">
+ {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
+ </small>
+ {/if}
+ </dd>
+</dl>
+
+<dl{if $errorField == 'from'} class="formError"{/if}>
+ <dt><label for="from">{lang}wcf.acp.user.sendMail.from{/lang}</label></dt>
+ <dd>
+ <input type="text" id="from" name="from" value="{$from}" class="medium" />
+ {if $errorField == 'from'}
+ <small class="innerError">
+ {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
+ </small>
+ {/if}
+ <small>{lang}wcf.acp.user.sendMail.from.description{/lang}</small>
+ </dd>
+</dl>
+
+<dl{if $errorField == 'text'} class="formError"{/if}>
+ <dt><label for="text">{lang}wcf.acp.user.sendMail.text{/lang}</label></dt>
+ <dd>
+ <textarea id="text" name="text" rows="15" cols="40">{$text}</textarea>
+ {if $errorField == 'text'}
+ <small class="innerError" class="long">
+ {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
+ </small>
+ {/if}
+ </dd>
+</dl>
+
+<dl>
+ <dt></dt>
+ <dd>
+ <label for="enableHTML"><input type="checkbox" id="enableHTML" name="enableHTML" value="1"{if $enableHTML == 1} checked="checked"{/if}/> {lang}wcf.acp.user.sendMail.enableHTML{/lang}</label>
+ </dd>
+</dl>
+
+{if !$mailID|empty}
+ <script data-relocate="true">
+ require(['Language'], function(Language) {
+ Language.add('wcf.acp.worker.abort.confirmMessage', '{lang}wcf.acp.worker.abort.confirmMessage{/lang}');
+
+ new WCF.ACP.Worker('mail', 'wcf\\system\\worker\\MailWorker', '', {
+ mailID: {@$mailID}
+ });
+ });
+ </script>
+{/if}
+++ /dev/null
-{include file='header' pageTitle='wcf.acp.user.bulkProcessing'}
-
-{if $mailID|isset}
- <script data-relocate="true">
- //<![CDATA[
- $(function() {
- WCF.Language.add('wcf.acp.worker.abort.confirmMessage', '{lang}wcf.acp.worker.abort.confirmMessage{/lang}');
-
- new WCF.ACP.Worker('mail', 'wcf\\system\\worker\\MailWorker', '', {
- mailID: {@$mailID}
- });
- });
- //]]>
- </script>
-{/if}
-
-<script data-relocate="true">
- //<![CDATA[
- $(function() {
- function toggleContainer(value) {
- for (var $name in $targetContainers) {
- if ($name === value) {
- $targetContainers[$name].show();
- }
- else {
- $targetContainers[$name].hide();
- }
- }
- }
-
- var $targetContainers = { };
- $('input[name=action]').each(function(index, input) {
- var $input = $(input);
- var $value = $input.prop('value');
-
- if (!$targetContainers[$value]) {
- var $container = $('#' + $.wcfEscapeID($value + 'Div'));
- if ($container.length) {
- $targetContainers[$value] = $container;
- }
- }
-
- $input.change(function(event) {
- toggleContainer($(event.currentTarget).prop('value'));
- });
- });
-
- function setFileType(newType) {
- if (newType === 'csv') {
- $('#separatorDiv').show().next().show();
- }
- else {
- $('#separatorDiv').hide().next().hide();
- }
- }
-
- $('input[name=fileType]').each(function(index, input) {
- var $input = $(input);
-
- $input.change(function(event) {
- setFileType($input.prop('value'));
- });
- });
-
- toggleContainer('{@$action}');
- setFileType('{@$fileType}');
-
- new WCF.Search.User($('#username'), function(data) {
- $('#username').val(data.label);
- return false;
- }, false);
- WCF.TabMenu.init();
- });
- //]]>
-</script>
-
-<header class="boxHeadline">
- <h1>{lang}wcf.acp.user.bulkProcessing{/lang}</h1>
-</header>
-
-{include file='formError'}
-
-<p class="warning">{lang}wcf.acp.user.bulkProcessing.warning{/lang}</p>
-
-{if $affectedUsers|isset}
- <p class="success">{lang}wcf.acp.user.bulkProcessing.success{/lang}</p>
-{/if}
-
-<div class="contentNavigation">
- {hascontent}
- <nav>
- <ul>
- {content}
- {event name='contentNavigationButtons'}
- {/content}
- </ul>
- </nav>
- {/hascontent}
-</div>
-
-<form method="post" action="{link controller='UserBulkProcessing'}{/link}">
- <div class="tabMenuContainer" data-active="{$activeTabMenuItem}" data-store="activeTabMenuItem">
- <nav class="tabMenu">
- <ul>
- <li><a href="{@$__wcf->getAnchor('conditions')}">{lang}wcf.acp.user.search.conditions{/lang}</a></li>
-
- {if $options|count}
- <li><a href="{@$__wcf->getAnchor('profile')}">{lang}wcf.acp.user.search.conditions.profile{/lang}</a></li>
- {/if}
-
- <li><a href="{@$__wcf->getAnchor('action')}">{lang}wcf.acp.user.bulkProcessing.action{/lang}</a></li>
- {event name='tabMenuTabs'}
- </ul>
- </nav>
-
- <div id="conditions" class="container containerPadding tabMenuContent">
- <fieldset>
- <legend>{lang}wcf.acp.user.search.conditions{/lang}</legend>
-
- <dl>
- <dt><label for="username">{lang}wcf.user.username{/lang}</label></dt>
- <dd>
- <input type="text" id="username" name="username" value="{$username}" autofocus="autofocus" class="medium" />
- </dd>
- </dl>
-
- {if $__wcf->session->getPermission('admin.user.canEditMailAddress')}
- <dl>
- <dt><label for="email">{lang}wcf.user.email{/lang}</label></dt>
- <dd>
- <input type="text" id="email" name="email" value="{$email}" class="medium" />
- </dd>
- </dl>
- {/if}
-
- {if $availableGroups|count}
- <dl>
- <dt><label>{lang}wcf.acp.user.groups{/lang}</label></dt>
- <dd>
- {htmlCheckboxes options=$availableGroups name='groupIDs' selected=$groupIDs}
-
- <label class="marginTop"><input type="checkbox" name="invertGroupIDs" value="1" {if $invertGroupIDs == 1}checked="checked" {/if}/> {lang}wcf.acp.user.groups.invertSearch{/lang}</label>
- </dd>
- </dl>
- {/if}
-
- {if $availableLanguages|count > 1}
- <dl>
- <dt><label>{lang}wcf.user.language{/lang}</label></dt>
- <dd>
- {htmlCheckboxes options=$availableLanguages name='languageIDs' selected=$languageIDs disableEncoding=true}
- </dd>
- </dl>
- {/if}
-
- <dl>
- <dt><label for="registrationDateStart">{lang}wcf.user.registrationDate{/lang}</label></dt>
- <dd>
- <input type="date" id="registrationDateStart" name="registrationDateStart" value="{$registrationDateStart}" placeholder="{lang}wcf.date.period.start{/lang}" />
- <input type="date" id="registrationDateEnd" name="registrationDateEnd" value="{$registrationDateEnd}" placeholder="{lang}wcf.date.period.end{/lang}" />
- </dd>
- </dl>
-
- <dl>
- <dt><label for="lastActivityTimeStart">{lang}wcf.user.lastActivityTime{/lang}</label></dt>
- <dd>
- <input type="date" id="lastActivityTimeStart" name="lastActivityTimeStart" value="{$lastActivityTimeStart}" placeholder="{lang}wcf.date.period.start{/lang}" />
- <input type="date" id="lastActivityTimeEnd" name="lastActivityTimeEnd" value="{$lastActivityTimeEnd}" placeholder="{lang}wcf.date.period.end{/lang}" />
- </dd>
- </dl>
-
- {event name='conditionFields'}
- </fieldset>
-
- <fieldset>
- <legend>{lang}wcf.acp.user.search.conditions.states{/lang}</legend>
-
- <dl>
- <dt></dt>
- <dd>
- <label><input type="checkbox" name="banned" value="1" {if $banned == 1}checked="checked" {/if}/> {lang}wcf.acp.user.search.conditions.state.banned{/lang}</label>
- <label><input type="checkbox" name="notBanned" value="1" {if $notBanned == 1}checked="checked" {/if}/> {lang}wcf.acp.user.search.conditions.state.notBanned{/lang}</label>
- <label><input type="checkbox" name="enabled" value="1" {if $enabled == 1}checked="checked" {/if}/> {lang}wcf.acp.user.search.conditions.state.enabled{/lang}</label>
- <label><input type="checkbox" name="disabled" value="1" {if $disabled == 1}checked="checked" {/if}/> {lang}wcf.acp.user.search.conditions.state.disabled{/lang}</label>
-
- {event name='states'}
- </dd>
- </dl>
-
- {event name='stateFields'}
- </fieldset>
-
- {event name='conditionFieldsets'}
- </div>
-
- {if $options|count}
- <div id="profile" class="container containerPadding tabMenuContent">
- <fieldset>
- <legend>{lang}wcf.acp.user.search.conditions.profile{/lang}</legend>
-
- {include file='optionFieldList' langPrefix='wcf.user.option.'}
- </fieldset>
-
- {event name='profileFieldsets'}
- </div>
- {/if}
-
- <div id="action" class="container containerPadding tabMenuContent">
- <fieldset{if $errorField == 'action'} class="formError"{/if}>
- <legend>{lang}wcf.acp.user.bulkProcessing.action{/lang}</legend>
-
- <dl>
- <dt></dt>
- <dd>
- {if $__wcf->session->getPermission('admin.user.canMailUser')}
- <label><input type="radio" name="action" value="sendMail" {if $action == 'sendMail'}checked="checked" {/if}/> {lang}wcf.acp.user.sendMail{/lang}</label>
- <label><input type="radio" name="action" value="exportMailAddress" {if $action == 'exportMailAddress'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress{/lang}</label>
- {/if}
- {if $__wcf->session->getPermission('admin.user.canEditUser')}
- <label><input type="radio" name="action" value="assignToGroup" {if $action == 'assignToGroup'}checked="checked" {/if}/> {lang}wcf.acp.user.assignToGroup{/lang}</label>
- {/if}
- {if $__wcf->session->getPermission('admin.user.canDeleteUser')}
- <label><input type="radio" name="action" value="delete" {if $action == 'delete'}checked="checked" {/if}/> {lang}wcf.acp.user.delete{/lang}</label>
- {/if}
-
- {event name='actions'}
-
- {if $errorField == 'action'}
- <small class="innerError">
- {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
- </small>
- {/if}
- </dd>
- </dl>
- </fieldset>
-
- {if $__wcf->session->getPermission('admin.user.canMailUser')}
- <div id="sendMailDiv">
- <fieldset>
- <legend>{lang}wcf.acp.user.sendMail.mail{/lang}</legend>
-
- <dl{if $errorField == 'subject'} class="formError"{/if}>
- <dt><label for="subject">{lang}wcf.acp.user.sendMail.subject{/lang}</label></dt>
- <dd>
- <input type="text" id="subject" name="subject" value="{$subject}" class="long" />
- {if $errorField == 'subject'}
- <small class="innerError">
- {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- <dl{if $errorField == 'from'} class="formError"{/if}>
- <dt><label for="from">{lang}wcf.acp.user.sendMail.from{/lang}</label></dt>
- <dd>
- <input type="text" id="from" name="from" value="{$from}" class="medium" />
- {if $errorField == 'from'}
- <small class="innerError">
- {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
- </small>
- {/if}
- <small>{lang}wcf.acp.user.sendMail.from.description{/lang}</small>
- </dd>
- </dl>
-
- <dl{if $errorField == 'text'} class="formError"{/if}>
- <dt><label for="text">{lang}wcf.acp.user.sendMail.text{/lang}</label></dt>
- <dd>
- <textarea id="text" name="text" rows="15" cols="40">{$text}</textarea>
- {if $errorField == 'text'}
- <small class="innerError" class="long">
- {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- <dl>
- <dt></dt>
- <dd>
- <label for="enableHTML"><input type="checkbox" id="enableHTML" name="enableHTML" value="1"{if $enableHTML == 1} checked="checked"{/if}/> {lang}wcf.acp.user.sendMail.enableHTML{/lang}</label>
- </dd>
- </dl>
- </fieldset>
- </div>
-
- <div id="exportMailAddressDiv">
- <fieldset>
- <legend>{lang}wcf.acp.user.exportEmailAddress.format{/lang}</legend>
-
- <dl>
- <dt><label>{lang}wcf.acp.user.exportEmailAddress.fileType{/lang}</label></dt>
- <dd>
- <label><input type="radio" name="fileType" value="csv" {if $fileType == 'csv'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.csv{/lang}</label>
- <label><input type="radio" name="fileType" value="xml" {if $fileType == 'xml'}checked="checked" {/if}/> {lang}wcf.acp.user.exportEmailAddress.fileType.xml{/lang}</label>
- </dd>
- </dl>
-
- <dl id="separatorDiv">
- <dt><label for="separator">{lang}wcf.acp.user.exportEmailAddress.separator{/lang}</label></dt>
- <dd>
- <input type="text" id="separator" name="separator" value="{$separator}" class="medium" />
- </dd>
- </dl>
-
- <dl id="textSeparatorDiv">
- <dt><label for="textSeparator">{lang}wcf.acp.user.exportEmailAddress.textSeparator{/lang}</label></dt>
- <dd>
- <input type="text" id="textSeparator" name="textSeparator" value="{$textSeparator}" class="medium" />
- </dd>
- </dl>
- </fieldset>
- </div>
- {/if}
-
- {if $__wcf->session->getPermission('admin.user.canEditUser')}
- <div id="assignToGroupDiv">
- <fieldset>
- <legend>{lang}wcf.acp.user.groups{/lang}</legend>
-
- <dl>
- <dt></dt>
- <dd{if $errorField == 'assignToGroupIDs'} class="formError"{/if}>
- {htmlCheckboxes options=$availableGroups name=assignToGroupIDs selected=$assignToGroupIDs}
- {if $errorField == 'assignToGroupIDs'}
- <small class="innerError">
- {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
- </small>
- {/if}
- </dd>
- </dl>
- </fieldset>
- </div>
- {/if}
-
- {event name='actionFieldsets'}
- </div>
- </div>
-
- <div class="formSubmit">
- <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
- {@SECURITY_TOKEN_INPUT_TAG}
- </div>
-</form>
-
-{include file='footer'}
+{if !$groupedObjectTypes|isset && $conditions|isset}{assign var='groupedObjectTypes' value=$conditions}{/if}
+
<div class="tabMenuContainer">
<nav class="tabMenu">
<ul>
</nav>
{foreach from=$groupedObjectTypes key='conditionGroup' item='conditionObjectTypes'}
- <div id="user_{$conditionGroup}" class="container containerPadding tabMenuContainer tabMenuContent">
+ <div id="user_{$conditionGroup}" class="container containerPadding tabMenuContent">
{if $conditionGroup != 'userOptions'}
<fieldset>
<legend>{lang}wcf.user.condition.conditionGroup.{$conditionGroup}{/lang}</legend>
--- /dev/null
+<dl>
+ <dt></dt>
+ <dd{if $errorField == $inputName} class="formError"{/if}>
+ {htmlCheckboxes options=$availableUserGroups name=$inputName selected=$selectedUserGroupIDs}
+ {if $errorField == $inputName}
+ <small class="innerError">{lang}wcf.global.form.error.{$errorType}{/lang}</small>
+ {/if}
+ </dd>
+</dl>
--- /dev/null
+<?php
+namespace wcf\acp\form;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\form\AbstractForm;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\exception\SystemException;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a form for bulk processing objects of a certain type.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage acp.form
+ * @category Community Framework
+ */
+abstract class AbstractBulkProcessingForm extends AbstractForm {
+ /**
+ * object action object type types
+ * @var array<\wcf\data\object\type\ObjectType>
+ */
+ public $actions = array();
+
+ /**
+ * number of objects affected by bulk processing
+ * @var integer
+ */
+ public $affectedObjectCount = 0;
+
+ /**
+ * object condition object type types
+ * @var array<\wcf\data\object\type\ObjectType>
+ */
+ public $conditions = array();
+
+ /**
+ * list with bulk processed objects
+ * @var \wcf\data\DatabaseObjectList
+ */
+ public $objectList = null;
+
+ /**
+ * bulk processable object type
+ * @var \wcf\data\object\type\ObjectType
+ */
+ public $objectType = null;
+
+ /**
+ * name of the bulk processable object type
+ * @var string
+ */
+ public $objectTypeName = '';
+
+ /**
+ * @see \wcf\page\Abstractpage::$templateName
+ */
+ public $templateName = 'bulkProcessing';
+
+ /**
+ * @see \wcf\page\IPage::assignVariables()
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ $classParts = explode('\\', get_class($this));
+
+ WCF::getTPL()->assign([
+ 'actions' => $this->actions,
+ 'affectedObjectCount' => $this->affectedObjectCount,
+ 'controller' => str_replace('Form', '', array_pop($classParts)),
+ 'conditions' => $this->conditions,
+ 'objectType' => $this->objectType
+ ]);
+ }
+
+ /**
+ * @see \wcf\page\IPage::readData()
+ */
+ public function readData() {
+ // read bulk processable object type
+ $this->objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.bulkProcessableObject', $this->objectTypeName);
+ if ($this->objectType === null) {
+ throw new SystemException("Unknown bulk processable object type '".$this->objectTypeName."'");
+ }
+
+ // read conditions
+ if (ObjectTypeCache::getInstance()->getDefinitionByName($this->objectType->getProcessor()->getConditionObjectTypeDefinition()) === null) {
+ throw new SystemException("Unknown condition object type definition '".$this->objectType->getProcessor()->getConditionObjectTypeDefinition()."'");
+ }
+ $conditionObjectTypes = ObjectTypeCache::getInstance()->getObjectTypes($this->objectType->getProcessor()->getConditionObjectTypeDefinition());
+ if (empty($conditionObjectTypes)) {
+ throw new IllegalLinkException();
+ }
+
+ foreach ($conditionObjectTypes as $objectType) {
+ if ($objectType->conditiongroup) {
+ if (!isset($this->conditions[$objectType->conditiongroup])) {
+ $this->conditions[$objectType->conditiongroup] = [ ];
+ }
+
+ $this->conditions[$objectType->conditiongroup][$objectType->objectTypeID] = $objectType;
+ }
+ else {
+ $this->conditions[''][$objectType->objectTypeID] = $objectType;
+ }
+ }
+
+ // read actions
+ if (ObjectTypeCache::getInstance()->getDefinitionByName($this->objectType->getProcessor()->getActionObjectTypeDefinition()) === null) {
+ throw new SystemException("Unknown action object type definition '".$this->objectType->getProcessor()->getActionObjectTypeDefinition()."'");
+ }
+
+ $actions = ObjectTypeCache::getInstance()->getObjectTypes($this->objectType->getProcessor()->getActionObjectTypeDefinition());
+ foreach ($actions as $objectType) {
+ if (isset($this->actions[$objectType->action])) {
+ throw new SystemException("Duplicate action with name '".$objectType->action."'");
+ }
+
+ if ($objectType->validateOptions() && $objectType->validatePermissions()) {
+ $this->actions[$objectType->action] = $objectType;
+ }
+ }
+ if (empty($this->actions)) {
+ throw new IllegalLinkException();
+ }
+
+ parent::readData();
+ }
+
+ /**
+ * @see \wcf\form\IForm::readFormParameters()
+ */
+ public function readFormParameters() {
+ parent::readFormParameters();
+
+ foreach ($this->conditions as $groupedObjectTypes) {
+ foreach ($groupedObjectTypes as $objectType) {
+ $objectType->getProcessor()->readFormParameters();
+ }
+ }
+
+ if (isset($this->actions[$this->action])) {
+ $this->actions[$this->action]->getProcessor()->readFormParameters();
+ }
+ }
+
+ /**
+ * @see \wcf\form\IForm::save()
+ */
+ public function save() {
+ $this->objectList = $this->actions[$this->action]->getProcessor()->getObjectList();
+
+ parent::save();
+
+ // read objects
+ foreach ($this->conditions as $groupedObjectTypes) {
+ foreach ($groupedObjectTypes as $objectType) {
+ $data = $objectType->getProcessor()->getData();
+ if ($data !== null) {
+ $objectType->getProcessor()->addObjectListCondition($this->objectList, $data);
+ }
+ }
+ }
+ $this->objectList->readObjects();
+
+ // execute action
+ $this->actions[$this->action]->getProcessor()->executeAction($this->objectList);
+
+ $this->affectedObjectCount = count($this->objectList);
+
+ $this->saved();
+
+ // reset fields
+ $this->actions[$this->action]->getProcessor()->reset();
+
+ foreach ($this->conditions as $groupedObjectTypes) {
+ foreach ($groupedObjectTypes as $objectType) {
+ $objectType->getProcessor()->reset();
+ }
+ }
+ $this->action = '';
+
+ WCF::getTPL()->assign('success', true);
+ }
+
+ /**
+ * @see \wcf\form\IForm::validate()
+ */
+ public function validate() {
+ parent::validate();
+
+ // validate action
+ if (empty($this->action)) {
+ throw new UserInputException('action');
+ }
+
+ if (!isset($this->actions[$this->action])) {
+ throw new UserInputException('action', 'noValidSelection');
+ }
+
+ $this->actions[$this->action]->getProcessor()->validate();
+
+ // validate conditions
+ foreach ($this->conditions as $groupedObjectTypes) {
+ foreach ($groupedObjectTypes as $objectType) {
+ $objectType->getProcessor()->validate();
+ }
+ }
+ }
+}
<?php
namespace wcf\acp\form;
-use wcf\data\user\group\UserGroup;
-use wcf\data\user\User;
-use wcf\data\user\UserAction;
-use wcf\data\user\UserEditor;
-use wcf\form\AbstractForm;
-use wcf\system\database\util\PreparedStatementConditionBuilder;
-use wcf\system\event\EventHandler;
-use wcf\system\exception\PermissionDeniedException;
-use wcf\system\exception\UserInputException;
-use wcf\system\language\LanguageFactory;
-use wcf\system\menu\acp\ACPMenu;
-use wcf\system\user\storage\UserStorageHandler;
-use wcf\system\WCF;
-use wcf\system\WCFACP;
-use wcf\util\ArrayUtil;
-use wcf\util\StringUtil;
/**
* Shows the user bulk processing form.
*
- * @author Marcel Werk
+ * @author Matthias Schmidt
* @copyright 2001-2015 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage acp.form
* @category Community Framework
*/
-class UserBulkProcessingForm extends UserOptionListForm {
+class UserBulkProcessingForm extends AbstractBulkProcessingForm {
/**
- * @see \wcf\page\AbstractPage::$neededPermissions
+ * @see \wcf\page\AbstractPage::$activeMenuItem
*/
- public $neededPermissions = array('admin.user.canEditUser', 'admin.user.canDeleteUser', 'admin.user.canMailUser');
+ public $activeMenuItem = 'wcf.acp.menu.link.user.bulkProcessing';
/**
- * searched username
- * @var string
+ * @see \wcf\acp\form\AbstractBulkProcessingForm::$objectTypeName
*/
- public $username = '';
-
- /**
- * searched email adress
- * @var string
- */
- public $email = '';
-
- /**
- * ids of the searched user group ids
- * @var array<integer>
- */
- public $groupIDs = array();
-
- /**
- * ids of the users' languages
- * @var array<integer>
- */
- public $languageIDs = array();
-
- /**
- * indicates if the user may not be in the user groups with the selected
- * ids
- * @var integer
- */
- public $invertGroupIDs = 0;
-
- /**
- * registration start date
- * @var string
- */
- public $registrationDateStart = '';
-
- /**
- * registration start date
- * @var string
- */
- public $registrationDateEnd = '';
-
- /**
- * banned state
- * @var boolean
- */
- public $banned = 0;
-
- /**
- * not banned state
- * @var boolean
- */
- public $notBanned = 0;
-
- /**
- * last activity start time
- * @var string
- */
- public $lastActivityTimeStart = '';
-
- /**
- * last activity end time
- * @var string
- */
- public $lastActivityTimeEnd = '';
-
- /**
- * enabled state
- * @var boolean
- */
- public $enabled = 0;
-
- /**
- * disabled state
- * @var boolean
- */
- public $disabled = 0;
-
- // assign to group
- public $assignToGroupIDs = array();
-
- // export mail address
- public $fileType = 'csv';
- public $separator = ',';
- public $textSeparator = '"';
-
- // send mail
- public $subject = '';
- public $text = '';
- public $from = '';
- public $enableHTML = 0;
-
- // data
- public $availableGroups = array();
- public $options = array();
- public $availableActions = array('sendMail', 'exportMailAddress', 'assignToGroup', 'delete');
- public $affectedUsers = 0;
-
- /**
- * conditions builder object
- * @var \wcf\system\database\condition\PreparedStatementConditionBuilder
- */
- public $conditions = null;
-
- /**
- * options of the active category
- * @var array
- */
- public $activeOptions = array();
-
- /**
- * @see \wcf\form\IForm::readFormParameters()
- */
- public function readFormParameters() {
- parent::readFormParameters();
-
- if (isset($_POST['username'])) $this->username = StringUtil::trim($_POST['username']);
- if (isset($_POST['email'])) $this->email = StringUtil::trim($_POST['email']);
- if (isset($_POST['groupIDs']) && is_array($_POST['groupIDs'])) $this->groupIDs = ArrayUtil::toIntegerArray($_POST['groupIDs']);
- if (isset($_POST['languageIDs']) && is_array($_POST['languageIDs'])) $this->languageIDs = ArrayUtil::toIntegerArray($_POST['languageIDs']);
- if (isset($_POST['invertGroupIDs'])) $this->invertGroupIDs = intval($_POST['invertGroupIDs']);
- if (isset($_POST['registrationDateStart'])) $this->registrationDateStart = $_POST['registrationDateStart'];
- if (isset($_POST['registrationDateEnd'])) $this->registrationDateEnd = $_POST['registrationDateEnd'];
- if (isset($_POST['banned'])) $this->banned = intval($_POST['banned']);
- if (isset($_POST['notBanned'])) $this->notBanned = intval($_POST['notBanned']);
- if (isset($_POST['lastActivityTimeStart'])) $this->lastActivityTimeStart = $_POST['lastActivityTimeStart'];
- if (isset($_POST['lastActivityTimeEnd'])) $this->lastActivityTimeEnd = $_POST['lastActivityTimeEnd'];
- if (isset($_POST['enabled'])) $this->enabled = intval($_POST['enabled']);
- if (isset($_POST['disabled'])) $this->disabled = intval($_POST['disabled']);
-
- // assign to group
- if (isset($_POST['assignToGroupIDs']) && is_array($_POST['assignToGroupIDs'])) $this->assignToGroupIDs = ArrayUtil::toIntegerArray($_POST['assignToGroupIDs']);
- // export mail address
- if (isset($_POST['fileType']) && $_POST['fileType'] == 'xml') $this->fileType = $_POST['fileType'];
- if (isset($_POST['separator'])) $this->separator = $_POST['separator'];
- if (isset($_POST['textSeparator'])) $this->textSeparator = $_POST['textSeparator'];
- // send mail
- if (isset($_POST['subject'])) $this->subject = StringUtil::trim($_POST['subject']);
- if (isset($_POST['text'])) $this->text = StringUtil::trim($_POST['text']);
- if (isset($_POST['from'])) $this->from = StringUtil::trim($_POST['from']);
- if (isset($_POST['enableHTML'])) $this->enableHTML = intval($_POST['enableHTML']);
- }
-
- /**
- * @see \wcf\form\IForm::validate()
- */
- public function validate() {
- AbstractForm::validate();
-
- // action
- if (!in_array($this->action, $this->availableActions)) {
- throw new UserInputException('action');
- }
-
- // assign to group
- if ($this->action == 'assignToGroup') {
- if (empty($this->assignToGroupIDs)) {
- throw new UserInputException('assignToGroupIDs');
- }
- }
-
- // send mail
- if ($this->action == 'sendMail') {
- if (empty($this->subject)) {
- throw new UserInputException('subject');
- }
-
- if (empty($this->text)) {
- throw new UserInputException('text');
- }
-
- if (empty($this->from)) {
- throw new UserInputException('from');
- }
- }
- }
-
- /**
- * @see \wcf\form\IForm::save()
- */
- public function save() {
- parent::save();
-
- // build conditions
- $this->conditions = new PreparedStatementConditionBuilder();
-
- // deny self delete
- if ($this->action == 'delete') {
- $this->conditions->add("user_table.userID <> ?", array(WCF::getUser()->userID));
- }
-
- // static fields
- if (!empty($this->username)) {
- $this->conditions->add("user_table.username LIKE ?", array('%'.addcslashes($this->username, '_%').'%'));
- }
- if (!empty($this->email)) {
- $this->conditions->add("user_table.email LIKE ?", array('%'.addcslashes($this->email, '_%').'%'));
- }
- if (!empty($this->groupIDs)) {
- $this->conditions->add("user_table.userID ".($this->invertGroupIDs == 1 ? 'NOT ' : '')."IN (SELECT userID FROM wcf".WCF_N."_user_to_group WHERE groupID IN (?))", array($this->groupIDs));
- }
- if (!empty($this->languageIDs)) {
- $this->conditions->add("user_table.languageID IN (?)", array($this->languageIDs));
- }
-
- // registration date
- if ($startDate = @strtotime($this->registrationDateStart)) {
- $this->conditions->add('user_table.registrationDate >= ?', array($startDate));
- }
- if ($endDate = @strtotime($this->registrationDateEnd)) {
- $this->conditions->add('user_table.registrationDate <= ?', array($endDate));
- }
-
- if ($this->banned) {
- $this->conditions->add('user_table.banned = ?', array(1));
- }
- if ($this->notBanned) {
- $this->conditions->add('user_table.banned = ?', array(0));
- }
-
- // last activity time
- if ($startDate = @strtotime($this->lastActivityTimeStart)) {
- $this->conditions->add('user_table.lastActivityTime >= ?', array($startDate));
- }
- if ($endDate = @strtotime($this->lastActivityTimeEnd)) {
- $this->conditions->add('user_table.lastActivityTime <= ?', array($endDate));
- }
-
- if ($this->enabled) {
- $this->conditions->add('user_table.activationCode = ?', array(0));
- }
- if ($this->disabled) {
- $this->conditions->add('user_table.activationCode <> ?', array(0));
- }
-
- // dynamic fields
- foreach ($this->activeOptions as $name => $option) {
- $value = isset($this->values[$option['optionName']]) ? $this->values[$option['optionName']] : null;
- $this->getTypeObject($option['optionType'])->getCondition($this->conditions, $option, $value);
- }
-
- // call buildConditions event
- EventHandler::getInstance()->fireAction($this, 'buildConditions');
-
- // execute action
- switch ($this->action) {
- case 'sendMail':
- WCF::getSession()->checkPermissions(array('admin.user.canMailUser'));
- // get user ids
- $userIDs = array();
- $sql = "SELECT user_table.userID
- FROM wcf".WCF_N."_user user_table
- LEFT JOIN wcf".WCF_N."_user_option_value option_value
- ON (option_value.userID = user_table.userID)".
- $this->conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($this->conditions->getParameters());
- while ($row = $statement->fetchArray()) {
- $userIDs[] = $row['userID'];
- $this->affectedUsers++;
- }
-
- if (!empty($userIDs)) {
- // save config in session
- $userMailData = WCF::getSession()->getVar('userMailData');
- if ($userMailData === null) $userMailData = array();
- $mailID = count($userMailData);
- $userMailData[$mailID] = array(
- 'action' => '',
- 'userIDs' => $userIDs,
- 'groupIDs' => '',
- 'subject' => $this->subject,
- 'text' => $this->text,
- 'from' => $this->from,
- 'enableHTML' => $this->enableHTML
- );
- WCF::getSession()->register('userMailData', $userMailData);
-
- WCF::getTPL()->assign('mailID', $mailID);
- }
- break;
-
- case 'exportMailAddress':
- WCF::getSession()->checkPermissions(array('admin.user.canMailUser'));
- // send content type
- header('Content-Type: text/'.$this->fileType.'; charset=UTF-8');
- header('Content-Disposition: attachment; filename="export.'.$this->fileType.'"');
-
- if ($this->fileType == 'xml') {
- echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<addresses>\n";
- }
-
- // count users
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_user user_table
- LEFT JOIN wcf".WCF_N."_user_option_value option_value
- ON (option_value.userID = user_table.userID)
- ".$this->conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($this->conditions->getParameters());
- $count = $statement->fetchArray();
-
- // get users
- $sql = "SELECT user_table.email
- FROM wcf".WCF_N."_user user_table
- LEFT JOIN wcf".WCF_N."_user_option_value option_value
- ON (option_value.userID = user_table.userID)
- ".$this->conditions."
- ORDER BY user_table.email";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($this->conditions->getParameters());
-
- $i = 0;
- while ($row = $statement->fetchArray()) {
- if ($this->fileType == 'xml') echo "<address><![CDATA[".StringUtil::escapeCDATA($row['email'])."]]></address>\n";
- else echo $this->textSeparator . $row['email'] . $this->textSeparator . ($i < $count['count'] ? $this->separator : '');
- $i++;
- $this->affectedUsers++;
- }
-
- if ($this->fileType == 'xml') {
- echo "</addresses>";
- }
- $this->saved();
- exit;
- break;
-
- case 'assignToGroup':
- WCF::getSession()->checkPermissions(array('admin.user.canEditUser'));
-
- $_this = $this;
- $userIDs = $this->fetchUsers(function($userID, array $userData) use ($_this) {
- $user = new UserEditor(new User(null, $userData));
- $user->addToGroups($_this->assignToGroupIDs, false, false);
- });
-
- if (!empty($userIDs)) {
- UserStorageHandler::getInstance()->reset($userIDs, 'groupIDs', 1);
- }
- break;
-
- case 'delete':
- WCF::getSession()->checkPermissions(array('admin.user.canDeleteUser'));
-
- $userIDs = $this->fetchUsers();
-
- if (!empty($userIDs)) {
- $userAction = new UserAction($userIDs, 'delete');
- $userAction->executeAction();
- }
- break;
- }
- $this->saved();
-
- WCF::getTPL()->assign('affectedUsers', $this->affectedUsers);
- }
-
- /**
- * Fetches a list of users.
- *
- * @param mixed $loopFunction
- * @return array<integer>
- */
- public function fetchUsers($loopFunction = null) {
- // select users
- $sql = "SELECT user_table.*
- FROM wcf".WCF_N."_user user_table
- LEFT JOIN wcf".WCF_N."_user_option_value option_value
- ON (option_value.userID = user_table.userID)
- ".$this->conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($this->conditions->getParameters());
-
- $users = array();
- while ($row = $statement->fetchArray()) {
- $users[$row['userID']] = $row;
- }
- if (empty($users)) return array();
-
- // select group ids
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("userID IN (?)", array(array_keys($users)));
-
- $sql = "SELECT userID, groupID
- FROM wcf".WCF_N."_user_to_group
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- $groupIDs = array();
- while ($row = $statement->fetchArray()) {
- if (!isset($groupIDs[$row['userID']])) {
- $groupIDs[$row['userID']] = array();
- }
-
- $groupIDs[$row['userID']][] = $row['groupID'];
- }
-
- foreach ($users as $userID => $userData) {
- if (!empty($groupIDs[$userID]) && !UserGroup::isAccessibleGroup($groupIDs[$userID])) {
- throw new PermissionDeniedException();
- }
-
- if ($loopFunction !== null) {
- $loopFunction($userID, $userData);
- }
-
- $userIDs[] = $userID;
- $this->affectedUsers++;
- }
-
- return $userIDs;
- }
-
- /**
- * @see \wcf\page\IPage::readData()
- */
- public function readData() {
- parent::readData();
-
- if (empty($_POST)) {
- if (MAIL_USE_FORMATTED_ADDRESS) {
- $this->from = MAIL_FROM_NAME.' <'.MAIL_FROM_ADDRESS.'>';
- }
- else {
- $this->from = MAIL_FROM_ADDRESS;
- }
- }
-
- $this->availableGroups = $this->getAvailableGroups();
-
- foreach ($this->activeOptions as $name => $option) {
- if (isset($this->values[$name])) {
- $this->activeOptions[$name]['optionValue'] = $this->values[$name];
- }
- }
-
- $this->options = $this->optionHandler->getCategoryOptions('profile');
- }
-
- /**
- * @see \wcf\page\IPage::assignVariables()
- */
- public function assignVariables() {
- parent::assignVariables();
-
- WCF::getTPL()->assign(array(
- 'username' => $this->username,
- 'email' => $this->email,
- 'groupIDs' => $this->groupIDs,
- 'languageIDs' => $this->languageIDs,
- 'invertGroupIDs' => $this->invertGroupIDs,
- 'registrationDateStart' => $this->registrationDateStart,
- 'registrationDateEnd' => $this->registrationDateEnd,
- 'banned' => $this->banned,
- 'notBanned' => $this->notBanned,
- 'lastActivityTimeStart' => $this->lastActivityTimeStart,
- 'lastActivityTimeEnd' => $this->lastActivityTimeEnd,
- 'enabled' => $this->enabled,
- 'disabled' => $this->disabled,
-
- 'availableGroups' => $this->availableGroups,
- 'availableLanguages' => LanguageFactory::getInstance()->getLanguages(),
- 'options' => $this->options,
- 'availableActions' => $this->availableActions,
- // assign to group
- 'assignToGroupIDs' => $this->assignToGroupIDs,
- // export mail address
- 'separator' => $this->separator,
- 'textSeparator' => $this->textSeparator,
- 'fileType' => $this->fileType,
- // send mail
- 'subject' => $this->subject,
- 'text' => $this->text,
- 'from' => $this->from,
- 'enableHTML' => $this->enableHTML
- ));
- }
-
- /**
- * @see \wcf\form\IForm::show()
- */
- public function show() {
- // set active menu item
- ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.user.bulkProcessing');
-
- // check master password
- WCFACP::checkMasterPassword();
-
- // show form
- parent::show();
- }
+ public $objectTypeName = 'com.woltlab.wcf.bulkProcessing.user';
}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing;
+use wcf\data\object\type\AbstractObjectTypeProcessor;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a bulk processable object type.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing
+ * @category Community Framework
+ */
+class AbstractBulkProcessableObjectType extends AbstractObjectTypeProcessor implements IBulkProcessableObjectType {
+ /**
+ * name of the object type definition for the bulk actions
+ * @var string
+ */
+ protected $actionObjectTypeDefinition = '';
+
+ /**
+ * name of the object type definition for the object conditions
+ * @var string
+ */
+ protected $conditionObjectTypeDefinition = '';
+
+ /**
+ * name of the prefix of the language items used in the interface
+ * @var string
+ */
+ protected $languageItemPrefix = '';
+
+ /**
+ * name of the conditions template
+ * @var string
+ */
+ protected $templateName = '';
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessableObjectType::getActionObjectTypeDefinition()
+ */
+ public function getActionObjectTypeDefinition() {
+ if (empty($this->actionObjectTypeDefinition)) {
+ $this->actionObjectTypeDefinition = $this->object->objectType.'.action';
+ }
+
+ return $this->actionObjectTypeDefinition;
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessableObjectType::getConditionHTML()
+ */
+ public function getConditionHTML() {
+ return WCF::getTPL()->fetch($this->templateName, explode('\\', get_class($this))[0]);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessableObjectType::getConditionObjectTypeDefinition()
+ */
+ public function getConditionObjectTypeDefinition() {
+ if (empty($this->conditionObjectTypeDefinition)) {
+ $this->conditionObjectTypeDefinition = $this->object->objectType.'.condition';
+ }
+
+ return $this->conditionObjectTypeDefinition;
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessableObjectType::getLanguageItemPrefix()
+ */
+ public function getLanguageItemPrefix() {
+ if (empty($this->languageItemPrefix)) {
+ $application = explode('\\', get_class($this))[0];
+ $objectTypePieces = explode('.', $this->object->objectType);
+
+ $this->languageItemPrefix = $application.'.acp.'.end($objectTypePieces).'.bulkProcessing';
+ }
+
+ return $this->languageItemPrefix;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing;
+use wcf\data\object\type\AbstractObjectTypeProcessor;
+
+/**
+ * Abstract implementation of a bulk processing action.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing
+ * @category Community Framework
+ */
+abstract class AbstractBulkProcessingAction extends AbstractObjectTypeProcessor implements IBulkProcessingAction {
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getHTML()
+ */
+ public function getHTML() {
+ return '';
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::isAvailable()
+ */
+ public function isAvailable() {
+ return true;
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::readFormParameters()
+ */
+ public function readFormParameters() {
+ // does nothing
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::reset()
+ */
+ public function reset() {
+ // does nothing
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::validate()
+ */
+ public function validate() {
+ // does nothing
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing;
+
+/**
+ * Every bulk processable object type has to implement this interface.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing
+ * @category Community Framework
+ */
+interface IBulkProcessableObjectType {
+ /**
+ * Returns the name of the object type definition for the bulk actions.
+ *
+ * @return string
+ */
+ public function getActionObjectTypeDefinition();
+
+ /**
+ * Returns the output for setting up the conditions for the bulk processable
+ * object.
+ *
+ * @return string
+ */
+ public function getConditionHTML();
+
+ /**
+ * Returns the name of the object type definition for the object conditions.
+ *
+ * @return string
+ */
+ public function getConditionObjectTypeDefinition();
+
+ /**
+ * Returns the name of the prefix of the language items used in the interface.
+ *
+ * The returned prefix has not trailing dot.
+ *
+ * @return string
+ */
+ public function getLanguageItemPrefix();
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Every bulk processing action has to implement this interface.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing
+ * @category Community Framework
+ */
+interface IBulkProcessingAction {
+ /**
+ * Executes the bulk processing action on all objects in the given object
+ * list.
+ *
+ * @param \wcf\data\DatabaseObjectList $objectList
+ */
+ public function executeAction(DatabaseObjectList $objectList);
+
+ /**
+ * Returns the output for setting additional action parameters.
+ *
+ * @return string
+ */
+ public function getHTML();
+
+ /**
+ * Returns an object list which will be populated with conditions to read
+ * the processed objects.
+ *
+ * @return \wcf\data\DatabaseObjectList
+ */
+ public function getObjectList();
+
+ /**
+ * Returns true if the action is available for the active user.
+ *
+ * @return boolean
+ */
+ public function isAvailable();
+
+ /**
+ * Reads additional parameters to execute the action.
+ */
+ public function readFormParameters();
+
+ /**
+ * Resets the internally stored additional action parameters.
+ */
+ public function reset();
+
+ /**
+ * Validates the additional action parameters.
+ */
+ public function validate();
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\data\user\group\UserGroup;
+use wcf\data\user\UserList;
+use wcf\system\bulk\processing\AbstractBulkProcessingAction;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a user bulk processing action.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+abstract class AbstractUserBulkProcessingAction extends AbstractBulkProcessingAction {
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getObjectList()
+ */
+ public function getObjectList() {
+ return new UserList();
+ }
+
+ /**
+ * Returns all users who the active user can access due to their user group
+ * assocition.
+ *
+ * @param \wcf\data\user\UserList $userList
+ */
+ protected function getAccessibleUsers(UserList $userList) {
+ // fetch user group ids of all users
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('userID IN (?)', [ $userList->getObjectIDs() ]);
+
+ $sql = "SELECT userID, groupID
+ FROM wcf".WCF_N."_user_to_group
+ ".$conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+
+ $groupIDs = [ ];
+ while ($row = $statement->fetchArray()) {
+ if (!isset($groupIDs[$row['userID']])) {
+ $groupIDs[$row['userID']] = [ ];
+ }
+
+ $groupIDs[$row['userID']][] = $row['groupID'];
+ }
+
+ $users = [ ];
+ foreach ($userList as $user) {
+ if (empty($groupIDs[$user->userID]) || UserGroup::isAccessibleGroup($groupIDs[$user->userID])) {
+ $users[$user->userID] = $user;
+ }
+ }
+
+ return $users;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\data\user\group\UserGroup;
+use wcf\data\user\UserEditor;
+use wcf\data\user\UserList;
+use wcf\data\DatabaseObject;
+use wcf\data\DatabaseObjectList;
+use wcf\system\exception\UserInputException;
+use wcf\system\user\storage\UserStorageHandler;
+use wcf\system\WCF;
+use wcf\util\ArrayUtil;
+
+/**
+ * Abstract implementation of a user bulk processing action related to selecting
+ * user groups.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+abstract class AbstractUserGroupsUserBulkProcessingAction extends AbstractUserBulkProcessingAction {
+ /**
+ * list of available user groups
+ * @var array<\wcf\data\user\group\UserGroup>
+ */
+ public $availableUserGroups = [ ];
+
+ /**
+ * name of the inputs used to store the selected user group ids
+ * @var string
+ */
+ public $inputName = '';
+
+ /**
+ * ids of selected user groups
+ * @var array<integer>
+ */
+ public $userGroupIDs = [ ];
+
+ /**
+ * @see \wcf\data\DatabaseObjectDecorator::__construct()
+ */
+ public function __construct(DatabaseObject $object) {
+ parent::__construct($object);
+
+ $this->availableUserGroups = UserGroup::getAccessibleGroups([ ], [ UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS ]);
+
+ uasort($this->availableUserGroups, function(UserGroup $groupA, UserGroup $groupB) {
+ return strcmp($groupA->getName(), $groupB->getName());
+ });
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::executeAction()
+ */
+ public function executeAction(DatabaseObjectList $objectList) {
+ if (!($objectList instanceof UserList)) return;
+
+ $users = $this->getAccessibleUsers($objectList);
+
+ if (!empty($users)) {
+ WCF::getDB()->beginTransaction();
+ foreach ($users as $user) {
+ $user = new UserEditor($user);
+ $this->executeUserAction($user);
+ }
+ WCF::getDB()->commitTransaction();
+
+ UserStorageHandler::getInstance()->reset(array_keys($users), 'groupIDs');
+ }
+ }
+
+ /**
+ * Execute the action for the given user.
+ *
+ * @param \wcf\data\user\UserEditor $user
+ */
+ abstract protected function executeUserAction(UserEditor $user);
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getHTML()
+ */
+ public function getHTML() {
+ return WCF::getTPL()->fetch('userGroupListUserBulkProcessing', 'wcf', [
+ 'availableUserGroups' => $this->availableUserGroups,
+ 'inputName' => $this->inputName,
+ 'selectedUserGroupIDs' => $this->userGroupIDs
+ ]);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::isAvailable()
+ */
+ public function isAvailable() {
+ return !empty($this->availableUserGroups);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST[$this->inputName])) $this->userGroupIDs = ArrayUtil::toIntegerArray($_POST[$this->inputName]);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::reset()
+ */
+ public function reset() {
+ $this->userGroupIDs = [ ];
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::validate()
+ */
+ public function validate() {
+ if (empty($this->userGroupIDs)) {
+ throw new UserInputException($this->inputName);
+ }
+
+ foreach ($this->userGroupIDs as $groupID) {
+ if (!isset($this->availableUserGroups[$groupID])) {
+ throw new UserInputException($this->inputName, 'noValidSelection');
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\data\user\UserEditor;
+
+/**
+ * Bulk processing action implementation for assigning users to user groups.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+class AssignToUserGroupsUserBulkProcessingAction extends AbstractUserGroupsUserBulkProcessingAction {
+ /**
+ * @see \wcf\system\bulk\processing\user\AbstractUserGroupsUserBulkProcessingAction::$inputName
+ */
+ public $inputName = 'assignToUserGroupIDs';
+
+ /**
+ * @see \wcf\system\bulk\processing\user\AbstractUserGroupsUserBulkProcessingAction::executeUserAction()
+ */
+ protected function executeUserAction(UserEditor $user) {
+ $user->addToGroups($this->userGroupIDs, false, false);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\data\user\UserAction;
+use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
+use wcf\system\WCF;
+
+/**
+ * Bulk processing action implementation for deleting users.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+class DeleteUserBulkProcessingAction extends AbstractUserBulkProcessingAction {
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::executeAction()
+ */
+ public function executeAction(DatabaseObjectList $objectList) {
+ if (!($objectList instanceof UserList)) return;
+
+ $users = $this->getAccessibleUsers($objectList);
+
+ if (!empty($users)) {
+ $userAction = new UserAction($users, 'delete');
+ $userAction->executeAction();
+ }
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getObjectList()
+ */
+ public function getObjectList() {
+ $userList = parent::getObjectList();
+
+ // deny self deletion
+ $userList->getConditionBuilder()->add('user_table.userID <> ?', array(WCF::getUser()->userID));
+
+ return $userList;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\data\user\UserAction;
+use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Bulk processing action implementation for exporting mail addresses of users.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+class ExportMailAddressUserBulkProcessingAction extends AbstractUserBulkProcessingAction {
+ /**
+ * type of the file the email addresses will be saved in (csv or xml)
+ * @var string
+ */
+ public $fileType = 'csv';
+
+ /**
+ * separates the exported email addresses
+ * @var string
+ */
+ public $separator = ',';
+
+ /**
+ * encloses the exported email addresses
+ * @var string
+ */
+ public $textSeparator = '"';
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::executeAction()
+ */
+ public function executeAction(DatabaseObjectList $objectList) {
+ if (!($objectList instanceof UserList)) return;
+
+ // send content type
+ header('Content-Type: text/'.$this->fileType.'; charset=UTF-8');
+ header('Content-Disposition: attachment; filename="export.'.$this->fileType.'"');
+
+ if ($this->fileType == 'xml') {
+ echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<addresses>\n";
+ }
+
+ $userCount = count($objectList);
+ $i = 0;
+ foreach ($objectList as $user) {
+ if ($this->fileType == 'xml') {
+ echo "<address><![CDATA[".StringUtil::escapeCDATA($user->email)."]]></address>\n";
+ }
+ else {
+ echo $this->textSeparator.$user->email.$this->textSeparator.($i < $userCount ? $this->separator : '');
+ }
+
+ $i++;
+ }
+
+ if ($this->fileType == 'xml') {
+ echo "</addresses>";
+ }
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getHTML()
+ */
+ public function getHTML() {
+ return WCF::getTPL()->fetch('exportMailAddressUserBulkProcessing', 'wcf', [
+ 'fileType' => $this->fileType,
+ 'separator' => $this->separator,
+ 'textSeparator' => $this->textSeparator
+ ]);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getObjectList()
+ */
+ public function getObjectList() {
+ $userList = parent::getObjectList();
+
+ $userList->sqlOrderBy = 'user_table.email';
+
+ return $userList;
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST['fileType']) && $_POST['fileType'] == 'xml') $this->fileType = $_POST['fileType'];
+ if (isset($_POST['separator'])) $this->separator = $_POST['separator'];
+ if (isset($_POST['textSeparator'])) $this->textSeparator = $_POST['textSeparator'];
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::reset()
+ */
+ public function reset() {
+ exit;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\data\user\UserEditor;
+use wcf\system\WCF;
+
+/**
+ * Bulk processing action implementation for removing users from user groups.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+class RemoveFromUserGroupsUserBulkProcessingAction extends AbstractUserGroupsUserBulkProcessingAction {
+ /**
+ * @see \wcf\system\bulk\processing\user\AbstractUserGroupsUserBulkProcessingAction::$inputName
+ */
+ public $inputName = 'removeFromUserGroupIDs';
+
+ /**
+ * @see \wcf\system\bulk\processing\user\AbstractUserGroupsUserBulkProcessingAction::executeUserAction()
+ */
+ protected function executeUserAction(UserEditor $user) {
+ $user->removeFromGroups($this->userGroupIDs);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getObjectList()
+ */
+ public function getObjectList() {
+ $userList = parent::getObjectList();
+
+ // the active user may not remove themselves from any user group
+ // to avoid potential permission issues
+ $userList->getConditionBuilder()->add('user_table.userID <> ?', array(WCF::getUser()->userID));
+
+ return $userList;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Bulk processing action implementation for sening mails to users.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+class SendMailUserBulkProcessingAction extends AbstractUserBulkProcessingAction {
+ /**
+ * email text
+ * @var string
+ */
+ public $email = '';
+
+ /**
+ * is 1 if HTML for the email is enabled
+ * @var integer
+ */
+ public $enableHTML = 0;
+
+ /**
+ * sender
+ * @var string
+ */
+ public $from = '';
+
+ /**
+ * identifier for the mail worker
+ * @var string
+ */
+ public $mailID = '';
+
+ /**
+ * email text
+ * @var string
+ */
+ public $text = '';
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::executeAction()
+ */
+ public function executeAction(DatabaseObjectList $objectList) {
+ if (!($objectList instanceof UserList)) return;
+
+ if (count($objectList)) {
+ // save config in session
+ $userMailData = WCF::getSession()->getVar('userMailData');
+ if ($userMailData === null) $userMailData = array();
+ $this->mailID = count($userMailData);
+ $userMailData[$this->mailID] = array(
+ 'action' => '',
+ 'enableHTML' => $this->enableHTML,
+ 'from' => $this->from,
+ 'groupIDs' => '',
+ 'subject' => $this->subject,
+ 'text' => $this->text,
+ 'userIDs' => $objectList->getObjectIDs()
+ );
+ WCF::getSession()->register('userMailData', $userMailData);
+ }
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::getHTML()
+ */
+ public function getHTML() {
+ return WCF::getTPL()->fetch('sendMailUserBulkProcessing', 'wcf', [
+ 'enableHTML' => $this->enableHTML,
+ 'from' => $this->from,
+ 'mailID' => $this->mailID,
+ 'subject' => $this->subject,
+ 'text' => $this->text
+ ]);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST['enableHTML'])) $this->enableHTML = intval($_POST['enableHTML']);
+ if (isset($_POST['from'])) $this->from = StringUtil::trim($_POST['from']);
+ if (isset($_POST['subject'])) $this->subject = StringUtil::trim($_POST['subject']);
+ if (isset($_POST['text'])) $this->text = StringUtil::trim($_POST['text']);
+ }
+
+ /**
+ * @see \wcf\system\bulk\processing\IBulkProcessingAction::validate()
+ */
+ public function validate() {
+ if (empty($this->subject)) {
+ throw new UserInputException('subject');
+ }
+
+ if (empty($this->text)) {
+ throw new UserInputException('text');
+ }
+
+ if (empty($this->from)) {
+ throw new UserInputException('from');
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\bulk\processing\user;
+use wcf\system\bulk\processing\AbstractBulkProcessableObjectType;
+
+
+/**
+ * Bulk processable object type implementation for users.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.bulk.processing.user
+ * @category Community Framework
+ */
+class UserBulkProcessableObjectType extends AbstractBulkProcessableObjectType {
+ /**
+ * @see \wcf\system\bulk\processing\AbstractBulkProcessableObjectType::$templateName
+ */
+ protected $templateName = 'userConditions';
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\DatabaseObject;
+use wcf\data\DatabaseObjectList;
+use wcf\util\ClassUtil;
+
+/**
+ * Abstract condition implementation for check a text-typed property of a database
+ * object.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ */
+abstract class AbstractObjectTextPropertyCondition extends AbstractTextCondition implements IObjectCondition, IObjectListCondition {
+ /**
+ * name of the relevant database object class
+ * @var string
+ */
+ protected $className = '';
+
+ /**
+ * is true if the entered value should be split by commas to search for
+ * multiple values
+ * @var boolean
+ */
+ protected $supportsMultipleValues = false;
+
+ /**
+ * name of the relevant object property
+ * @var string
+ */
+ protected $propertyName = '';
+
+ /**
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
+ */
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!ClassUtil::isInstanceOf($objectList, $this->getListClassName())) return;
+
+ if ($this->supportsMultipleValues) {
+ $objectList->getConditionBuilder()->add($objectList->getDatabaseTableAlias().'.'.$this->getPropertyName().' IN (?)', [ $conditionData[$this->fieldName] ]);
+ }
+ else {
+ $objectList->getConditionBuilder()->add($objectList->getDatabaseTableAlias().'.'.$this->getPropertyName().' = ?', [ $conditionData[$this->fieldName] ]);
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IObjectCondition::checkObject()
+ */
+ public function checkObject(DatabaseObject $object, array $conditionData) {
+ if (!ClassUtil::isInstanceOf($object, $this->getClassName())) return;
+
+ return in_array($object->{$this->getPropertyName()}, $conditionData[$this->fieldName]);
+ }
+
+ /**
+ * Returns the name of the relevant database object class.
+ *
+ * @return string
+ */
+ protected function getClassName() {
+ return $this->className;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ $value = parent::getData();
+ if ($value === null || !$this->supportsMultipleValues) {
+ return $value;
+ }
+
+ return [
+ $this->fieldName => preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY)
+ ];
+ }
+
+ /**
+ * Returns the name of the relevant database object list class.
+ *
+ * @return string
+ */
+ protected function getListClassName() {
+ return $this->className.'List';
+ }
+
+ /**
+ * Returns the name of the relevant object property.
+ *
+ * @return string
+ */
+ protected function getPropertyName() {
+ return $this->propertyName;
+ }
+}
*/
public function getData() {
if (mb_strlen($this->fieldValue)) {
- return array(
+ return [
$this->fieldName => $this->fieldValue
- );
+ ];
}
return null;
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+use wcf\data\DatabaseObject;
+use wcf\data\DatabaseObjectList;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+use wcf\util\ClassUtil;
+
+/**
+ * Condition implementation for compairing a user-bound timestamp with a fixed time
+ * interval.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ */
+abstract class AbstractTimestampCondition extends AbstractSingleFieldCondition implements IObjectCondition, IObjectListCondition {
+ /**
+ * name of the relevant database object class
+ * @var string
+ */
+ protected $className = '';
+
+ /**
+ * registration start date
+ * @var string
+ */
+ protected $endTime = '';
+
+ /**
+ * name of the relevant object property
+ * @var string
+ */
+ protected $propertyName = '';
+
+ /**
+ * registration start date
+ * @var string
+ */
+ protected $startTime = '';
+
+ /**
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
+ */
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!ClassUtil::isInstanceOf($objectList, $this->getListClassName())) return;
+
+ $objectList->getConditionBuilder()->add($objectList->getDatabaseTableAlias().'.'.$this->getPropertyName().' <> ?', [ 0 ]);
+ if (isset($conditionData['endTime'])) {
+ $objectList->getConditionBuilder()->add($objectList->getDatabaseTableAlias().'.'.$this->getPropertyName().' < ?', [ strtotime($conditionData['endTime']) + 86400 ]);
+ }
+ if (isset($conditionData['startTime'])) {
+ $objectList->getConditionBuilder()->add($objectList->getDatabaseTableAlias().'.'.$this->getPropertyName().' >= ?', [ strtotime($conditionData['startTime']) ]);
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IObjectCondition::checkObject()
+ */
+ public function checkObject(DatabaseObject $object, array $conditionData) {
+ if (!ClassUtil::isInstanceOf($object, $this->getClassName())) return;
+
+ if (isset($conditionData['startTime']) && $object->{$this->getPropertyName()} < strtotime($conditionData['startTime'])) {
+ return false;
+ }
+ if (isset($conditionData['endTimeTime']) && $object->{$this->getPropertyName()} >= strtotime($conditionData['endTime']) + 86400) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the name of the relevant database object class.
+ *
+ * @return string
+ */
+ protected function getClassName() {
+ return $this->className;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ $data = array();
+
+ if (strlen($this->startTime)) {
+ $data['startTime'] = $this->startTime;
+ }
+ if (strlen($this->endTime)) {
+ $data['endTime'] = $this->endTime;
+ }
+
+ if (!empty($data)) {
+ return $data;
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::getFieldElement()
+ */
+ protected function getFieldElement() {
+ $start = WCF::getLanguage()->get('wcf.date.period.start');
+ $end = WCF::getLanguage()->get('wcf.date.period.end');
+
+ return <<<HTML
+<input type="date" id="{$this->getPropertyName()}StartTime" name="{$this->getPropertyName()}StartTime" value="{$this->startTime}" placeholder="{$start}" />
+<input type="date" id="{$this->getPropertyName()}EndTime" name="{$this->getPropertyName()}EndTime" value="{$this->endTime}" placeholder="{$end}" />
+HTML;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::getLabel()
+ */
+ protected function getLabel() {
+ return WCF::getLanguage()->get($this->getLanguageItemPrefix().'.'.$this->getPropertyName());
+ }
+
+ /**
+ * Returns the prefix of the language items used for the condition.
+ *
+ * @return string
+ */
+ abstract protected function getLanguageItemPrefix();
+
+ /**
+ * Returns the name of the relevant database object list class.
+ *
+ * @return string
+ */
+ protected function getListClassName() {
+ return $this->className.'List';
+ }
+
+ /**
+ * Returns the name of the relevant object property.
+ *
+ * @return string
+ */
+ protected function getPropertyName() {
+ return $this->propertyName;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST[$this->getPropertyName().'EndTime'])) $this->endTime = $_POST[$this->getPropertyName().'EndTime'];
+ if (isset($_POST[$this->getPropertyName().'StartTime'])) $this->startTime = $_POST[$this->getPropertyName().'StartTime'];
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->endTime = '';
+ $this->startTime = '';
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ if ($condition->endTime) {
+ $this->endTime = $condition->endTime;
+ }
+ if ($condition->startTime) {
+ $this->startTime = $condition->startTime;
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ $endTime = $startTime = null;
+ if (strlen($this->startTime)) {
+ $startTime = @strtotime($this->startTime);
+ if ($startTime === false) {
+ $this->errorMessage = $this->getLanguageItemPrefix().'.'.$this->getPropertyName().'.error.startNotValid';
+
+ throw new UserInputException($this->getPropertyName(), 'startNotValid');
+ }
+ }
+ if (strlen($this->endTime)) {
+ $endTime = @strtotime($this->endTime);
+ if ($endTime === false) {
+ $this->errorMessage = $this->getLanguageItemPrefix().'.'.$this->getPropertyName().'.error.endNotValid';
+
+ throw new UserInputException($this->getPropertyName(), 'endNotValid');
+ }
+ }
+
+ if ($endTime !== null && $startTime !== null && $endTime < $startTime) {
+ $this->errorMessage = $this->getLanguageItemPrefix().'.'.$this->getPropertyName().'.error.endBeforeStart';
+
+ throw new UserInputException($this->getPropertyName(), 'endBeforeStart');
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\DatabaseObject;
+
+/**
+ * Every implementation of database object-related conditions needs to implements
+ * this interface.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ */
+interface IObjectCondition extends ICondition {
+ /**
+ * Returns true if the given object fulfills the condition specified by
+ * the given condition data returned by \wcf\system\condition\ICondition::getData().
+ *
+ * @param \wcf\data\DatabaseObject $object
+ * @param array $conditionData
+ * @return boolean
+ */
+ public function checkObject(DatabaseObject $object, array $conditionData);
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Every implementation of database object list-related conditions needs to implements
+ * this interface.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ */
+interface IObjectListCondition extends ICondition {
+ /**
+ * Adds a condition to the given object list based on the given condition
+ * data returned by \wcf\system\condition\ICondition::getData().
+ *
+ * @param \wcf\data\DatabaseObjectList $objectList
+ * @param array $conditionData
+ */
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData);
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\UserList;
+
+/**
+ * Redirects IUserCondition::addUserCondition() calls to the more general
+ * IObjectListCondition::addObjectListCondition().
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ */
+trait TObjectListUserCondition {
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ $this->addObjectListCondition($userList, $condition->conditionData);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+
+/**
+ * Redirects IUserCondition::checkUser() calls to the more general IObjectCondition::checkObject().
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ */
+trait TObjectUserCondition {
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ $this->checkObject($user, $condition->conditionData);
+ }
+}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\WCF;
/**
* @subpackage system.condition
* @category Community Framework
*/
-class UserAvatarCondition extends AbstractSelectCondition implements IContentCondition, IUserCondition {
+class UserAvatarCondition extends AbstractSelectCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see wcf\system\condition\AbstractSelectCondition::$fieldName
*/
const GRAVATAR = 2;
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- switch ($condition->userAvatar) {
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ switch ($conditionData['userAvatar']) {
case self::NO_AVATAR:
- $userList->getConditionBuilder()->add('user_table.avatarID IS NULL');
- $userList->getConditionBuilder()->add('user_table.enableGravatar = ?', array(0));
+ $objectList->getConditionBuilder()->add('user_table.avatarID IS NULL');
+ $objectList->getConditionBuilder()->add('user_table.enableGravatar = ?', array(0));
break;
case self::AVATAR:
- $userList->getConditionBuilder()->add('user_table.avatarID IS NOT NULL');
+ $objectList->getConditionBuilder()->add('user_table.avatarID IS NOT NULL');
break;
case self::GRAVATAR:
- $userList->getConditionBuilder()->add('user_table.enableGravatar = ?', array(1));
+ $objectList->getConditionBuilder()->add('user_table.enableGravatar = ?', array(1));
break;
}
}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\WCF;
/**
* @subpackage system.condition
* @category Community Framework
*/
-class UserEmailCondition extends AbstractTextCondition implements IContentCondition, IUserCondition {
+class UserEmailCondition extends AbstractTextCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see \wcf\system\condition\AbstractTextCondition::$fieldName
*/
protected $label = 'wcf.user.email';
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- $userList->getConditionBuilder()->add('user_table.email LIKE ?', array('%'.addcslashes($condition->email, '_%').'%'));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ $objectList->getConditionBuilder()->add('user_table.email LIKE ?', array('%'.addcslashes($conditionData['email'], '_%').'%'));
}
/**
use wcf\data\condition\Condition;
use wcf\data\user\group\UserGroup;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use wcf\util\ArrayUtil;
* @subpackage system.condition
* @category Community Framework
*/
-class UserGroupCondition extends AbstractMultipleFieldsCondition implements IContentCondition, IUserCondition {
+class UserGroupCondition extends AbstractMultipleFieldsCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see \wcf\system\condition\AbstractMultipleFieldsCondition::$descriptions
*/
protected $userGroups = null;
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- if ($condition->groupIDs !== null) {
- $userList->getConditionBuilder()->add('user_table.userID IN (SELECT userID FROM wcf'.WCF_N.'_user_to_group WHERE groupID IN (?) GROUP BY userID HAVING COUNT(userID) = ?)', array($condition->groupIDs, count($condition->groupIDs)));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ if (isset($conditionData['groupIDs'])) {
+ $objectList->getConditionBuilder()->add('user_table.userID IN (SELECT userID FROM wcf'.WCF_N.'_user_to_group WHERE groupID IN (?) GROUP BY userID HAVING COUNT(userID) = ?)', array($conditionData['groupIDs'], count($conditionData['groupIDs'])));
}
- if ($condition->notGroupIDs !== null) {
- $userList->getConditionBuilder()->add('user_table.userID NOT IN (SELECT userID FROM wcf'.WCF_N.'_user_to_group WHERE groupID IN (?))', array($condition->notGroupIDs));
+ if (isset($conditionData['notGroupIDs'])) {
+ $objectList->getConditionBuilder()->add('user_table.userID NOT IN (SELECT userID FROM wcf'.WCF_N.'_user_to_group WHERE groupID IN (?))', array($conditionData['notGroupIDs']));
}
}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\WCF;
/**
* @subpackage system.condition
* @category Community Framework
*/
-class UserIntegerPropertyCondition extends AbstractIntegerCondition implements IContentCondition, IUserCondition {
+class UserIntegerPropertyCondition extends AbstractIntegerCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- if ($condition->greaterThan !== null) {
- $userList->getConditionBuilder()->add('user_table.'.$this->getDecoratedObject()->propertyname.' > ?', array($condition->greaterThan));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ if (isset($conditionData['greaterThan'])) {
+ $objectList->getConditionBuilder()->add('user_table.'.$this->getDecoratedObject()->propertyname.' > ?', array($conditionData['greaterThan']));
}
- if ($condition->lessThan !== null) {
- $userList->getConditionBuilder()->add('user_table.'.$this->getDecoratedObject()->propertyname.' < ?', array($condition->lessThan));
+ if (isset($conditionData['lessThan'])) {
+ $objectList->getConditionBuilder()->add('user_table.'.$this->getDecoratedObject()->propertyname.' < ?', array($conditionData['lessThan']));
}
}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\exception\UserInputException;
use wcf\system\language\LanguageFactory;
use wcf\system\WCF;
* @subpackage system.condition
* @category Community Framework
*/
-class UserLanguageCondition extends AbstractSingleFieldCondition implements IContentCondition, IUserCondition {
+class UserLanguageCondition extends AbstractSingleFieldCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see \wcf\system\condition\AbstractSingleFieldCondition::$label
*/
protected $languageIDs = array();
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- $userList->getConditionBuilder()->add('user_table.languageID IN (?)', array($condition->conditionData['languageIDs']));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ $objectList->getConditionBuilder()->add('user_table.languageID IN (?)', array($conditionData['languageIDs']));
}
/**
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
use wcf\data\DatabaseObject;
+use wcf\data\DatabaseObjectList;
use wcf\system\option\user\UserOptionHandler;
use wcf\system\WCF;
* @subpackage system.condition
* @category Community Framework
*/
-class UserOptionsCondition extends AbstractMultipleFieldsCondition implements IContentCondition, IUserCondition {
+class UserOptionsCondition extends AbstractMultipleFieldsCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* user option handler object
* @var \wcf\system\option\user\UserOptionHandler
}
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- $optionValues = $condition->optionValues;
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ $optionValues = $conditionData['optionValues'];
foreach ($this->optionHandler->getCategoryOptions('profile') as $option) {
$option = $option['object'];
if (isset($optionValues[$option->optionName])) {
- $this->optionHandler->getTypeObject($option->optionType)->addCondition($userList, $option, $optionValues[$option->optionName]);
+ $this->optionHandler->getTypeObject($option->optionType)->addCondition($objectList, $option, $optionValues[$option->optionName]);
}
}
}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
* @subpackage system.condition
* @category Community Framework
*/
-class UserRegistrationDateCondition extends AbstractSingleFieldCondition implements IContentCondition, IUserCondition {
+class UserRegistrationDateCondition extends AbstractSingleFieldCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see \wcf\system\condition\AbstractSingleFieldCondition::$label
*/
protected $registrationDateStart = '';
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- if ($condition->registrationDateEnd !== null) {
- $userList->getConditionBuilder()->add('user_table.registrationDate < ?', array(strtotime($condition->registrationDateEnd) + 86400));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ if (isset($conditionData['registrationDateEnd'])) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate < ?', array(strtotime($conditionData['registrationDateEnd']) + 86400));
}
- if ($condition->registrationDateStart !== null) {
- $userList->getConditionBuilder()->add('user_table.registrationDate >= ?', array(strtotime($condition->registrationDateStart)));
+ if (isset($conditionData['registrationDateStart'])) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate >= ?', array(strtotime($conditionData['registrationDateStart'])));
}
}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\WCF;
/**
* @subpackage system.condition
* @category Community Framework
*/
-class UserRegistrationDateIntervalCondition extends AbstractIntegerCondition implements IContentCondition, IUserCondition {
+class UserRegistrationDateIntervalCondition extends AbstractIntegerCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see \wcf\system\condition\AbstractMultipleFieldsCondition::$languageItemPrefix
*/
protected $minValue = 0;
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- if ($condition->greaterThan !== null) {
- $userList->getConditionBuilder()->add('user_table.registrationDate < ?', array(TIME_NOW - $condition->greaterThan * 86400));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ if ($conditionData['greaterThan'] !== null) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate < ?', array(TIME_NOW - $conditionData['greaterThan'] * 86400));
}
- if ($condition->lessThan !== null) {
- $userList->getConditionBuilder()->add('user_table.registrationDate > ?', array(TIME_NOW - $condition->lessThan * 86400));
+ if ($conditionData['lessThan'] !== null) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate > ?', array(TIME_NOW - $conditionData['lessThan'] * 86400));
}
}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
* @subpackage system.condition
* @category Community Framework
*/
-class UserStateCondition extends AbstractSingleFieldCondition implements IContentCondition, IUserCondition {
+class UserStateCondition extends AbstractSingleFieldCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see \wcf\system\condition\AbstractSingleFieldCondition::$label
*/
protected $userIsNotBanned = 0;
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- if ($condition->userIsBanned !== null) {
- $userList->getConditionBuilder()->add('user_table.banned = ?', array($condition->userIsBanned));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ if (isset($conditionData['userIsBanned'])) {
+ $userList->getConditionBuilder()->add('user_table.banned = ?', array($conditionData['userIsBanned']));
}
- if ($condition->userIsEnabled !== null) {
- if ($condition->userIsEnabled) {
+ if ($conditionData['userIsEnabled']) {
+ if ($conditionData['userIsEnabled']) {
$userList->getConditionBuilder()->add('user_table.activationCode = ?', array(0));
}
else {
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\system\WCF;
+
+/**
+ * Condition implementation for compairing a user-bound timestamp with a fixed time
+ * interval.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.condition
+ * @category Community Framework
+ */
+class UserTimestampPropertyCondition extends AbstractTimestampCondition implements IContentCondition, IUserCondition {
+ use TObjectUserCondition;
+ use TObjectListUserCondition;
+
+ /**
+ * @see \wcf\system\condition\AbstractTimestampCondition::$className
+ */
+ protected $className = User::class;
+
+ /**
+ * @see \wcf\system\condition\AbstractTimestampCondition::getLanguageItemPrefix()
+ */
+ protected function getLanguageItemPrefix() {
+ return 'wcf.user.condition';
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractTimestampCondition::getPropertyName()
+ */
+ protected function getPropertyName() {
+ return $this->getDecoratedObject()->propertyname;
+ }
+
+ /**
+ * @see \wcf\system\condition\IContentCondition::showContent()
+ */
+ public function showContent(Condition $condition) {
+ if (!WCF::getUser()->userID) return false;
+
+ return $this->checkUser($condition, WCF::getUser());
+ }
+}
namespace wcf\system\condition;
use wcf\data\condition\Condition;
use wcf\data\user\User;
-use wcf\data\user\UserList;
+use wcf\data\DatabaseObjectList;
use wcf\system\WCF;
/**
* @subpackage system.condition
* @category Community Framework
*/
-class UserUsernameCondition extends AbstractTextCondition implements IContentCondition, IUserCondition {
+class UserUsernameCondition extends AbstractTextCondition implements IContentCondition, IObjectListCondition, IUserCondition {
+ use TObjectListUserCondition;
+
/**
* @see \wcf\system\condition\AbstractTextCondition::$fieldName
*/
protected $label = 'wcf.user.username';
/**
- * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ * @see \wcf\system\condition\IObjectListCondition::addObjectListCondition()
*/
- public function addUserCondition(Condition $condition, UserList $userList) {
- $userList->getConditionBuilder()->add('user_table.username LIKE ?', array('%'.addcslashes($condition->username, '_%').'%'));
+ public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
+ if (!($objectList instanceof UserList)) return;
+
+ $objectList->getConditionBuilder()->add('user_table.username LIKE ?', array('%'.addcslashes($conditionData['username'], '_%').'%'));
}
/**
<item name="wcf.acp.user.revertChanges.timeframe"><![CDATA[Zeitraum]]></item>
<item name="wcf.acp.user.revertChanges.timeframe.description"><![CDATA[Zeitraum in dem Änderungen des Benutzers zurückgesetzt werden sollen. Inhalte werden auf die neuste Version, welche entweder älter als der angegebene Zeitraum ist oder welche von einem anderen Nutzer stammt, zurückgesetzt. [Zeitraum in Tagen]]]></item>
<item name="wcf.acp.user.revertChanges.markedUsers"><![CDATA[Änderungen folgender Nutzer zurücksetzen]]></item>
- <item name="wcf.acp.user.bulkProcessing"><![CDATA[Benutzer-Massenbearbeitung]]></item>
- <item name="wcf.acp.user.bulkProcessing.action"><![CDATA[Aktion]]></item>
- <item name="wcf.acp.user.bulkProcessing.conditions"><![CDATA[Bedingungen]]></item>
- <item name="wcf.acp.user.bulkProcessing.success"><![CDATA[Die gewählte Aktion wurde erfolgreich auf {#$affectedUsers} Benutzer ausgeführt.]]></item>
- <item name="wcf.acp.user.bulkProcessing.warning"><![CDATA[Die Massenbearbeitung von Benutzern führt die unten ausgewählte Aktion <b>ohne zusätzliche Sicherheitsabfrage</b> bei allen Benutzern aus, die unter die eingestellten Bedingungen fallen.]]></item>
<item name="wcf.acp.user.search"><![CDATA[Benutzer suchen]]></item>
<item name="wcf.acp.user.search.conditions.general"><![CDATA[Allgemein]]></item>
<item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profil]]></item>
<item name="wcf.acp.user.notificationPresetSettings.description"><![CDATA[Sie können auf dieser Seite die Standardeinstellungen für neue Benutzer festlegen, dies wirkt sich nicht auf bestehende Benutzer aus. Benutzer können abweichende Einstellungen festlegen.]]></item>
<item name="wcf.acp.user.notificationPresetSettings.applyChangesToExistingUsers"><![CDATA[Änderungen auch auf bestehende Benutzerkonten anwenden]]></item>
<item name="wcf.acp.user.notificationPresetSettings.applyChangesToExistingUsers.description"><![CDATA[Die hier eingestellten Änderungen der Vorgabewerte für Benachrichtigungen werden auch in bestehende Benutzerkonten übernommen. Die entsprechenden Einstellungen der Benutzer werden dabei überschrieben.]]></item>
+
+ <item name="wcf.acp.user.bulkProcessing"><![CDATA[Benutzer-Massenbearbeitung]]></item>
+ <item name="wcf.acp.user.bulkProcessing.action"><![CDATA[Aktion]]></item>
+ <item name="wcf.acp.user.bulkProcessing.assignToUserGroups"><![CDATA[Benutzergruppen zuweisen]]></item>
+ <item name="wcf.acp.user.bulkProcessing.conditions"><![CDATA[Bedingungen]]></item>
+ <item name="wcf.acp.user.bulkProcessing.delete"><![CDATA[Benutzer löschen]]></item>
+ <item name="wcf.acp.user.bulkProcessing.exportMailAddress"><![CDATA[E-Mail-Adressen exportieren]]></item>
+ <item name="wcf.acp.user.bulkProcessing.removeFromUserGroups"><![CDATA[Aus Benutzergruppen entfernen]]></item>
+ <item name="wcf.acp.user.bulkProcessing.sendMail"><![CDATA[E-Mail an Benutzer senden]]></item>
+ <item name="wcf.acp.user.bulkProcessing.success"><![CDATA[Die gewählte Aktion wurde auf {#$affectedObjectCount} Benutzer ausgeführt.]]></item>
+ <item name="wcf.acp.user.bulkProcessing.warning"><![CDATA[Die Massenbearbeitung von Benutzern führt die unten ausgewählte Aktion <b>ohne zusätzliche Sicherheitsabfrage</b> bei allen Benutzern aus, die unter die eingestellten Bedingungen fallen.]]></item>
</category>
<category name="wcf.acp.worker">
<item name="wcf.global.button.showAll"><![CDATA[Alle anzeigen]]></item>
<item name="wcf.global.reason"><![CDATA[Begründung]]></item>
<item name="wcf.global.settings"><![CDATA[Einstellungen]]></item>
+ <item name="wcf.global.bulkProcessing.warning"><![CDATA[Die Massenbearbeitung führt die unten ausgewählte Aktion <b>ohne zusätzliche Sicherheitsabfrage</b> aus!]]></item>
</category>
<category name="wcf.global.form">
<item name="wcf.user.condition.groupIDs"><![CDATA[in Benutzergruppen]]></item>
<item name="wcf.user.condition.groupIDs.description"><![CDATA[Benutzer müssen in den ausgewählten Benutzergruppen Mitglied sein.]]></item>
<item name="wcf.user.condition.languages"><![CDATA[Sprachen]]></item>
+ <item name="wcf.user.condition.lastActivityTime"><![CDATA[Letzte Aktivität]]></item>
<item name="wcf.user.condition.likesReceived"><![CDATA[Erhaltene Likes]]></item>
<item name="wcf.user.condition.mobileBrowser"><![CDATA[Mobiler Browser]]></item>
<item name="wcf.user.condition.mobileBrowser.usesMobileBrowser"><![CDATA[Verwendet mobilen Browser]]></item>
<item name="wcf.acp.user.revertChanges.timeframe"><![CDATA[Timeframe]]></item>
<item name="wcf.acp.user.revertChanges.timeframe.description"><![CDATA[Changes made in this timeframe will be reverted to the newest version that is either older than the given timeframe or made by an unrelated user [time in days]]]></item>
<item name="wcf.acp.user.revertChanges.markedUsers"><![CDATA[Revert changes by the following users]]></item>
- <item name="wcf.acp.user.bulkProcessing"><![CDATA[Bulk Processing]]></item>
- <item name="wcf.acp.user.bulkProcessing.action"><![CDATA[Actions]]></item>
- <item name="wcf.acp.user.bulkProcessing.conditions"><![CDATA[Conditions]]></item>
- <item name="wcf.acp.user.bulkProcessing.success"><![CDATA[Executed action affected {#$affectedUsers} user{if $affectedUsers != 1}s{/if}.]]></item>
- <item name="wcf.acp.user.bulkProcessing.warning"><![CDATA[Heads up! The bulk processing executes all actions below without any further confirmation prompt!]]></item>
<item name="wcf.acp.user.search"><![CDATA[Search Users]]></item>
<item name="wcf.acp.user.search.conditions.general"><![CDATA[General]]></item>
<item name="wcf.acp.user.search.conditions.profile"><![CDATA[Profile]]></item>
<item name="wcf.acp.user.notificationPresetSettings.applyChangesToExistingUsers"><![CDATA[Apply changes for existing users too]]></item>
<item name="wcf.acp.user.notificationPresetSettings.applyChangesToExistingUsers.description"><![CDATA[Any changes to default notification settings will be applied to existing users. This overrides all affected settings previously changed by the respective user itself.]]></item>
+ <item name="wcf.acp.user.bulkProcessing"><![CDATA[User Bulk Processing]]></item>
+ <item name="wcf.acp.user.bulkProcessing.action"><![CDATA[Action]]></item>
+ <item name="wcf.acp.user.bulkProcessing.assignToUserGroups"><![CDATA[Assign to User Groups]]></item>
+ <item name="wcf.acp.user.bulkProcessing.conditions"><![CDATA[Conditions]]></item>
+ <item name="wcf.acp.user.bulkProcessing.delete"><![CDATA[Delete Users]]></item>
+ <item name="wcf.acp.user.bulkProcessing.exportMailAddress"><![CDATA[Export Email Addresses]]></item>
+ <item name="wcf.acp.user.bulkProcessing.removeFromUserGroups"><![CDATA[Remove from User Groups]]></item>
+ <item name="wcf.acp.user.bulkProcessing.sendMail"><![CDATA[Send Email to Users]]></item>
+ <item name="wcf.acp.user.bulkProcessing.success"><![CDATA[The selection action has been executed and affected {#$affectedObjectCount} user{if $affectedUsers != 1}s{/if}.]]></item>
+ <item name="wcf.acp.user.bulkProcessing.warning"><![CDATA[Heads up! The bulk processing executes all actions below on all users matching the seleced conditions without any further confirmation prompt!]]></item>
</category>
<category name="wcf.acp.worker">