<parent>wcf.acp.menu.link.group</parent>
<permissions>admin.user.canMailUser</permissions>
</acpmenuitem>
+
+ <acpmenuitem name="wcf.acp.menu.link.group.assignment">
+ <controller><![CDATA[wcf\acp\page\UserGroupAssignmentListPage]]></controller>
+ <parent>wcf.acp.menu.link.group</parent>
+ <permissions>admin.user.canManageGroupAssignment</permissions>
+ </acpmenuitem>
<!-- user groups -->
<acpmenuitem name="wcf.acp.menu.link.user.rank">
<canbeedited>1</canbeedited>
<canbedisabled>1</canbedisabled>
</cronjob>
+
+ <cronjob>
+ <classname><![CDATA[wcf\system\cronjob\UserGroupAssignmentCronjob]]></classname>
+ <description><![CDATA[Automatically assigns users to user groups]]></description>
+ <description language="de"><![CDATA[Ordnet Benutzer automatisch Benutzergruppen zu]]></description>
+ <startminute>*/30</startminute>
+ <starthour>*</starthour>
+ <startdom>*</startdom>
+ <startmonth>*</startmonth>
+ <startdow>*</startdow>
+ <active>1</active>
+ <canbeedited>1</canbeedited>
+ <canbedisabled>1</canbedisabled>
+ </cronjob>
</import>
</data>
\ No newline at end of file
<classname><![CDATA[wcf\system\stat\DislikeStatDailyHandler]]></classname>
</type>
<!-- /stat handlers -->
+
+ <!-- user group assignment conditions -->
+ <type>
+ <name>com.woltlab.wcf.username</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserUsernameCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.email</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserEmailCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.userGroup</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserGroupCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.languages</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserLanguageCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.registrationDate</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserRegistrationDateCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.registrationDateInterval</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserRegistrationDateIntervalCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.avatar</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserAvatarCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.state</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserStateCondition]]></classname>
+ <conditiongroup>general</conditiongroup>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.activityPoints</name>
+ <definitionname>com.woltlab.wcf.condition.userGroupAssignment</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.condition.userGroupAssignment</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.condition.userGroupAssignment</definitionname>
+ <classname><![CDATA[wcf\system\condition\UserOptionsCondition]]></classname>
+ <conditiongroup>userOptions</conditiongroup>
+ </type>
+ <!-- /user group assignment conditions -->
</import>
-</data>
\ No newline at end of file
+</data>
<name>com.woltlab.wcf.statDailyHandler</name>
<interfacename><![CDATA[wcf\system\stat\IStatDailyHandler]]></interfacename>
</definition>
+
+ <definition>
+ <name>com.woltlab.wcf.condition.userGroupAssignment</name>
+ <interfacename><![CDATA[wcf\system\condition\IUserCondition]]></interfacename>
+ </definition>
</import>
</data>
<defaultvalue>0</defaultvalue>
<admindefaultvalue>1</admindefaultvalue>
</option>
+ <option name="admin.user.canManageGroupAssignment">
+ <categoryname>admin.user.group</categoryname>
+ <optiontype>boolean</optiontype>
+ <defaultvalue>0</defaultvalue>
+ <admindefaultvalue>1</admindefaultvalue>
+ </option>
<option name="admin.user.canManageUserOption">
<categoryname>admin.user.option</categoryname>
--- /dev/null
+<div class="tabMenuContainer">
+ <nav class="tabMenu">
+ <ul>
+ {foreach from=$groupedObjectTypes key='conditionGroup' item='conditionObjectTypes'}
+ {assign var='__anchor' value='user_'|concat:$conditionGroup}
+ <li><a href="{@$__wcf->getAnchor($__anchor)}">{lang}wcf.user.condition.conditionGroup.{$conditionGroup}{/lang}</a></li>
+ {/foreach}
+ </ul>
+ </nav>
+
+ {foreach from=$groupedObjectTypes key='conditionGroup' item='conditionObjectTypes'}
+ <div id="user_{$conditionGroup}" class="container containerPadding tabMenuContainer tabMenuContent">
+ {if $conditionGroup != 'userOptions'}
+ <fieldset>
+ <legend>{lang}wcf.user.condition.conditionGroup.{$conditionGroup}{/lang}</legend>
+ {/if}
+
+ {foreach from=$conditionObjectTypes item='condition'}
+ {@$condition->getProcessor()->getHtml()}
+ {/foreach}
+
+ {if $conditionGroup != 'userOptions'}
+ </fieldset>
+ {/if}
+ </div>
+ {/foreach}
+</div>
--- /dev/null
+{include file='header' pageTitle='wcf.acp.group.assignment.'|concat:$action}
+
+<script data-relocate="true">
+ //<![CDATA[
+ $(function() {
+ WCF.TabMenu.init();
+ });
+ //]]>
+</script>
+
+<header class="boxHeadline">
+ <h1>{lang}wcf.acp.group.assignment.{$action}{/lang}</h1>
+</header>
+
+{include file='formError'}
+
+{if $success|isset}
+ <p class="success">{lang}wcf.global.success.{@$action}{/lang}</p>
+{/if}
+
+<div class="contentNavigation">
+ <nav>
+ <ul>
+ <li><a href="{link controller='UserGroupAssignmentList'}{/link}" class="button"><span class="icon icon16 icon-list"></span> <span>{lang}wcf.acp.group.assignment.button.list{/lang}</span></a></li>
+
+ {event name='contentNavigationButtons'}
+ </ul>
+ </nav>
+</div>
+
+<form method="post" action="{if $action == 'add'}{link controller='UserGroupAssignmentAdd'}{/link}{else}{link controller='UserGroupAssignmentEdit' object=$assignment}{/link}{/if}">
+ <div class="container containerPadding marginTop">
+ <fieldset>
+ <legend>{lang}wcf.global.form.data{/lang}</legend>
+
+ <dl{if $errorField == 'title'} class="formError"{/if}>
+ <dt><label for="title">{lang}wcf.global.name{/lang}</label></dt>
+ <dd>
+ <input type="text" id="title" name="title" value="{$title}" class="long" />
+ {if $errorField == 'title'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {else}
+ {lang}wcf.acp.group.assignment.title.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+
+ <dl{if $errorField == 'groupID'} class="formError"{/if}>
+ <dt><label for="groupID">{lang}wcf.user.group{/lang}</label></dt>
+ <dd>
+ {htmlOptions name='groupID' options=$userGroups selected=$groupID}
+ {if $errorField == 'groupID'}
+ <small class="innerError">{lang}wcf.acp.group.assignment.groupID.error.{@$errorType}{/lang}</small>
+ {/if}
+ </dd>
+ </dl>
+
+ <dl class="formError">
+ <dt></dt>
+ <dd>
+ <label><input type="checkbox" id="isDisabled" name="isDisabled"{if $isDisabled} checked="checked"{/if} /> {lang}wcf.acp.group.assignment.isDisabled{/lang}</label>
+ </dd>
+ </dl>
+
+ {event name='dataFields'}
+ </fieldset>
+
+ {event name='fieldsets'}
+ </div>
+
+ <header class="boxHeadline boxSubHeadline">
+ <h2>{lang}wcf.acp.group.assignment.conditions{/lang}</h2>
+ <small>{lang}wcf.acp.group.assignment.conditions.description{/lang}</small>
+ </header>
+
+ {if $errorField == 'conditions'}
+ <p class="error">{lang}wcf.acp.group.assignment.error.noConditions{/lang}</p>
+ {/if}
+
+ {include file='userConditions'}
+
+ <div class="formSubmit">
+ <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
+ <input type="hidden" name="action" value="{@$action}" />
+ {@SECURITY_TOKEN_INPUT_TAG}
+ </div>
+</form>
+
+{include file='footer'}
--- /dev/null
+{include file='header' pageTitle='wcf.acp.group.assignment.list'}
+
+<script data-relocate="true">
+ //<![CDATA[
+ $(function() {
+ new WCF.Action.Delete('wcf\\data\\user\\group\\assignment\\UserGroupAssignmentAction', '.jsUserGroupAssignmentRow');
+ new WCF.Action.Toggle('wcf\\data\\user\\group\\assignment\\UserGroupAssignmentAction', '.jsUserGroupAssignmentRow');
+
+ var options = { };
+ {if $pages > 1}
+ options.refreshPage = true;
+ {if $pages == $pageNo}
+ options.updatePageNumber = -1;
+ {/if}
+ {else}
+ options.emptyMessage = '{lang}wcf.global.noItems{/lang}';
+ {/if}
+
+ new WCF.Table.EmptyTableHandler($('#userGroupAssignmentTableContainer'), 'jsUserGroupAssignmentRow', options);
+ });
+ //]]>
+</script>
+
+<header class="boxHeadline">
+ <h1>{lang}wcf.acp.group.assignment.list{/lang}</h1>
+</header>
+
+<div class="contentNavigation">
+ {pages print=true assign=pagesLinks controller="UserGroupAssignmentList" link="pageNo=%d"}
+
+ <nav>
+ <ul>
+ <li><a href="{link controller='UserGroupAssignmentAdd'}{/link}" class="button"><span class="icon icon16 icon-plus"></span> <span>{lang}wcf.acp.group.assignment.button.add{/lang}</span></a></li>
+
+ {event name='contentNavigationButtonsTop'}
+ </ul>
+ </nav>
+</div>
+
+{if $objects|count}
+ <div class="tabularBox tabularBoxTitle marginTop" id="userGroupAssignmentTableContainer">
+ <header>
+ <h2>{lang}wcf.acp.group.assignment.list{/lang} <span class="badge badgeInverse">{#$items}</span></h2>
+ </header>
+
+ <table class="table">
+ <thead>
+ <tr>
+ <th class="columnID columnAssignmentID" colspan="2"><span>{lang}wcf.global.objectID{/lang}</span></th>
+ <th class="columnTitle columnAssignmentName"><span>{lang}wcf.global.name{/lang}</span></th>
+ <th class="columnTitle columnGroupName"><span>{lang}wcf.acp.group.assignment.userGroup{/lang}</span></th>
+
+ {event name='columnHeads'}
+ </tr>
+ </thead>
+
+ <tbody>
+ {foreach from=$objects item='assignment'}
+ <tr class="jsUserGroupAssignmentRow">
+ <td class="columnIcon">
+ <span class="icon icon16 icon-check{if $assignment->isDisabled}-empty{/if} jsToggleButton jsTooltip pointer" title="{lang}wcf.global.button.{if $assignment->isDisabled}enable{else}disable{/if}{/lang}" data-object-id="{@$assignment->assignmentID}" data-disable-message="{lang}wcf.global.button.disable{/lang}" data-enable-message="{lang}wcf.global.button.enable{/lang}"></span>
+ <a href="{link controller='UserGroupAssignmentEdit' object=$assignment}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip"><span class="icon icon16 icon-pencil"></span></a>
+ <span class="icon icon16 icon-remove jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$assignment->assignmentID}" data-confirm-message="{lang}wcf.acp.group.assignment.delete.confirmMessage{/lang}"></span>
+
+ {event name='rowButtons'}
+ </td>
+ <td class="columnID columnAssignmentID">{@$assignment->assignmentID}</td>
+ <td class="columnTitle columnAssignmentName">
+ <a href="{link controller='UserGroupAssignmentEdit' object=$assignment}{/link}">{$assignment->title}</a>
+ </td>
+ <td class="columnDigits columnGroupName">
+ {$assignment->getUserGroup()->getName()}
+ </td>
+
+ {event name='columns'}
+ </tr>
+ {/foreach}
+ </tbody>
+ </table>
+ </div>
+
+ <div class="contentNavigation">
+ {@$pagesLinks}
+
+ <nav>
+ <ul>
+ <li><a href="{link controller='UserGroupAssignmentAdd'}{/link}" class="button"><span class="icon icon16 icon-plus"></span> <span>{lang}wcf.acp.group.assignment.button.add{/lang}</span></a></li>
+
+ {event name='contentNavigationButtonsBottom'}
+ </ul>
+ </nav>
+ </div>
+{else}
+ <p class="info">{lang}wcf.global.noItems{/lang}</p>
+{/if}
+
+{include file='footer'}
--- /dev/null
+{foreach from=$optionTree item='category'}
+ <fieldset>
+ <legend>{lang}wcf.user.option.category.{@$category[object]->categoryName}{/lang}</legend>
+ {hascontent}<p>{content}{lang __optional=true}wcf.user.option.category.{@$category[object]->categoryName}.description{/lang}{/content}</p>{/hascontent}
+
+ {include file='optionFieldList' options=$category[options] langPrefix='wcf.user.option.'}
+ </fieldset>
+{/foreach}
--- /dev/null
+<?php
+namespace wcf\acp\form;
+use wcf\data\user\group\assignment\UserGroupAssignmentAction;
+use wcf\data\user\group\UserGroup;
+use wcf\form\AbstractForm;
+use wcf\system\condition\ConditionHandler;
+use wcf\system\exception\UserInputException;
+use wcf\system\user\group\assignment\UserGroupAssignmentHandler;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Shows the form to create a new automatic user group assignment.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserGroupAssignmentAddForm extends AbstractForm {
+ /**
+ * @see \wcf\page\AbstractPage::$activeMenuItem
+ */
+ public $activeMenuItem = 'wcf.acp.menu.link.group.assignment';
+
+ /**
+ * list of grouped user group assignment condition object types
+ * @var array
+ */
+ public $conditions = array();
+
+ /**
+ * id of the selected user group
+ * @var integer
+ */
+ public $groupID = 0;
+
+ /**
+ * true if the automatic assignment is disabled
+ * @var integer
+ */
+ public $isDisabled = 0;
+
+ /**
+ * @see \wcf\page\AbstractPage::$neededPermissions
+ */
+ public $neededPermissions = array('admin.user.canManageGroupAssignment');
+
+ /**
+ * title of the user group assignment
+ * @var string
+ */
+ public $title = '';
+
+ /**
+ * list of selectable user groups
+ * @var array<\wcf\data\user\group\UserGroup>
+ */
+ public $userGroups = array();
+
+ /**
+ * @see \wcf\page\IPage::assignVariables()
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ WCF::getTPL()->assign(array(
+ 'action' => 'add',
+ 'groupedObjectTypes' => $this->conditions,
+ 'groupID' => $this->groupID,
+ 'isDisabled' => $this->isDisabled,
+ 'title' => $this->title,
+ 'userGroups' => $this->userGroups
+ ));
+ }
+
+ /**
+ * @see \wcf\page\IPage::readData()
+ */
+ public function readData() {
+ $this->userGroups = UserGroup::getGroupsByType(array(UserGroup::OTHER));
+ foreach ($this->userGroups as $key => $userGroup) {
+ if (!$userGroup->isAccessible()) {
+ unset($this->userGroups[$key]);
+ }
+ }
+
+ uasort($this->userGroups, function(UserGroup $groupA, UserGroup $groupB) {
+ return strcmp($groupA->getName(), $groupB->getName());
+ });
+
+ $this->conditions = UserGroupAssignmentHandler::getInstance()->getGroupedObjectTypes('com.woltlab.wcf.condition.userGroupAssignment');
+
+ parent::readData();
+ }
+
+ /**
+ * @see \wcf\form\IForm::readFormParameters()
+ */
+ public function readFormParameters() {
+ parent::readFormParameters();
+
+ if (isset($_POST['groupID'])) $this->groupID = intval($_POST['groupID']);
+ if (isset($_POST['isDisabled'])) $this->isDisabled = 1;
+ if (isset($_POST['title'])) $this->title = StringUtil::trim($_POST['title']);
+
+ foreach ($this->conditions as $conditions) {
+ foreach ($conditions as $condition) {
+ $condition->getProcessor()->readFormParameters();
+ }
+ }
+ }
+
+ /**
+ * @see \wcf\form\IForm::save()
+ */
+ public function save() {
+ parent::save();
+
+ $this->objectAction = new UserGroupAssignmentAction(array(), 'create', array(
+ 'data' => array(
+ 'groupID' => $this->groupID,
+ 'isDisabled' => $this->isDisabled,
+ 'title' => $this->title
+ )
+ ));
+ $returnValues = $this->objectAction->executeAction();
+
+ ConditionHandler::getInstance()->createConditions($returnValues['returnValues']->assignmentID, $this->conditions);
+
+ $this->saved();
+
+ // reset values
+ $this->groupID = 0;
+ $this->isDisabled = 0;
+ $this->title = '';
+
+ foreach ($this->conditions as $conditions) {
+ foreach ($conditions as $condition) {
+ $condition->getProcessor()->reset();
+ }
+ }
+
+ WCF::getTPL()->assign('success', true);
+ }
+
+ /**
+ * @see \wcf\form\IForm::validate()
+ */
+ public function validate() {
+ parent::validate();
+
+ if (empty($this->title)) {
+ throw new UserInputException('title');
+ }
+ if (strlen($this->title) > 255) {
+ throw new UserInputException('title', 'tooLong');
+ }
+
+ if (!isset($this->userGroups[$this->groupID])) {
+ throw new UserInputException('groupID', 'notValid');
+ }
+
+ $hasData = false;
+ foreach ($this->conditions as $conditions) {
+ foreach ($conditions as $condition) {
+ $condition->getProcessor()->validate();
+
+ if (!$hasData && $condition->getProcessor()->getData() !== null) {
+ $hasData = true;
+ }
+ }
+ }
+
+ if (!$hasData) {
+ throw new UserInputException('conditions');
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\acp\form;
+use wcf\data\user\group\assignment\UserGroupAssignment;
+use wcf\data\user\group\assignment\UserGroupAssignmentAction;
+use wcf\form\AbstractForm;
+use wcf\system\condition\ConditionHandler;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\WCF;
+
+/**
+ * Shows the form to edit an existing automatic user group assignment.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserGroupAssignmentEditForm extends UserGroupAssignmentAddForm {
+ /**
+ * edited automatic user group assignment
+ * @var \wcf\data\user\group\assignment\UserGroupAssignment
+ */
+ public $assignment = null;
+
+ /**
+ * id of the edited automatic user group assignment
+ * @var integer
+ */
+ public $assignmentID = 0;
+
+ /**
+ * @see \wcf\page\IPage::assignVariables()
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ WCF::getTPL()->assign(array(
+ 'action' => 'edit',
+ 'assignment' => $this->assignment
+ ));
+ }
+
+ /**
+ * @see \wcf\page\IPage::readData()
+ */
+ public function readData() {
+ parent::readData();
+
+ if (empty($_POST)) {
+ $this->groupID = $this->assignment->groupID;
+ $this->title = $this->assignment->title;
+
+ $conditions = $this->assignment->getConditions();
+ foreach ($conditions as $condition) {
+ $this->conditions[$condition->getObjectType()->conditiongroup][$condition->objectTypeID]->getProcessor()->setData($condition);
+ }
+ }
+ }
+
+ /**
+ * @see \wcf\page\IPage::readParameters()
+ */
+ public function readParameters() {
+ parent::readParameters();
+
+ if (isset($_REQUEST['id'])) $this->assignmentID = intval($_REQUEST['id']);
+ $this->assignment = new UserGroupAssignment($this->assignmentID);
+ if (!$this->assignment->assignmentID) {
+ throw new IllegalLinkException();
+ }
+ }
+
+ /**
+ * @see \wcf\form\IForm::save()
+ */
+ public function save() {
+ AbstractForm::save();
+
+ $this->objectAction = new UserGroupAssignmentAction(array($this->assignment), 'update', array(
+ 'data' => array(
+ 'groupID' => $this->groupID,
+ 'isDisabled' => $this->isDisabled,
+ 'title' => $this->title
+ )
+ ));
+ $returnValues = $this->objectAction->executeAction();
+
+ ConditionHandler::getInstance()->updateConditions($this->assignment->assignmentID, $this->assignment->getConditions(), $this->conditions);
+
+ $this->saved();
+
+ WCF::getTPL()->assign('success', true);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\acp\page;
+use wcf\page\MultipleLinkPage;
+
+/**
+ * Lists the available automatic user group assignments.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage acp.page
+ * @category Community Framework
+ */
+class UserGroupAssignmentListPage extends MultipleLinkPage {
+ /**
+ * @see \wcf\page\AbstractPage::$activeMenuItem
+ */
+ public $activeMenuItem = 'wcf.acp.menu.link.group.assignment';
+
+ /**
+ * @see \wcf\page\AbstractPage::$neededPermissions
+ */
+ public $neededPermissions = array('admin.user.canManageGroupAssignment');
+
+ /**
+ * @see \wcf\page\MultipleLinkPage::$objectListClassName
+ */
+ public $objectListClassName = 'wcf\data\user\group\assignment\UserGroupAssignmentList';
+}
--- /dev/null
+<?php
+namespace wcf\data\condition;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents a condition.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.condition
+ * @category Community Framework
+ */
+class Condition extends DatabaseObject {
+ /**
+ * @see \wcf\data\DatabaseObject::$databaseTableIndexName
+ */
+ protected static $databaseTableIndexName = 'conditionID';
+
+ /**
+ * @see \wcf\data\DatabaseObject::$databaseTableName
+ */
+ protected static $databaseTableName = 'condition';
+
+ /**
+ * @see \wcf\data\IStorableObject::__get()
+ */
+ public function __get($name) {
+ $value = parent::__get($name);
+
+ // treat condition data as data variables if it is an array
+ if ($value === null && is_array($this->data['conditionData']) && isset($this->data['conditionData'][$name])) {
+ $value = $this->data['conditionData'][$name];
+ }
+
+ return $value;
+ }
+
+ /**
+ * Returns the condition object type of the condition.
+ *
+ * @return \wcf\data\object\type\ObjectType
+ */
+ public function getObjectType() {
+ return ObjectTypeCache::getInstance()->getObjectType($this->objectTypeID);
+ }
+
+ /**
+ * @see \wcf\data\DatabaseObject::handleData()
+ */
+ protected function handleData($data) {
+ parent::handleData($data);
+
+ // handle condition data
+ $this->data['conditionData'] = @unserialize($data['conditionData']);
+ if (!is_array($this->data['conditionData'])) {
+ $this->data['conditionData'] = array();
+ }
+ }
+
+ /**
+ * @see \wcf\data\IStorableObject::getDatabaseTableAlias()
+ */
+ public static function getDatabaseTableAlias() {
+ return 'condition_table';
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\condition;
+use wcf\data\AbstractDatabaseObjectAction;
+
+/**
+ * Executes condition-related actions.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.condition
+ * @category Community Framework
+ */
+class ConditionAction extends AbstractDatabaseObjectAction { }
--- /dev/null
+<?php
+namespace wcf\data\condition;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\IEditableCachedObject;
+use wcf\system\cache\builder\ConditionCacheBuilder;
+
+/**
+ * Executes condition-related actions.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.condition
+ * @category Community Framework
+ */
+class ConditionEditor extends DatabaseObjectEditor implements IEditableCachedObject {
+ /**
+ * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ */
+ protected static $baseClass = 'wcf\data\condition\Condition';
+
+ /**
+ * @see \wcf\data\IEditableCachedObject::resetCache()
+ */
+ public static function resetCache() {
+ ConditionCacheBuilder::getInstance()->reset();
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\condition;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of conditions.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.condition
+ * @category Community Framework
+ */
+class ConditionList extends DatabaseObjectList { }
if ($birthdayYear) {
return $year - $birthdayYear;
}
-
}
return 0;
$this->__age = 0;
}
}
-
+
return $this->__age;
}
}
/**
* Returns the formatted birthday of this user.
- *
+ *
* @param integer $year
* @return string
*/
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\option\user\UserOptionHandler;
+use wcf\system\user\group\assignment\UserGroupAssignmentHandler;
use wcf\system\user\storage\UserStorageHandler;
use wcf\system\WCF;
use wcf\util\StringUtil;
$userAction = new UserAction(array($this->userProfile->userID), 'update', $data);
$userAction->executeAction();
+ // check if the user will be automatically added to new
+ // user groups because of the changed user options
+ UserGroupAssignmentHandler::getInstance()->checkUsers(array($this->userProfile->userID));
+
// return parsed template
$user = new User($this->userProfile->userID);
--- /dev/null
+<?php
+namespace wcf\data\user\group\assignment;
+use wcf\data\user\group\UserGroup;
+use wcf\data\DatabaseObject;
+use wcf\system\condition\ConditionHandler;
+use wcf\system\request\IRouteController;
+
+/**
+ * Represents an automatic assignement to a user group.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.user.group.assignment
+ * @category Community Framework
+ */
+class UserGroupAssignment extends DatabaseObject implements IRouteController {
+ /**
+ * @see \wcf\data\DatabaseObject::$databaseTableIndexName
+ */
+ protected static $databaseTableIndexName = 'assignmentID';
+
+ /**
+ * @see \wcf\data\DatabaseObject::$databaseTableName
+ */
+ protected static $databaseTableName = 'user_group_assignment';
+
+ /**
+ * Returns the conditions of the automatic assignement to a user group.
+ *
+ * @return array<\wcf\data\condition\Condition>
+ */
+ public function getConditions() {
+ return ConditionHandler::getInstance()->getConditions('com.woltlab.wcf.condition.userGroupAssignment', $this->assignmentID);
+ }
+
+ /**
+ * @see \wcf\data\ITitledObject::getTitle()
+ */
+ public function getTitle() {
+ return $this->title;
+ }
+
+ /**
+ * Returns the user group the automatic assignement belongs to.
+ *
+ * @return \wcf\data\user\group\UserGroup
+ */
+ public function getUserGroup() {
+ return UserGroup::getGroupByID($this->groupID);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\user\group\assignment;
+use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\IToggleAction;
+
+/**
+ * Executes user group assignment-related actions.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.user.group.assignment
+ * @category Community Framework
+ */
+class UserGroupAssignmentAction extends AbstractDatabaseObjectAction implements IToggleAction {
+ /**
+ * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsDelete
+ */
+ protected $permissionsDelete = array('admin.user.canManageGroupAssignment');
+
+ /**
+ * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsUpdate
+ */
+ protected $permissionsUpdate = array('admin.user.canManageGroupAssignment');
+
+ /**
+ * @see \wcf\data\AbstractDatabaseObjectAction::$requireACP
+ */
+ protected $requireACP = array('create', 'delete', 'toggle', 'update');
+
+ /**
+ * @see \wcf\data\IToggleAction::toggle()
+ */
+ public function toggle() {
+ foreach ($this->objects as $assignment) {
+ $assignment->update(array(
+ 'isDisabled' => $assignment->isDisabled ? 0 : 1
+ ));
+ }
+ }
+
+ /**
+ * @see \wcf\data\IToggleAction::validateToggle()
+ */
+ public function validateToggle() {
+ parent::validateUpdate();
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\user\group\assignment;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\data\DatabaseObjectEditor;
+use wcf\data\IEditableCachedObject;
+use wcf\system\cache\builder\UserGroupAssignmentCacheBuilder;
+use wcf\system\cache\builder\ConditionCacheBuilder;
+
+/**
+ * Executes user group assignment-related actions.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.user.group.assignment
+ * @category Community Framework
+ */
+class UserGroupAssignmentEditor extends DatabaseObjectEditor implements IEditableCachedObject {
+ /**
+ * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ */
+ protected static $baseClass = 'wcf\data\user\group\assignment\UserGroupAssignment';
+
+ /**
+ * @see \wcf\data\IEditableCachedObject::resetCache()
+ */
+ public static function resetCache() {
+ UserGroupAssignmentCacheBuilder::getInstance()->reset();
+ ConditionCacheBuilder::getInstance()->reset(array(
+ 'definitionID' => ObjectTypeCache::getInstance()->getDefinitionByName('com.woltlab.wcf.condition.userGroupAssignment')->definitionID
+ ));
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\user\group\assignment;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of user group assignments.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage data.user.group.assignment
+ * @category Community Framework
+ */
+class UserGroupAssignmentList extends DatabaseObjectList { }
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\menu\user\UserMenu;
+use wcf\system\user\group\assignment\UserGroupAssignmentHandler;
use wcf\system\WCF;
/**
));
$this->objectAction->executeAction();
+ // check if the user will be automatically added to new user groups
+ // because of the changed avatar
+ UserGroupAssignmentHandler::getInstance()->checkUsers(array(WCF::getUser()->userID));
+
// reset gravatar cache
if ($this->avatarType == 'gravatar') {
$pattern = WCF_DIR . sprintf(Gravatar::GRAVATAR_CACHE_LOCATION, md5(mb_strtolower(WCF::getUser()->email)), '*');
--- /dev/null
+<?php
+namespace wcf\system\cache\builder;
+use wcf\data\condition\ConditionList;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\exception\SystemException;
+
+/**
+ * Caches the conditions for a certain condition object type definition.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.cache.builder
+ * @category Community Framework
+ */
+class ConditionCacheBuilder extends AbstractCacheBuilder {
+ /**
+ * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
+ */
+ public function rebuild(array $parameters) {
+ if (!isset($parameters['definitionID'])) {
+ throw new SystemException("Missing 'definitionID' parameter");
+ }
+
+ $definition = ObjectTypeCache::getInstance()->getDefinition($parameters['definitionID']);
+ if ($definition === null) {
+ throw new SystemException("Unknown object type definition with id '".$parameters['definitionID']."'");
+ }
+
+ $objectTypes = ObjectTypeCache::getInstance()->getObjectTypes($definition->definitionName);
+ if (empty($objectTypes)) {
+ return array();
+ }
+
+ $objectTypeIDs = array();
+ foreach ($objectTypes as $objectType) {
+ $objectTypeIDs[] = $objectType->objectTypeID;
+ }
+
+ $conditionList = new ConditionList();
+ $conditionList->getConditionBuilder()->add('condition_table.objectTypeID IN (?)', array($objectTypeIDs));
+ $conditionList->readObjects();
+
+ $groupedConditions = array();
+ foreach ($conditionList as $condition) {
+ if (!isset($groupedConditions[$condition->objectID])) {
+ $groupedConditions[$condition->objectID] = array();
+ }
+
+ $groupedConditions[$condition->objectID][$condition->conditionID] = $condition;
+ }
+
+ return $groupedConditions;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\cache\builder;
+use wcf\data\user\group\assignment\UserGroupAssignmentList;
+
+/**
+ * Caches the enabled automatic user group assignments.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.cache.builder
+ * @category Community Framework
+ */
+class UserGroupAssignmentCacheBuilder extends AbstractCacheBuilder {
+ /**
+ * @see \wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
+ */
+ protected function rebuild(array $parameters) {
+ $assignmentList = new UserGroupAssignmentList();
+ $assignmentList->getConditionBuilder()->add('isDisabled = ?', array(0));
+ $assignmentList->readObjects();
+
+ return $assignmentList->getObjects();
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\object\type\AbstractObjectTypeProcessor;
+
+/**
+ * Abstract implementation of a condition.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 AbstractCondition extends AbstractObjectTypeProcessor implements ICondition {
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ // does nothing
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ // does nothing
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a condition for an integer value.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 AbstractIntegerCondition extends AbstractMultipleFieldsCondition {
+ /**
+ * property value has to be greater than the given value
+ * @var integer
+ */
+ protected $greaterThan = null;
+
+ /**
+ * identifier used for the input fields
+ * @var string
+ */
+ protected $identifier = '';
+
+ /**
+ * prefix used for error message language items
+ * @var string
+ */
+ protected $languageItemPrefix = '';
+
+ /**
+ * property value has to be less than the given value
+ * @var integer
+ */
+ protected $lessThan = null;
+
+ /**
+ * maximum value the property can have
+ * @var integer
+ */
+ protected $maxValue = null;
+
+ /**
+ * language item with the global maximum value error message
+ * @var string
+ */
+ protected $maxValueErrorMessage = null;
+
+ /**
+ * minimum value the property can have
+ * @var integer
+ */
+ protected $minValue = null;
+
+ /**
+ * language item with the global minimum value error message
+ * @var string
+ */
+ protected $minValueErrorMessage = null;
+
+ /**
+ * name of the integer user property
+ * @var string
+ */
+ protected $propertyName = '';
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ $data = array();
+
+ if ($this->lessThan !== null) {
+ $data['lessThan'] = $this->lessThan;
+ }
+ if ($this->greaterThan !== null) {
+ $data['greaterThan'] = $this->greaterThan;
+ }
+
+ if (!empty($data)) {
+ return $data;
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractMultipleFieldsCondition::getData()
+ */
+ protected function getErrorMessageElement($identifier) {
+ if (isset($this->errorMessages[$identifier])) {
+ $errorMessage = '';
+ switch ($this->errorMessages[$identifier]) {
+ case $this->languageItemPrefix.'.greaterThan.error.maxValue':
+ case $this->languageItemPrefix.'.lessThan.error.maxValue':
+ $errorMessage = WCF::getLanguage()->getDynamicVariable($this->maxValueErrorMessage ? $this->maxValueErrorMessage : $this->errorMessages[$identifier], array(
+ 'maxValue' => $this->maxValue
+ ));
+ break;
+
+ case $this->languageItemPrefix.'.greaterThan.error.minValue':
+ case $this->languageItemPrefix.'.lessThan.error.minValue':
+ $errorMessage = WCF::getLanguage()->getDynamicVariable($this->minValueErrorMessage ? $this->minValueErrorMessage : $this->errorMessages[$identifier], array(
+ 'minValue' => $this->minValue
+ ));
+ break;
+
+ default:
+ $errorMessage = WCF::getLanguage()->get($this->errorMessages[$identifier]);
+ break;
+ }
+ return '<small class="innerError">'.$errorMessage.'</small>';
+ }
+
+ return '';
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getHTML()
+ */
+ public function getHTML() {
+ return <<<HTML
+<dl>
+ <dt>{$this->getLabel('lessThan')}</dt>
+ <dd>
+ <input type="number" name="lessThan_{$this->getIdentifier()}" value="{$this->lessThan}"{$this->getMinMaxAttributes('lessThan')} />
+ {$this->getDescriptionElement('lessThan')}
+ {$this->getErrorMessageElement('lessThan')}
+ </dd>
+</dl>
+
+<dl>
+ <dt>{$this->getLabel('greaterThan')}</dt>
+ <dd>
+ <input type="number" name="greaterThan_{$this->getIdentifier()}" value="{$this->greaterThan}"{$this->getMinMaxAttributes('greaterThan')} />
+ {$this->getDescriptionElement('greaterThan')}
+ {$this->getErrorMessageElement('greaterThan')}
+ </dd>
+</dl>
+HTML;
+ }
+
+ /**
+ * Returns the identifier used for the input fields.
+ *
+ * @return string
+ */
+ protected function getIdentifier() {
+ return $this->identifier;
+ }
+
+ /**
+ * Returns the maximum value the property can have or null if there is no
+ * such maximum.
+ *
+ * @return integer
+ */
+ protected function getMaxValue() {
+ if ($this->getDecoratedObject()->maxvalue !== null) {
+ return $this->getDecoratedObject()->maxvalue;
+ }
+
+ if ($this->maxValue !== null) {
+ return $this->maxValue;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the min and max attributes for the input elements.
+ *
+ * @param string $type
+ * @return string
+ */
+ protected function getMinMaxAttributes($type) {
+ $attributes = '';
+ if ($this->getMinValue() !== null) {
+ $attributes .= ' min="'.($this->getMinValue() + ($type == 'lessThan' ? 1 : 0)).'"';
+ }
+ if ($this->getMaxValue() !== null) {
+ $attributes .= ' max="'.($this->getMaxValue() - ($type == 'lessThan' ? 1 : 0)).'"';
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Returns the minimum value the property can have or null if there is no
+ * such minimum.
+ *
+ * @return integer
+ */
+ protected function getMinValue() {
+ if ($this->getDecoratedObject()->minvalue !== null) {
+ return $this->getDecoratedObject()->minvalue;
+ }
+
+ if ($this->minValue !== null) {
+ return $this->minValue;
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST['lessThan_'.$this->getIdentifier()]) && strlen($_POST['lessThan_'.$this->getIdentifier()])) $this->lessThan = intval($_POST['lessThan_'.$this->getIdentifier()]);
+ if (isset($_POST['greaterThan_'.$this->getIdentifier()]) && strlen($_POST['greaterThan_'.$this->getIdentifier()])) $this->greaterThan = intval($_POST['greaterThan_'.$this->getIdentifier()]);
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->lessThan = null;
+ $this->greaterThan = null;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ $this->lessThan = $condition->lessThan;
+ $this->greaterThan = $condition->greaterThan;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ if ($this->lessThan !== null) {
+ if ($this->getMinValue() !== null && $this->lessThan <= $this->getMinValue()) {
+ $this->errorMessages['lessThan'] = $this->languageItemPrefix.'.lessThan.error.minValue';
+
+ throw new UserInputException('lessThan', 'minValue');
+ }
+ else if ($this->getMaxValue() !== null && $this->lessThan > $this->getMaxValue()) {
+ $this->errorMessages['lessThan'] = $this->languageItemPrefix.'.lessThan.error.maxValue';
+
+ throw new UserInputException('lessThan', 'maxValue');
+ }
+ }
+ if ($this->greaterThan !== null) {
+ if ($this->getMinValue() !== null && $this->greaterThan < $this->getMinValue()) {
+ $this->errorMessages['greaterThan'] = $this->languageItemPrefix.'.greaterThan.error.minValue';
+
+ throw new UserInputException('greaterThan', 'minValue');
+ }
+ else if ($this->getMaxValue() !== null && $this->greaterThan >= $this->getMaxValue()) {
+ $this->errorMessages['greaterThan'] = $this->languageItemPrefix.'.greaterThan.error.maxValue';
+
+ throw new UserInputException('greaterThan', 'maxValue');
+ }
+ }
+
+ if ($this->lessThan !== null && $this->greaterThan !== null && $this->greaterThan + 1 >= $this->lessThan) {
+ $this->errorMessages['greaterThan'] = $this->languageItemPrefix.'.greaterThan.error.lessThan';
+
+ throw new UserInputException('greaterThan', 'lessThan');
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\object\type\AbstractObjectTypeProcessor;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a condition for multiple fields.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 AbstractMultipleFieldsCondition extends AbstractCondition {
+ /**
+ * language items of the input element descriptions
+ * @var string
+ */
+ protected $descriptions = array();
+
+ /**
+ * error messages if the validation failed
+ * @var string
+ */
+ protected $errorMessages = array();
+
+ /**
+ * language items of the input element labels
+ * @var string
+ */
+ protected $labels = array();
+
+ /**
+ * Returns the description element for the HTML output.
+ *
+ * @param string $identifier
+ * @return string
+ */
+ protected function getDescriptionElement($identifier) {
+ if (isset($this->descriptions[$identifier])) {
+ return '<small>'.WCF::getLanguage()->get($this->descriptions[$identifier]).'</small>';
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns the error class for the definition list element.
+ *
+ * @param string $identifier
+ * @return string
+ */
+ public function getErrorClass($identifier) {
+ if (isset($this->errorMessages[$identifier])) {
+ return ' class="formError"';
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns the error message element for the HTML output.
+ *
+ * @param string $identifier
+ * @return string
+ */
+ protected function getErrorMessageElement($identifier) {
+ if (isset($this->errorMessages[$identifier])) {
+ return '<small class="innerError">'.WCF::getLanguage()->get($this->errorMessages[$identifier]).'</small>';
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns the label of the input element.
+ *
+ * @param string $identifier
+ * @return string
+ */
+ protected function getLabel($identifier) {
+ if (isset($this->labels[$identifier])) {
+ return '<label for="'.$identifier.'">'.WCF::getLanguage()->get($this->labels[$identifier]).'</label>';
+ }
+
+ return '';
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a condition with select options.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 AbstractSelectCondition extends AbstractSingleFieldCondition {
+ /**
+ * name of the field
+ * @var string
+ */
+ protected $fieldName = '';
+
+ /**
+ * value of the selected option
+ * @var string
+ */
+ protected $fieldValue = self::NO_SELECTION_VALUE;
+
+ /**
+ * value of the "no selection" option
+ * @var string
+ */
+ const NO_SELECTION_VALUE = -1;
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ if ($this->fieldValue != self::NO_SELECTION_VALUE) {
+ return array(
+ $this->fieldName => $this->fieldValue
+ );
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::getFieldElement()
+ */
+ protected function getFieldElement() {
+ $options = $this->getOptions();
+
+ $fieldElement = '<select name="'.$this->fieldName.'">';
+ foreach ($options as $value => $label) {
+ $fieldElement .= '<option value="'.$value.'"'.($this->fieldValue == $value ? ' selected="selected"' : '').'>'.WCF::getLanguage()->get($label).'</option>';
+ }
+ $fieldElement .= "</select>";
+
+ return $fieldElement;
+ }
+
+ /**
+ * Returns the selectable options.
+ */
+ abstract protected function getOptions();
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST[$this->fieldName])) $this->fieldValue = intval($_POST[$this->fieldName]);
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->fieldValue = self::NO_SELECTION_VALUE;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ $this->fieldValue = $condition->conditionData[$this->fieldName];
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ if ($this->fieldValue != self::NO_SELECTION_VALUE) {
+ $options = $this->getOptions();
+
+ if (!isset($options[$this->fieldValue])) {
+ $this->errorMessage = 'wcf.global.form.error.noValidSelection';
+
+ throw new UserInputException($this->fieldName, 'noValidSelection');
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of a condition for a single field.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 AbstractSingleFieldCondition extends AbstractCondition implements ICondition {
+ /**
+ * language item of the input element description
+ * @var string
+ */
+ protected $description = '';
+
+ /**
+ * error message if the validation failed
+ * @var string
+ */
+ protected $errorMessage = '';
+
+ /**
+ * language item of the input element label
+ * @var string
+ */
+ protected $label = '';
+
+ /**
+ * Returns the description element for the HTML output.
+ *
+ * @return string
+ */
+ protected function getDescriptionElement() {
+ if ($this->description) {
+ return '<small>'.WCF::getLanguage()->get($this->description).'</small>';
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns the error class for the definition list element.
+ *
+ * @return string
+ */
+ public function getErrorClass() {
+ if ($this->errorMessage) {
+ return ' class="formError"';
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns the error message element for the HTML output.
+ *
+ * @return string
+ */
+ protected function getErrorMessageElement() {
+ if ($this->errorMessage) {
+ return '<small class="innerError">'.WCF::getLanguage()->get($this->errorMessage).'</small>';
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns the output of the field element.
+ *
+ * @return string
+ */
+ abstract protected function getFieldElement();
+
+ /**
+ * @see \wcf\system\condition\ICondition::getHTML()
+ */
+ public function getHTML() {
+ return <<<HTML
+<dl>
+ <dt>{$this->getLabel()}</dt>
+ <dd>
+ {$this->getFieldElement()}
+ {$this->getDescriptionElement()}
+ {$this->getErrorMessageElement()}
+ </dd>
+</dl>
+HTML;
+ }
+
+ /**
+ * Returns the label of the input element.
+ *
+ * @return string
+ */
+ protected function getLabel() {
+ return WCF::getLanguage()->get($this->label);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\util\StringUtil;
+
+/**
+ * Abstract implementation of a text condition.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 AbstractTextCondition extends AbstractSingleFieldCondition {
+ /**
+ * name of the field
+ * @var string
+ */
+ protected $fieldName = '';
+
+ /**
+ * entered condition field value
+ * @var string
+ */
+ protected $fieldValue = '';
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ if (mb_strlen($this->fieldValue)) {
+ return array(
+ $this->fieldName => $this->fieldValue
+ );
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::getFieldElement()
+ */
+ protected function getFieldElement() {
+ return '<input type="text" name="'.$this->fieldName.'" value="'.StringUtil::encodeHTML($this->fieldValue).'" class="long" />';
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST[$this->fieldName])) $this->fieldValue = StringUtil::trim($_POST[$this->fieldName]);
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->fieldValue = '';
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ $this->fieldValue = $condition->conditionData[$this->fieldName];
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\ConditionAction;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\cache\builder\ConditionCacheBuilder;
+use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
+
+/**
+ * Handles general condition-related matters.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 ConditionHandler extends SingletonFactory {
+ /**
+ * list of available conditions grouped by the id of the related condition
+ * object type definition
+ * @var array
+ */
+ protected $conditions = array();
+
+ /**
+ * Creates condition objects for the object with the given id and based
+ * on the given condition object types.
+ *
+ * @param integer $objectID
+ * @param array $conditionObjectTypes
+ */
+ public function createConditions($objectID, array $conditionObjectTypes) {
+ foreach ($conditionObjectTypes as $objectTypes) {
+ foreach ($objectTypes as $objectType) {
+ $conditionData = $objectType->getProcessor()->getData();
+ if ($conditionData !== null) {
+ $conditionAction = new ConditionAction(array(), 'create', array(
+ 'data' => array(
+ 'conditionData' => serialize($conditionData),
+ 'objectID' => $objectID,
+ 'objectTypeID' => $objectType->objectTypeID
+ )
+ ));
+ $conditionAction->executeAction();
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the conditions for the conditioned object with the given condition
+ * object type definition and object id.
+ *
+ * @param string $definitionName
+ * @param integer $objectID
+ * @return array<\wcf\data\condition\Condition>
+ */
+ public function getConditions($definitionName, $objectID) {
+ // validate definition
+ $definition = ObjectTypeCache::getInstance()->getDefinitionByName($definitionName);
+ if ($definition === null) {
+ throw new SystemException("Unknown object type definition with name '".$definitionName."'");
+ }
+
+ if (!isset($this->conditions[$definition->definitionID])) {
+ $this->conditions[$definition->definitionID] = ConditionCacheBuilder::getInstance()->getData(array(
+ 'definitionID' => $definition->definitionID
+ ));
+ }
+
+ if (isset($this->conditions[$definition->definitionID][$objectID])) {
+ return $this->conditions[$definition->definitionID][$objectID];
+ }
+
+ return null;
+ }
+
+ /**
+ * Updates the conditions for the object with the given object id.
+ *
+ * @param integer $objectID
+ * @param array<\wcf\data\condition\Condition> $oldConditions
+ * @param array $conditionObjectTypes
+ */
+ public function updateConditions($objectID, array $oldConditions, array $conditionObjectTypes) {
+ // delete old conditions first
+ $conditionAction = new ConditionAction($oldConditions, 'delete');
+ $conditionAction->executeAction();
+
+ // create new conditions
+ $this->createConditions($objectID, $conditionObjectTypes);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\IDatabaseObjectProcessor;
+
+/**
+ * Every concrete condition implementation needs to implement this interface.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 ICondition extends IDatabaseObjectProcessor {
+ /**
+ * Returns the data saved with the condition used to check if the condition
+ * is fulfilled. If null is returned, there is no condition to be created.
+ *
+ * @return mixed
+ */
+ public function getData();
+
+ /**
+ * Returns the output for setting up the condition.
+ *
+ * @return string
+ */
+ public function getHTML();
+
+ /**
+ * Reads the form parameters of the condition.
+ */
+ public function readFormParameters();
+
+ /**
+ * Resets the internally stored condition data.
+ */
+ public function reset();
+
+ /**
+ * Extracts all needed data from the given condition to pre-fill the output
+ * for editing the given condition.
+ *
+ * @param \wcf\data\condition\Condition $condition
+ */
+ public function setData(Condition $condition);
+
+ /**
+ * Validates the given data.
+ *
+ * @param string $value
+ */
+ public function validate();
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+
+/**
+ * Every implementation for user conditions needs to implements this interface.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 IUserCondition extends ICondition {
+ /**
+ * Adds the condition to the given user list to fetch the users which fulfill
+ * the given condition.
+ *
+ * @param \wcf\data\condition\Condition $condition
+ * @param \wcf\data\user\UserList $userList
+ */
+ public function addUserCondition(Condition $condition, UserList $userList);
+
+ /**
+ * Returns true if the given user fulfills the given condition.
+ *
+ * @param \wcf\data\condition\Condition $condition
+ * @param \wcf\data\user\User $user
+ * @return boolean
+ */
+ public function checkUser(Condition $condition, User $user);
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Condition implementation for the avatar of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserAvatarCondition extends AbstractSelectCondition implements IUserCondition {
+ /**
+ * @see wcf\system\condition\AbstractSelectCondition::$fieldName
+ */
+ protected $fieldName = 'userAvatar';
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::$label
+ */
+ protected $label = 'wcf.user.condition.avatar';
+
+ /**
+ * value of the "user has no avatar" option
+ * @var integer
+ */
+ const NO_AVATAR = 0;
+
+ /**
+ * value of the "user has a custom avatar" option
+ * @var integer
+ */
+ const AVATAR = 1;
+
+ /**
+ * value of the "user has a gravatar" option
+ * @var integer
+ */
+ const GRAVATAR = 2;
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ switch ($condition->userAvatar) {
+ case self::NO_AVATAR:
+ $userList->getConditionBuilder()->add('user_table.avatarID IS NULL');
+ break;
+
+ case self::AVATAR:
+ $userList->getConditionBuilder()->add('user_table.avatarID IS NOT NULL');
+ break;
+
+ case self::GRAVATAR:
+ $userList->getConditionBuilder()->add('user_table.enableGravatar = ?', array(1));
+ break;
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ switch ($condition->userAvatar) {
+ case self::NO_AVATAR:
+ return !$user->avatar;
+ break;
+
+ case self::AVATAR:
+ return $user->avatar != 0;
+ break;
+
+ case self::GRAVATAR:
+ return $user->enableGravatar;
+ break;
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractSelectCondition::getOptions()
+ */
+ protected function getOptions() {
+ return array(
+ self::NO_SELECTION_VALUE => 'wcf.global.noSelection',
+ self::NO_AVATAR => 'wcf.user.condition.avatar.noAvatar',
+ self::AVATAR => 'wcf.user.condition.avatar.avatar',
+ self::GRAVATAR => 'wcf.user.condition.avatar.gravatar'
+ );
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+
+/**
+ * Condition implementation for the email address of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserEmailCondition extends AbstractTextCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractTextCondition::$fieldName
+ */
+ protected $fieldName = 'email';
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::$label
+ */
+ protected $label = 'wcf.user.email';
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ $userList->getConditionBuilder()->add('user_table.email LIKE ?', array('%'.addcslashes($condition->email, '_%').'%'));
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ return mb_strpos($user->email, $condition->email) !== false;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\group\UserGroup;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+use wcf\system\exception\UserInputException;
+use wcf\util\ArrayUtil;
+
+/**
+ * Condition implementation for the user group a user is a member or no member of.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserGroupCondition extends AbstractMultipleFieldsCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractMultipleFieldsCondition::$descriptions
+ */
+ protected $descriptions = array(
+ 'groupIDs' => 'wcf.user.condition.groupIDs.description',
+ 'notGroupIDs' => 'wcf.user.condition.notGroupIDs.description'
+ );
+
+ /**
+ * ids of the selected user groups the user has to be member of
+ * @var array<integer>
+ */
+ protected $groupIDs = array();
+
+ /**
+ * @see \wcf\system\condition\AbstractMultipleFieldsCondition::$labels
+ */
+ protected $labels = array(
+ 'groupIDs' => 'wcf.user.condition.groupIDs',
+ 'notGroupIDs' => 'wcf.user.condition.notGroupIDs'
+ );
+
+ /**
+ * ids of the selected user groups the user may not be member of
+ * @var array<integer>
+ */
+ protected $notGroupIDs = array();
+
+ /**
+ * selectable user groups
+ * @var array<\wcf\data\user\group\UserGroup>
+ */
+ protected $userGroups = null;
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ 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)));
+ }
+ 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));
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ $groupIDs = $user->getGroupIDs();
+ if (!empty($condition->groupIDs) && count(array_diff($condition->groupIDs, $groupIDs))) {
+ return false;
+ }
+
+ if (!empty($condition->notGroupIDs) && count(array_intersect($condition->notGroupIDs, $groupIDs))) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ $data = array();
+
+ if (!empty($this->groupIDs)) {
+ $data['groupIDs'] = $this->groupIDs;
+ }
+ if (!empty($this->notGroupIDs)) {
+ $data['notGroupIDs'] = $this->notGroupIDs;
+ }
+
+ if (!empty($data)) {
+ return $data;
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getHTML()
+ */
+ public function getHTML() {
+ return <<<HTML
+<dl{$this->getErrorClass('groupIDs')}>
+ <dt>{$this->getLabel('groupIDs')}</dt>
+ <dd>
+ {$this->getOptionElements('groupIDs')}
+ {$this->getDescriptionElement('groupIDs')}
+ {$this->getErrorMessageElement('groupIDs')}
+ </dd>
+</dl>
+<dl{$this->getErrorClass('notGroupIDs')}>
+ <dt>{$this->getLabel('notGroupIDs')}</dt>
+ <dd>
+ {$this->getOptionElements('notGroupIDs')}
+ {$this->getDescriptionElement('notGroupIDs')}
+ {$this->getErrorMessageElement('notGroupIDs')}
+ </dd>
+</dl>
+HTML;
+ }
+
+ /**
+ * Returns the option elements for the user group selection.
+ *
+ * @param string $identifier
+ * @return string
+ */
+ protected function getOptionElements($identifier) {
+ $userGroups = $this->getUserGroups();
+
+ $returnValue = "";
+ foreach ($userGroups as $userGroup) {
+ $returnValue .= "<label><input type=\"checkbox\" name=\"".$identifier."[]\" value=\"".$userGroup->groupID."\"".(in_array($userGroup->groupID, $this->$identifier) ? ' checked="checked"' : "")." /> ".$userGroup->getName()."</label>";
+ }
+
+ return $returnValue;
+ }
+
+ /**
+ * Returns the selectable user groups.
+ *
+ * @return array<\wcf\data\user\group\UserGroup>
+ */
+ protected function getUserGroups() {
+ if ($this->userGroups == null) {
+ $this->userGroups = UserGroup::getGroupsByType(array(UserGroup::OTHER));
+ foreach ($this->userGroups as $key => $userGroup) {
+ if (!$userGroup->isAccessible()) {
+ unset($this->userGroups[$key]);
+ }
+ }
+
+ uasort($this->userGroups, function(UserGroup $groupA, UserGroup $groupB) {
+ return strcmp($groupA->getName(), $groupB->getName());
+ });
+ }
+
+ return $this->userGroups;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST['groupIDs'])) $this->groupIDs = ArrayUtil::toIntegerArray($_POST['groupIDs']);
+ if (isset($_POST['notGroupIDs'])) $this->notGroupIDs = ArrayUtil::toIntegerArray($_POST['notGroupIDs']);
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->groupIDs = array();
+ $this->notGroupIDs = array();
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ if ($condition->groupIDs !== null) {
+ $this->groupIDs = $condition->groupIDs;
+ }
+ if ($condition->notGroupIDs !== null) {
+ $this->notGroupIDs = $condition->notGroupIDs;
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ $userGroups = $this->getUserGroups();
+ foreach ($this->groupIDs as $groupID) {
+ if (!isset($userGroups[$groupID])) {
+ $this->errorMessages['groupIDs'] = 'wcf.global.form.error.noValidSelection';
+
+ throw new UserInputException('groupIDs', 'noValidSelection');
+ }
+ }
+ foreach ($this->notGroupIDs as $groupID) {
+ if (!isset($userGroups[$groupID])) {
+ $this->errorMessages['notGroupIDs'] = 'wcf.global.form.error.noValidSelection';
+
+ throw new UserInputException('notGroupIDs', 'noValidSelection');
+ }
+ }
+
+ if (count(array_intersect($this->notGroupIDs, $this->groupIDs))) {
+ $this->errorMessages['notGroupIDs'] = 'wcf.user.condition.notGroupIDs.error.groupIDsIntersection';
+
+ throw new UserInputException('notGroupIDs', 'groupIDsIntersection');
+ }
+ }
+}
--- /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\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Condition implementation for an integer property of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserIntegerPropertyCondition extends AbstractIntegerCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::$maxValueErrorMessage
+ */
+ protected $maxValueErrorMessage = 'wcf.user.condition.integerProperty.error.maxValue';
+
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::$minValueErrorMessage
+ */
+ protected $minValueErrorMessage = 'wcf.user.condition.integerProperty.error.minValue';
+
+ /**
+ * @see \wcf\data\DatabaseObjectDecorator::__construct()
+ */
+ public function __construct(DatabaseObject $object) {
+ parent::__construct($object);
+
+ $this->languageItemPrefix = 'wcf.user.condition.'.$this->getDecoratedObject()->propertyname;
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ if ($condition->greaterThan !== null) {
+ $userList->getConditionBuilder()->add('user_table.'.$this->getDecoratedObject()->propertyname.' > ?', array($condition->greaterThan));
+ }
+ if ($condition->lessThan !== null) {
+ $userList->getConditionBuilder()->add('user_table.'.$this->getDecoratedObject()->propertyname.' < ?', array($condition->lessThan));
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ if ($condition->greaterThan !== null && $user->{$this->getDecoratedObject()->propertyname} <= $condition->greaterThan) {
+ return false;
+ }
+ if ($condition->lessThan !== null && $user->{$this->getDecoratedObject()->propertyname} >= $condition->lessThan) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::getIdentifier()
+ */
+ protected function getIdentifier() {
+ return 'user_'.$this->getDecoratedObject()->propertyname;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractMultipleFieldsCondition::getLabel()
+ */
+ protected function getLabel($identifier) {
+ return WCF::getLanguage()->get('wcf.user.condition.'.$this->getDecoratedObject()->propertyname.'.'.$identifier);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+use wcf\system\exception\UserInputException;
+use wcf\system\language\LanguageFactory;
+use wcf\system\WCF;
+use wcf\util\ArrayUtil;
+
+/**
+ * Condition implementation for the languages of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserLanguageCondition extends AbstractSingleFieldCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::$label
+ */
+ protected $label = 'wcf.user.condition.languages';
+
+ /**
+ * ids of the selected languages
+ * @var array<integer>
+ */
+ protected $languageIDs = array();
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ $userList->getConditionBuilder()->add('user_table.languageID IN (?)', array($condition->conditionData['languageIDs']));
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ if (!empty($condition->languageIDs) && !in_array($user->languageID, $condition->languageIDs)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ if (!empty($this->languageIDs)) {
+ return array(
+ 'languageIDs' => $this->languageIDs
+ );
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::getFieldElement()
+ */
+ protected function getFieldElement() {
+ $returnValue = "";
+ foreach (LanguageFactory::getInstance()->getLanguages() as $language) {
+ $returnValue .= "<label><input type=\"checkbox\" name=\"languageIDs[]\" value=\"".$language->languageID."\"".(in_array($language->languageID, $this->languageIDs) ? ' checked="checked"' : "")." /> ".$language->languageName."</label>";
+ }
+
+ return $returnValue;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST['languageIDs']) && is_array($_POST['languageIDs'])) $this->languageIDs = ArrayUtil::toIntegerArray($_POST['languageIDs']);
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->languageIDs = array();
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ if (!empty($condition->conditionData['languageIDs'])) {
+ $this->languageIDs = $condition->conditionData['languageIDs'];
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ foreach ($this->languageIDs as $languageID) {
+ if (LanguageFactory::getInstance()->getLanguage($languageID) === null) {
+ $this->errorMessage = 'wcf.global.form.error.noValidSelection';
+
+ throw new UserInputException('languageIDs', 'noValidSelection');
+ }
+ }
+ }
+}
--- /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\system\option\user\UserOptionHandler;
+use wcf\system\WCF;
+
+/**
+ * Condition implementation for the options of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserOptionsCondition extends AbstractMultipleFieldsCondition implements IUserCondition {
+ /**
+ * user option handler object
+ * @var \wcf\system\option\user\UserOptionHandler
+ */
+ protected $optionHandler = null;
+
+ /**
+ * @see \wcf\data\DatabaseObjectDecorator::__construct()
+ */
+ public function __construct(DatabaseObject $object) {
+ parent::__construct($object);
+
+ $this->optionHandler = new UserOptionHandler(false);
+ $this->optionHandler->enableConditionMode();
+ $this->optionHandler->init();
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ $optionValues = $condition->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]);
+ }
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ $optionValues = $condition->optionValues;
+
+ $checkSuccess = true;
+ foreach ($this->optionHandler->getCategoryOptions('profile') as $option) {
+ $option = $option['object'];
+
+ if (isset($optionValues[$option->optionName])) {
+ if (!$this->optionHandler->getTypeObject($option->optionType)->checkUser($user, $option, $optionValues[$option->optionName])) {
+ $checkSuccess = false;
+ break;
+ }
+ }
+ }
+
+ return $checkSuccess;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ $optionValues = $this->optionHandler->getOptionValues();
+
+ $data = array();
+ foreach ($this->optionHandler->getCategoryOptions('profile') as $option) {
+ $option = $option['object'];
+
+ if (isset($optionValues[$option->optionName])) {
+ $conditionData = $this->optionHandler->getTypeObject($option->optionType)->getConditionData($option, $optionValues[$option->optionName]);
+ if ($conditionData !== null) {
+ $data[$option->optionName] = $conditionData;
+ }
+ }
+ }
+
+ if (!empty($data)) {
+ return array(
+ 'optionValues' => $data
+ );
+ }
+
+ return null;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getHTML()
+ */
+ public function getHTML() {
+ return WCF::getTPL()->fetch('userOptionsCondition', 'wcf', array(
+ 'optionTree' => $this->optionHandler->getOptionTree('profile')
+ ));
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ $this->optionHandler->readUserInput($_POST);
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->optionHandler->setOptionValues(array());
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ $this->optionHandler->setOptionValues($condition->conditionData['optionValues']);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Condition implementation for the registration date of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserRegistrationDateCondition extends AbstractSingleFieldCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::$label
+ */
+ protected $label = 'wcf.user.condition.registrationDate';
+
+ /**
+ * registration start date
+ * @var string
+ */
+ protected $registrationDateEnd = '';
+
+ /**
+ * registration start date
+ * @var string
+ */
+ protected $registrationDateStart = '';
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ if ($condition->registrationDateEnd !== null) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate <= ?', array(strtotime($condition->registrationDateEnd) + 24 * 3600 - 1));
+ }
+ if ($condition->registrationDateStart !== null) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate >= ?', array(strtotime($condition->registrationDateStart)));
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ if ($condition->registrationDateStart !== null && $user->registrationDate < $condition->registrationDateStart) {
+ return false;
+ }
+ if ($condition->registrationDateEnd !== null && $user->registrationDate > $condition->registrationDateEnd) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ $data = array();
+
+ if (strlen($this->registrationDateStart)) {
+ $data['registrationDateStart'] = $this->registrationDateStart;
+ }
+ if (strlen($this->registrationDateEnd)) {
+ $data['registrationDateEnd'] = $this->registrationDateEnd;
+ }
+
+ 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="registrationDateStart" name="registrationDateStart" value="{$this->registrationDateStart}" placeholder="{$start}" />
+<input type="date" id="registrationDateEnd" name="registrationDateEnd" value="{$this->registrationDateEnd}" placeholder="{$end}" />
+HTML;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST['registrationDateEnd'])) $this->registrationDateEnd = $_POST['registrationDateEnd'];
+ if (isset($_POST['registrationDateStart'])) $this->registrationDateStart = $_POST['registrationDateStart'];
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->registrationDateEnd = '';
+ $this->registrationDateStart = '';
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ if ($condition->registrationDateEnd) {
+ $this->registrationDateEnd = $condition->registrationDateEnd;
+ }
+ if ($condition->registrationDateStart) {
+ $this->registrationDateStart = $condition->registrationDateStart;
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ $registrationDateEnd = $registrationDateStart = null;
+ if (strlen($this->registrationDateStart)) {
+ $registrationDateStart = @strtotime($this->registrationDateStart);
+ if ($registrationDateStart === false) {
+ $this->errorMessage = 'wcf.user.condition.registrationDate.error.startNotValid';
+
+ throw new UserInputException($this->fieldName, 'startNotValid');
+ }
+ }
+ if (strlen($this->registrationDateEnd)) {
+ $registrationDateEnd = @strtotime($this->registrationDateEnd);
+ if ($registrationDateEnd === false) {
+ $this->errorMessage = 'wcf.user.condition.registrationDate.error.endNotValid';
+
+ throw new UserInputException($this->fieldName, 'endNotValid');
+ }
+ }
+
+ if ($registrationDateEnd !== null && $registrationDateStart !== null && $registrationDateEnd < $registrationDateStart) {
+ $this->errorMessage = 'wcf.user.condition.registrationDate.error.endBeforeStart';
+
+ throw new UserInputException($this->fieldName, 'endBeforeStart');
+ }
+ }
+}
--- /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\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Condition implementation for a relative interval for the registration date of
+ * a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserRegistrationDateIntervalCondition extends AbstractIntegerCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractMultipleFieldsCondition::$languageItemPrefix
+ */
+ protected $labels = array(
+ 'greaterThan' => 'wcf.user.condition.registrationDateInterval.greaterThan',
+ 'lessThan' => 'wcf.user.condition.registrationDateInterval.lessThan'
+ );
+
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::$languageItemPrefix
+ */
+ protected $languageItemPrefix = 'wcf.user.condition.registrationDateInterval';
+
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::$maxValueErrorMessage
+ */
+ protected $maxValueErrorMessage = 'wcf.user.condition.integerProperty.error.maxValue';
+
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::$minValue
+ */
+ protected $minValue = 0;
+
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::$minValueErrorMessage
+ */
+ protected $minValueErrorMessage = 'wcf.user.condition.integerProperty.error.minValue';
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ if ($condition->greaterThan !== null) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate < ?', array(TIME_NOW - $condition->greaterThan * 86400));
+ }
+ if ($condition->lessThan !== null) {
+ $userList->getConditionBuilder()->add('user_table.registrationDate > ?', array(TIME_NOW - $condition->lessThan * 86400));
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ if ($condition->greaterThan !== null && $user->registrationDate >= TIME_NOW - $condition->greaterThan * 86400) {
+ return false;
+ }
+ if ($condition->lessThan !== null && $user->registrationDate <= TIME_NOW - $condition->lessThan * 86400) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractIntegerCondition::getIdentifier()
+ */
+ protected function getIdentifier() {
+ return 'user_registrationDateInterval';
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractMultipleFieldsCondition::getLabel()
+ */
+ protected function getLabel($identifier) {
+ return WCF::getLanguage()->get('wcf.user.condition.registrationDateInterval.'.$identifier);
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+use wcf\system\exception\UserInputException;
+use wcf\system\WCF;
+
+/**
+ * Condition implementation for the state (banned, enabled) of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserStateCondition extends AbstractSingleFieldCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::$label
+ */
+ protected $label = 'wcf.user.condition.state';
+
+ /**
+ * true if the the user has to be banned
+ * @var integer
+ */
+ protected $userIsBanned = 0;
+
+ /**
+ * true if the user has to be disabled
+ * @var integer
+ */
+ protected $userIsDisabled = 0;
+
+ /**
+ * true if the user has to be enabled
+ * @var integer
+ */
+ protected $userIsEnabled = 0;
+
+ /**
+ * true if the the user may not be banned
+ * @var integer
+ */
+ protected $userIsNotBanned = 0;
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ if ($condition->userIsBanned !== null) {
+ $userList->getConditionBuilder()->add('user_table.banned = ?', array($condition->userIsBanned));
+ }
+
+ if ($condition->userIsEnabled !== null) {
+ if ($condition->userIsEnabled) {
+ $userList->getConditionBuilder()->add('user_table.activationCode = ?', array(0));
+ }
+ else {
+ $userList->getConditionBuilder()->add('user_table.activationCode <> ?', array(0));
+ }
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ if ($condition->userIsBanned !== null && $user->banned != $condition->userIsBanned) {
+ return false;
+ }
+
+ if ($condition->userIsEnabled !== null) {
+ if ($condition->userIsEnabled && $user->activationCode) {
+ return false;
+ }
+ else if (!$condition->userIsEnabled && !$user->activationCode) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::getData()
+ */
+ public function getData() {
+ $data = array();
+
+ if ($this->userIsBanned) {
+ $data['userIsBanned'] = 1;
+ }
+ else if ($this->userIsNotBanned) {
+ $data['userIsBanned'] = 0;
+ }
+ if ($this->userIsEnabled) {
+ $data['userIsEnabled'] = 1;
+ }
+ else if ($this->userIsDisabled) {
+ $data['userIsEnabled'] = 0;
+ }
+
+ if (!empty($data)) {
+ return $data;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the "checked" attribute for an input element.
+ *
+ * @param string $propertyName
+ * @return string
+ */
+ protected function getCheckedAttribute($propertyName) {
+ if ($this->$propertyName) {
+ return ' checked="checked"';
+ }
+
+ return '';
+ }
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::getFieldElement()
+ */
+ protected function getFieldElement() {
+ $userIsNotBanned = WCF::getLanguage()->get('wcf.user.condition.state.isNotBanned');
+ $userIsBanned = WCF::getLanguage()->get('wcf.user.condition.state.isBanned');
+ $userIsDisabled = WCF::getLanguage()->get('wcf.user.condition.state.isDisabled');
+ $userIsEnabled = WCF::getLanguage()->get('wcf.user.condition.state.isEnabled');
+
+ return <<<HTML
+<label><input type="checkbox" name="userIsBanned" value="1"{$this->getCheckedAttribute('userIsBanned')} /> {$userIsBanned}</label>
+<label><input type="checkbox" name="userIsNotBanned" value="1"{$this->getCheckedAttribute('userIsNotBanned')} /> {$userIsNotBanned}</label>
+<label><input type="checkbox" name="userIsEnabled" value="1"{$this->getCheckedAttribute('userIsEnabled')} /> {$userIsEnabled}</label>
+<label><input type="checkbox" name="userIsDisabled" value="1"{$this->getCheckedAttribute('userIsDisabled')} /> {$userIsDisabled}</label>
+HTML;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::readFormParameters()
+ */
+ public function readFormParameters() {
+ if (isset($_POST['userIsBanned'])) $this->userIsBanned = 1;
+ if (isset($_POST['userIsDisabled'])) $this->userIsDisabled = 1;
+ if (isset($_POST['userIsEnabled'])) $this->userIsEnabled = 1;
+ if (isset($_POST['userIsNotBanned'])) $this->userIsNotBanned = 1;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::reset()
+ */
+ public function reset() {
+ $this->userIsBanned = 0;
+ $this->userIsDisabled = 0;
+ $this->userIsEnabled = 0;
+ $this->userIsNotBanned = 0;
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::setData()
+ */
+ public function setData(Condition $condition) {
+ if ($condition->userIsBanned !== null) {
+ $this->userIsBanned = $condition->userIsBanned;
+ $this->userIsNotBanned = !$condition->userIsBanned;
+ }
+ if ($condition->userIsEnabled !== null) {
+ $this->userIsEnabled = $condition->userIsEnabled;
+ $this->userIsDisabled = !$condition->userIsEnabled;
+ }
+ }
+
+ /**
+ * @see \wcf\system\condition\ICondition::validate()
+ */
+ public function validate() {
+ if ($this->userIsBanned && $this->userIsNotBanned) {
+ $this->errorMessage = 'wcf.user.condition.state.isBanned.error.conflict';
+
+ throw new UserInputException('userIsBanned', 'conflict');
+ }
+
+ if ($this->userIsDisabled && $this->userIsEnabled) {
+ $this->errorMessage = 'wcf.user.condition.state.isEnabled.error.conflict';
+
+ throw new UserInputException('userisEnabled', 'conflict');
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\condition;
+use wcf\data\condition\Condition;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+use wcf\system\WCF;
+use wcf\util\StringUtil;
+
+/**
+ * Condition implementation for the username of a user.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 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 UserUsernameCondition extends AbstractTextCondition implements IUserCondition {
+ /**
+ * @see \wcf\system\condition\AbstractTextCondition::$fieldName
+ */
+ protected $fieldName = 'username';
+
+ /**
+ * @see \wcf\system\condition\AbstractSingleFieldCondition::$label
+ */
+ protected $label = 'wcf.user.username';
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::addUserCondition()
+ */
+ public function addUserCondition(Condition $condition, UserList $userList) {
+ $userList->getConditionBuilder()->add('user_table.username LIKE ?', array('%'.addcslashes($condition->username, '_%').'%'));
+ }
+
+ /**
+ * @see \wcf\system\condition\IUserCondition::checkUser()
+ */
+ public function checkUser(Condition $condition, User $user) {
+ return mb_strpos($user->username, $condition->username) !== false;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\cronjob;
+use wcf\data\cronjob\Cronjob;
+use wcf\data\user\UserAction;
+use wcf\system\cache\builder\UserGroupAssignmentCacheBuilder;
+use wcf\system\user\group\assignment\UserGroupAssignmentHandler;
+
+/**
+ * Executes automatic user group assignments.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.cronjob
+ * @category Community Framework
+ */
+class UserGroupAssignmentCronjob extends AbstractCronjob {
+ /**
+ * @see \wcf\system\cronjob\ICronjob::execute()
+ */
+ public function execute(Cronjob $cronjob) {
+ parent::execute($cronjob);
+
+ $assignments = UserGroupAssignmentCacheBuilder::getInstance()->getData();
+ $usersToGroup = array();
+ foreach ($assignments as $assignment) {
+ if (!isset($usersToGroup[$assignment->groupID])) {
+ $usersToGroup[$assignment->groupID] = array();
+ }
+
+ $usersToGroup[$assignment->groupID] = array_merge($usersToGroup[$assignment->groupID], UserGroupAssignmentHandler::getInstance()->getUsers($assignment));
+ }
+
+ foreach ($usersToGroup as $groupID => $users) {
+ $userAction = new UserAction(array_unique($users), 'addToGroups', array(
+ 'addDefaultGroups' => false,
+ 'deleteOldGroups' => false,
+ 'groups' => array($groupID)
+ ));
+ $userAction->executeAction();
+ }
+ }
+}
namespace wcf\system\option;
use wcf\data\option\Option;
use wcf\data\user\User;
+use wcf\data\user\UserList;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
}
}
+ /**
+ * @see \wcf\system\option\IOptionType::getData()
+ */
+ public function getData(Option $option, $newValue) {
+ return $newValue;
+ }
+
/**
* @see \wcf\system\option\IOptionType::getFormElement()
*/
return true;
}
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::addCondition()
+ */
+ public function addCondition(UserList $userList, Option $option, $value) {
+ $ageFrom = intval($value['ageFrom']);
+ $ageTo = intval($value['ageTo']);
+
+ if ($ageFrom < 0 || $ageFrom > 120 || $ageTo < 0 || $ageTo > 120) return false;
+
+ $dateFrom = DateUtil::getDateTimeByTimestamp(TIME_NOW)->sub(new \DateInterval('P'.($ageTo + 1).'Y'))->add(new \DateInterval('P1D'));
+ $dateTo = DateUtil::getDateTimeByTimestamp(TIME_NOW)->sub(new \DateInterval('P'.$ageFrom.'Y'));
+
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.User::getUserOptionID('birthdayShowYear').' = ?', array(1));
+
+ if ($ageFrom && $ageTo) {
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.$option->optionID.' BETWEEN DATE(?) AND DATE(?)', array($dateFrom->format('Y-m-d'), $dateTo->format('Y-m-d')));
+ }
+ else if ($ageFrom) {
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.$option->optionID.' BETWEEN DATE(?) AND DATE(?)', array('1893-01-01', $dateTo->format('Y-m-d')));
+ }
+ else {
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.$option->optionID.' BETWEEN DATE(?) AND DATE(?)', array($dateFrom->format('Y-m-d'), DateUtil::getDateTimeByTimestamp(TIME_NOW)->add(new \DateInterval('P1D'))->format('Y-m-d')));
+ }
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::checkUser()
+ */
+ public function checkUser(User $user, Option $option, $value) {
+ if (!$user->birthdayShowYear || !$user->birthday) return false;
+
+ $ageFrom = intval($value['ageFrom']);
+ $ageTo = intval($value['ageTo']);
+
+ $userAge = DateUtil::getAge($user->birthday);
+
+ if ($ageFrom && $ageTo) {
+ return $userAge >= $ageFrom && $userAge <= $ageTo;
+ }
+ else if ($ageFrom) {
+ return $userAge >= $ageFrom;
+ }
+ else {
+ return $userAge <= $ageTo;
+ }
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::getConditionData()
+ */
+ public function getConditionData(Option $option, $newValue) {
+ if (!$newValue['ageFrom'] && !$newValue['ageTo']) return null;
+
+ return $newValue;
+ }
}
<?php
namespace wcf\system\option;
use wcf\data\option\Option;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\WCF;
$conditions->add("option_value.userOption".$option->optionID." = ?", array(1));
return true;
}
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::addCondition()
+ */
+ public function addCondition(UserList $userList, Option $option, $value) {
+ $value = intval($value);
+ if (!$value) return;
+
+ if ($ageFrom < 0 || $ageFrom > 120 || $ageTo < 0 || $ageTo > 120) return false;
+
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.$option->optionID.' = ?', array(1));
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::checkUser()
+ */
+ public function checkUser(User $user, Option $option, $value) {
+ if (!$value) return false;
+
+ return $user->getUserOption($option->optionName);
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::getConditionData()
+ */
+ public function getConditionData(Option $option, $newValue) {
+ return $newValue;
+ }
}
--- /dev/null
+<?php
+namespace wcf\system\option;
+use wcf\data\option\Option;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
+
+/**
+ * Searchable user option types available for conditions have to implement this interface.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.option
+ * @category Community Framework
+ */
+interface ISearchableConditionUserOption extends ISearchableUserOption {
+ /**
+ * Adds the condition to the given user list to fetch the users which have
+ * the given value for the given option.
+ *
+ * @param \wcf\data\user\UserList $userList
+ * @param \wcf\data\option\Option $option
+ * @param mixed $value
+ */
+ public function addCondition(UserList $userList, Option $option, $value);
+
+ /**
+ * Returns true if given the user option of the given user matches a certain
+ * value.
+ *
+ * @param \wcf\data\user\User $user
+ * @param \wcf\data\option\Option $option
+ * @param mixed $value
+ * @return boolean
+ */
+ public function checkUser(User $user, Option $option, $value);
+
+ /**
+ * Returns the data of the condition or null if the option should be igored.
+ *
+ * @return mixed
+ */
+ public function getConditionData(Option $option, $newValue);
+}
/**
* Returns a condition for search sql query.
*
- * @param \wcf\system\database\condition\PreparedStatementConditionBuilder $conditions
+ * @param \wcf\system\database\condition\PreparedStatementConditionBuilder $conditions
* @param \wcf\data\option\Option $option
- * @param string $value
+ * @param mixed $value
* @return boolean
*/
public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value);
<?php
namespace wcf\system\option;
use wcf\data\option\Option;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
public function getSearchFormElement(Option $option, $value) {
WCF::getTPL()->assign(array(
'option' => $option,
- 'searchOption' => isset($_POST['searchOptions'][$option->optionName]),
+ 'searchOption' => $value !== $option->defaultValue || isset($_POST['searchOptions'][$option->optionName]),
'selectOptions' => $option->parseSelectOptions(),
'value' => (!is_array($value) ? explode("\n", $value) : $value)
));
$conditions->add("option_value.userOption".$option->optionID." REGEXP '".'(^|\n)'.implode('\n([^\n]*\n)*', array_map('escapeString', $value)).'($|\n)'."'");
return true;
}
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::addCondition()
+ */
+ public function addCondition(UserList $userList, Option $option, $value) {
+ if (!is_array($value) || empty($value)) return false;
+ $value = ArrayUtil::trim($value);
+
+ $userList->getConditionBuilder()->add("user_option_value.userOption".$option->optionID." REGEXP '".'(^|\n)'.implode('\n([^\n]*\n)*', array_map('escapeString', $value)).'($|\n)'."'");
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::checkUser()
+ */
+ public function checkUser(User $user, Option $option, $value) {
+ if (!is_array($value) || empty($value)) return false;
+
+ $optionValues = explode('\n', $user->getUserOption($option->optionName));
+
+ return count(array_diff($optionValues, $value)) > 0;
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::getConditionData()
+ */
+ public function getConditionData(Option $option, $newValue) {
+ return $newValue;
+ }
}
if (!$this->didInit) {
// get active options
$this->loadActiveOptions($this->categoryName);
-
+
// mark options as initialized
$this->didInit = true;
}
<?php
namespace wcf\system\option;
use wcf\data\option\Option;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
use wcf\system\database\util\PreparedStatementConditionBuilder;
/**
public function getCondition(PreparedStatementConditionBuilder &$conditions, Option $option, $value) {
return false;
}
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::addCondition()
+ */
+ public function addCondition(UserList $userList, Option $option, $value) {
+ // does nothing
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::checkUser()
+ */
+ public function checkUser(User $user, Option $option, $value) {
+ return false;
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::getConditionData()
+ */
+ public function getConditionData(Option $option, $newValue) {
+ return $newValue;
+ }
}
<?php
namespace wcf\system\option;
use wcf\data\option\Option;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
* @subpackage system.option
* @category Community Framework
*/
-class RadioButtonOptionType extends AbstractOptionType implements ISearchableUserOption {
+class RadioButtonOptionType extends AbstractOptionType implements ISearchableConditionUserOption {
/**
* name of the template that contains the form element of this option type
* @var string
*/
public function getSearchFormElement(Option $option, $value) {
$this->templateName = 'radioButtonSearchableOptionType';
- WCF::getTPL()->assign('searchOption', empty($_POST) || isset($_POST['searchOptions'][$option->optionName]));
+ WCF::getTPL()->assign('searchOption', $value !== $option->defaultValue || isset($_POST['searchOptions'][$option->optionName]));
return $this->getFormElement($option, $value);
}
$conditions->add("option_value.userOption".$option->optionID." = ?", array(StringUtil::trim($value)));
return true;
}
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::addCondition()
+ */
+ public function addCondition(UserList $userList, Option $option, $value) {
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.$option->optionID.' = ?', array(StringUtil::trim($value)));
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::checkUser()
+ */
+ public function checkUser(User $user, Option $option, $value) {
+ return mb_strtolower($user->getUserOption($option->optionName)) == mb_strtolower(StringUtil::trim($value));
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::getConditionData()
+ */
+ public function getConditionData(Option $option, $newValue) {
+ return $newValue;
+ }
}
'disableOptions' => $options['disableOptions'],
'enableOptions' => $options['enableOptions'],
'option' => $option,
- 'searchOption' => isset($_POST['searchOptions'][$option->optionName]),
+ 'searchOption' => ($value !== null && $value !== $option->defaultValue) || isset($_POST['searchOptions'][$option->optionName]),
'selectOptions' => $option->parseSelectOptions(),
'value' => $value
));
<?php
namespace wcf\system\option;
use wcf\data\option\Option;
+use wcf\data\user\User;
+use wcf\data\user\UserList;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
* @subpackage system.option
* @category Community Framework
*/
-class TextOptionType extends AbstractOptionType implements ISearchableUserOption {
+class TextOptionType extends AbstractOptionType implements ISearchableConditionUserOption {
/**
* input type
* @var string
'option' => $option,
'inputType' => $this->inputType,
'inputClass' => $this->inputClass,
- 'searchOption' => isset($_POST['searchOptions'][$option->optionName]),
+ 'searchOption' => $value !== $option->defaultValue || isset($_POST['searchOptions'][$option->optionName]),
'value' => $value
));
return WCF::getTPL()->fetch('textSearchableOptionType');
return $newValue;
}
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::addCondition()
+ */
+ public function addCondition(UserList $userList, Option $option, $value) {
+ $value = StringUtil::trim($value);
+ if ($value == '') {
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.$option->optionID.' = ?', array(''));
+ }
+ else {
+ $userList->getConditionBuilder()->add('user_option_value.userOption'.$option->optionID.' LIKE ?', array('%'.addcslashes($value, '_%').'%'));
+ }
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::checkUser()
+ */
+ public function checkUser(User $user, Option $option, $value) {
+ $value = StringUtil::trim($value);
+ if ($value == '') {
+ return $user->getUserOption($option->optionName) == '';
+ }
+ else {
+ return mb_stripos($user->getUserOption($option->optionName), $value) !== false;
+ }
+ }
+
+ /**
+ * @see \wcf\system\option\ISearchableConditionUserOption::getConditionData()
+ */
+ public function getConditionData(Option $option, $newValue) {
+ return $newValue;
+ }
}
public function getSearchFormElement(Option $option, $value) {
WCF::getTPL()->assign(array(
'option' => $option,
- 'searchOption' => isset($_POST['searchOptions'][$option->optionName]),
+ 'searchOption' => $value !== $option->defaultValue || isset($_POST['searchOptions'][$option->optionName]),
'value' => $value
));
return WCF::getTPL()->fetch('textareaSearchableOptionType');
* @subpackage system.option
* @category Community Framework
*/
-class UserGroupOptionType extends UserGroupsUserGroupOptionType {
-}
+class UserGroupOptionType extends UserGroupsUserGroupOptionType { }
use wcf\data\user\option\ViewableUserOption;
use wcf\data\user\User;
use wcf\system\exception\UserInputException;
+use wcf\system\option\ISearchableConditionUserOption;
use wcf\system\option\OptionHandler;
/**
protected $cacheClass = 'wcf\system\cache\builder\UserOptionCacheBuilder';
/**
- * true, if within registration process
+ * true if within registration process
* @var boolean
*/
public $inRegistration = false;
/**
- * true, if within edit mode
+ * true if within edit mode
* @var boolean
*/
public $editMode = true;
/**
- * true, if within search mode
+ * true if within search mode
* @var boolean
*/
public $searchMode = false;
/**
- * true, if empty options should be removed
+ * true if empty options should be removed
* @var boolean
*/
public $removeEmptyOptions = false;
*/
public $user = null;
+ /**
+ * true if the condition mode during search mode is enabled
+ * @var boolean
+ */
+ public $conditionMode = false;
+
/**
* Shows empty options.
*/
$this->optionValues = array();
}
+ /**
+ * Enables the condition mode.
+ *
+ * @param boolean $enable
+ */
+ public function enableConditionMode($enable = true) {
+ if (!$this->searchMode) {
+ $this->enableSearchMode();
+ }
+
+ $this->conditionMode = $enable;
+ }
+
+ /**
+ * Returns the option values.
+ *
+ * @return array
+ */
+ public function getOptionValues() {
+ return $this->optionValues;
+ }
+
+ /**
+ * Sets the option values.
+ *
+ * @param array $values
+ */
+ public function setOptionValues(array $values) {
+ $this->optionValues = $values;
+ }
+
/**
* @see \wcf\system\option\OptionHandler::getOption()
*/
return false;
}
+ if ($this->conditionMode && (!$this->getTypeObject($option->optionType) instanceof ISearchableConditionUserOption)) {
+ return false;
+ }
+
if ($this->user !== null) {
$option->setUser($this->user);
}
use wcf\data\user\UserProfileAction;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\SystemException;
+use wcf\system\user\group\assignment\UserGroupAssignmentHandler;
use wcf\system\SingletonFactory;
use wcf\system\WCF;
// update user ranks
$this->updateUserRanks(array($userID));
+
+ // check if the user will be automatically added to new user groups
+ // because of the new activity points
+ UserGroupAssignmentHandler::getInstance()->checkUsers(array($userID));
}
/**
// update activity points for given user ids
if ($updateUsers) {
$this->updateUsers($userIDs);
+
+ // check if one of the user will be automatically added
+ // to new user groups because of the new activity points
+ UserGroupAssignmentHandler::getInstance()->checkUsers($userIDs);
}
}
--- /dev/null
+<?php
+namespace wcf\system\user\group\assignment;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\data\user\group\assignment\UserGroupAssignment;
+use wcf\data\user\User;
+use wcf\data\user\UserAction;
+use wcf\data\user\UserList;
+use wcf\system\cache\builder\UserGroupAssignmentCacheBuilder;
+use wcf\system\SingletonFactory;
+
+/**
+ * Handles user group assignment-related matters.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.user.group.assignment
+ * @category Community Framework
+ */
+class UserGroupAssignmentHandler extends SingletonFactory {
+ /**
+ * list of grouped user group assignment condition object types
+ * @var array
+ */
+ protected $groupedObjectTypes = array();
+
+ /**
+ * Checks if the users with the given ids should be assigned to new user
+ * groups.
+ *
+ * Note: This method uses the user ids as a parameter instead of user objects
+ * on purpose to make sure the latest data of the users are fetched.
+ *
+ * @param array<integer> $userIDs
+ */
+ public function checkUsers(array $userIDs) {
+ if (empty($userIDs)) return;
+
+ $userList = new UserList();
+ $userList->getConditionBuilder()->add('user_table.userID IN (?)', array($userIDs));
+ $userList->readObjects();
+
+ $assignments = UserGroupAssignmentCacheBuilder::getInstance()->getData();
+ foreach ($userList as $user) {
+ $groupIDs = $user->getGroupIDs();
+ $newGroupIDs = array();
+
+ foreach ($assignments as $assignment) {
+ if (in_array($assignment->groupID, $groupIDs) || in_array($assignment->groupID, $newGroupIDs)) {
+ continue;
+ }
+
+ $checkFailed = false;
+ $conditions = $assignment->getConditions();
+ foreach ($conditions as $condition) {
+ if (!$condition->getObjectType()->getProcessor()->checkUser($condition, $user)) {
+ $checkFailed = true;
+ break;
+ }
+ }
+
+ if (!$checkFailed) {
+ $newGroupIDs[] = $assignment->groupID;
+ }
+ }
+
+ $userAction = new UserAction(array($user), 'addToGroups', array(
+ 'addDefaultGroups' => false,
+ 'deleteOldGroups' => false,
+ 'groups' => $newGroupIDs
+ ));
+ $userAction->executeAction();
+ }
+ }
+
+ /**
+ * Returns the list of grouped user group assignment condition object types.
+ *
+ * @return array
+ */
+ public function getGroupedObjectTypes() {
+ return $this->groupedObjectTypes;
+ }
+
+ /**
+ * Returns the users who fullfil all conditions of the given user group
+ * assignment.
+ *
+ * @param \wcf\data\user\group\assignment\UserGroupAssignment $assignment
+ * @return array<\wcf\data\user\User>
+ */
+ public function getUsers(UserGroupAssignment $assignment) {
+ $userList = new UserList();
+ $userList->getConditionBuilder()->add('user_table.userID NOT IN (SELECT userID FROM wcf'.WCF_N.'_user_to_group WHERE groupID = ?)', array(
+ $assignment->groupID
+ ));
+
+ $conditions = $assignment->getConditions();
+ foreach ($conditions as $condition) {
+ $condition->getObjectType()->getProcessor()->addUserCondition($condition, $userList);
+ }
+ $userList->readObjects();
+
+ return $userList->getObjects();
+ }
+
+ /**
+ * @see \wcf\system\SingletonFactory::init()
+ */
+ protected function init() {
+ $objectTypes = ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.condition.userGroupAssignment');
+ foreach ($objectTypes as $objectType) {
+ if (!$objectType->conditiongroup) continue;
+
+ if (!isset($this->groupedObjectTypes[$objectType->conditiongroup])) {
+ $this->groupedObjectTypes[$objectType->conditiongroup] = array();
+ }
+
+ $this->groupedObjectTypes[$objectType->conditiongroup][$objectType->objectTypeID] = $objectType;
+ }
+ }
+}
if (isset($value[0])) $year = intval($value[0]);
if (isset($value[1])) $month = intval($value[1]);
if (isset($value[2])) $day = intval($value[2]);
-
+
// calc
if ($year) {
$age = self::format(null, 'Y') - $year;
<item name="wcf.acp.group.option.error.validationFailed"><![CDATA[Sie haben einen ungültigen Inhalt eingegeben.]]></item>
<item name="wcf.acp.group.option.admin.user.canDisableAvatar"><![CDATA[Kann Avatar sperren]]></item>
<item name="wcf.acp.group.option.admin.user.canDisableSignature"><![CDATA[Kann Signatur sperren]]></item>
+ <item name="wcf.acp.group.option.admin.user.canManageGroupAssignment"><![CDATA[Kann automatische Gruppenzuordnungen verwalten]]></item>
+ <item name="wcf.acp.group.assignment.add"><![CDATA[Automatische Benutzergruppen-Zuordnung hinzufügen]]></item>
+ <item name="wcf.acp.group.assignment.button.add"><![CDATA[Automatische Zuordnung hinzufügen]]></item>
+ <item name="wcf.acp.group.assignment.button.list"><![CDATA[Automatische Zuordnungen auflisten]]></item>
+ <item name="wcf.acp.group.assignment.conditions"><![CDATA[Bedingungen]]></item>
+ <item name="wcf.acp.group.assignment.conditions.description"><![CDATA[Benutzer müssen die folgenden Bedingungen erfüllen um automatisch der Benutzergruppe hinzugefügt zu werden]]></item>
+ <item name="wcf.acp.group.assignment.delete.confirmMessage"><![CDATA[Wollen Sie diese automatische Benutzergruppen-Zuordnung wirklich löschen?]]></item>
+ <item name="wcf.acp.group.assignment.edit"><![CDATA[Automatische Benutzergruppen-Zuordnung bearbeiten]]></item>
+ <item name="wcf.acp.group.assignment.error.noConditions"><![CDATA[Sie haben keine Bedingungen ausgewählt.]]></item>
+ <item name="wcf.acp.group.assignment.list"><![CDATA[Automatische Benutzergruppen-Zuordnungen]]></item>
+ <item name="wcf.acp.group.assignment.userGroup"><![CDATA[Benutzergruppe]]></item>
+ <item name="wcf.acp.group.assignment.isDisabled"><![CDATA[Automatische Zuordnung deaktivieren]]></item>
</category>
<category name="wcf.acp.index">
<item name="wcf.acp.menu.link.maintenance.import"><![CDATA[Datenimport]]></item>
<item name="wcf.acp.menu.link.maintenance.rebuildData"><![CDATA[Anzeigen aktualisieren]]></item>
<item name="wcf.acp.menu.link.log.stat"><![CDATA[Statistiken]]></item>
+ <item name="wcf.acp.menu.link.group.assignment"><![CDATA[Automatische Zuordnungen]]></item>
</category>
<category name="wcf.acp.option">
<item name="wcf.global.form.error.lessThan"><![CDATA[Der eingebene Wert muss kleiner sein als {#$lessThan}.]]></item>
<item name="wcf.global.form.error.lessThan.javaScript"><![CDATA[{literal}Der eingebene Wert muss kleiner sein als {#$lessThan}.{/literal}]]></item>
<item name="wcf.global.form.error.multilingual"><![CDATA[Bitte füllen Sie dieses Eingabefeld für jede Sprache aus.]]></item>
+ <item name="wcf.global.form.error.noValidSelection"><![CDATA[Wählen Sie eine der angebotenen Optionen aus.]]></item>
<item name="wcf.global.form.error.securityToken"><![CDATA[Ihre Sitzung ist abgelaufen, bitte senden Sie das Formular erneut ab.]]></item>
</category>
<item name="wcf.user.avatar.upload.success"><![CDATA[Der neue Avatar wurde erfolgreich gespeichert.]]></item>
</category>
+ <category name="wcf.user.condition">
+ <item name="wcf.user.condition.activityPoints.greaterThan"><![CDATA[Punkte mehr als]]></item>
+ <item name="wcf.user.condition.activityPoints.greaterThan.error.lessThan"><![CDATA[Die Werte in „Punkte weniger als“ und „Punkte mehr als“ sind widersprüchlich.]]></item>
+ <item name="wcf.user.condition.activityPoints.lessThan"><![CDATA[Punkte weniger als]]></item>
+ <item name="wcf.user.condition.avatar"><![CDATA[Avatar]]></item>
+ <item name="wcf.user.condition.avatar.avatar"><![CDATA[Eigener Avatar]]></item>
+ <item name="wcf.user.condition.avatar.gravatar"><![CDATA[Gravatar]]></item>
+ <item name="wcf.user.condition.avatar.noAvatar"><![CDATA[Kein Avatar]]></item>
+ <item name="wcf.user.condition.conditionGroup.contents"><![CDATA[Inhalte]]></item>
+ <item name="wcf.user.condition.conditionGroup.general"><![CDATA[Allgemeine Daten]]></item>
+ <item name="wcf.user.condition.conditionGroup.userOptions"><![CDATA[Persönliche Daten]]></item>
+ <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.integerProperty.error.maxValue"><![CDATA[Der Wert darf nicht kleiner sein {#$minValue}.]]></item>
+ <item name="wcf.user.condition.integerProperty.error.minValue"><![CDATA[Der Wert muss größer sein als {#$minValue}.]]></item>
+ <item name="wcf.user.condition.languages"><![CDATA[Sprachen]]></item>
+ <item name="wcf.user.condition.likesReceived.greaterThan"><![CDATA[Erhaltene Likes mehr als]]></item>
+ <item name="wcf.user.condition.likesReceived.greaterThan.error.lessThan"><![CDATA[Die Werte in „Erhaltene Likes weniger als“ und „Erhaltene Likes mehr als“ sind widersprüchlich.]]></item>
+ <item name="wcf.user.condition.likesReceived.lessThan"><![CDATA[Erhaltene Likes weniger als]]></item>
+ <item name="wcf.user.condition.notGroupIDs"><![CDATA[nicht in Benutzergruppen]]></item>
+ <item name="wcf.user.condition.notGroupIDs.description"><![CDATA[Benutzer dürfen in den ausgewählten Benutzergruppen nicht Mitglied sein.]]></item>
+ <item name="wcf.user.condition.notGroupIDs.error.groupIDsIntersection"><![CDATA[Die ausgewählten Benutzergruppen in „in Benutzergruppen“ und „nicht in Benutzergruppen“ sind widersprüchlich.]]></item>
+ <item name="wcf.user.condition.registrationDate"><![CDATA[Registrierungsdatum]]></item>
+ <item name="wcf.user.condition.registrationDate.error.endBeforeStart"><![CDATA[Das Enddatum ist vor dem Startdatum.]]></item>
+ <item name="wcf.user.condition.registrationDate.error.endNotValid"><![CDATA[Das Startdatum ist ungültig.]]></item>
+ <item name="wcf.user.condition.registrationDate.error.startNotValid"><![CDATA[Das Enddatum ist ungültig.]]></item>
+ <item name="wcf.user.condition.registrationDateInterval.greaterThan"><![CDATA[mehr als X Tage registiert]]></item>
+ <item name="wcf.user.condition.registrationDateInterval.greaterThan.error.lessThan"><![CDATA[Die Werte in „weniger als X Tage registiert“ und „mehr als X Tage registiert“ sind widersprüchlich.]]></item>
+ <item name="wcf.user.condition.registrationDateInterval.lessThan"><![CDATA[weniger als X Tage registiert]]></item>
+ <item name="wcf.user.condition.state"><![CDATA[Zustand]]></item>
+ <item name="wcf.user.condition.state.isBanned"><![CDATA[Gesperrt]]></item>
+ <item name="wcf.user.condition.state.isBanned.error.conflict"><![CDATA[„Gesperrt“ und „Nicht gesperrt“ können nicht gleichzeitig ausgewählt werden.]]></item>
+ <item name="wcf.user.condition.state.isDisabled"><![CDATA[Nicht aktiviert]]></item>
+ <item name="wcf.user.condition.state.isEnabled"><![CDATA[Aktiviert]]></item>
+ <item name="wcf.user.condition.state.isEnabled.error.conflict"><![CDATA[„Aktiviert“ und „Nicht aktiviert“ können nicht gleichzeitig ausgewählt werden.]]></item>
+ <item name="wcf.user.condition.state.isNotBanned"><![CDATA[Nicht gesperrt]]></item>
+ </category>
+
<category name="wcf.user.notification">
<item name="wcf.user.notification.button.confirmed"><![CDATA[OK]]></item>
<item name="wcf.user.notification.count"><![CDATA[if (data.returnValues.count == 0) { "Keine Benachrichtigungen" } else if (data.returnValues.count == 1) { "Eine Benachrichtigung" } else { data.returnValues.count + " Benachrichtigungen" }]]></item>
<item name="wcf.acp.group.option.error.validationFailed"><![CDATA[You have entered an invalid value.]]></item>
<item name="wcf.acp.group.option.admin.user.canDisableAvatar"><![CDATA[Can block avatar]]></item>
<item name="wcf.acp.group.option.admin.user.canDisableSignature"><![CDATA[Can block signature]]></item>
+ <item name="wcf.acp.group.option.admin.user.canManageGroupAssignment"><![CDATA[Can manage automatic user group assignments]]></item>
+ <item name="wcf.acp.group.assignment.add"><![CDATA[Add User Group Automatic Assignment]]></item>
+ <item name="wcf.acp.group.assignment.button.add"><![CDATA[Add Automatic Assignment]]></item>
+ <item name="wcf.acp.group.assignment.button.list"><![CDATA[Automatic Assignments]]></item>
+ <item name="wcf.acp.group.assignment.conditions"><![CDATA[Conditions]]></item>
+ <item name="wcf.acp.group.assignment.conditions.description"><![CDATA[Users need to fulfill the following conditions to be automatically added to the user group]]></item>
+ <item name="wcf.acp.group.assignment.delete.confirmMessage"><![CDATA[Do you really want to delete this automatic user group assignment]]></item>
+ <item name="wcf.acp.group.assignment.edit"><![CDATA[Edit User Group Automatic Assignment]]></item>
+ <item name="wcf.acp.group.assignment.error.noConditions"><![CDATA[You have not chosen any condition.]]></item>
+ <item name="wcf.acp.group.assignment.list"><![CDATA[Automatic User Group Assignments]]></item>
+ <item name="wcf.acp.group.assignment.userGroup"><![CDATA[User Group]]></item>
+ <item name="wcf.acp.group.assignment.isDisabled"><![CDATA[Disable Automatic Assignment]]></item>
</category>
<category name="wcf.acp.index">
<item name="wcf.acp.menu.link.maintenance.import"><![CDATA[Data Import]]></item>
<item name="wcf.acp.menu.link.maintenance.rebuildData"><![CDATA[Rebuild Data]]></item>
<item name="wcf.acp.menu.link.log.stat"><![CDATA[Statistics]]></item>
+ <item name="wcf.acp.menu.link.group.assignment"><![CDATA[Automatic Assignments]]></item>
</category>
<category name="wcf.acp.option">
<item name="wcf.global.form.error.lessThan"><![CDATA[The entered value has to be less than {#$lessThan}.]]></item>
<item name="wcf.global.form.error.lessThan.javaScript"><![CDATA[{literal}The entered value has to be less than {#$lessThan}.{/literal}]]></item>
<item name="wcf.global.form.error.multilingual"><![CDATA[Please fill in this field for all languages.]]></item>
+ <item name="wcf.global.form.error.noValidSelection"><![CDATA[Choose one of the available options.]]></item>
<item name="wcf.global.form.error.securityToken"><![CDATA[Your session has expired, please submit the form again.]]></item>
</category>
<item name="wcf.user.avatar.upload.success"><![CDATA[Avatar has been saved.]]></item>
</category>
+ <category name="wcf.user.condition">
+ <item name="wcf.user.condition.activityPoints.greaterThan"><![CDATA[Points Greater Than]]></item>
+ <item name="wcf.user.condition.activityPoints.greaterThan.error.lessThan"><![CDATA[The values in “Points Less Than“ and “Points Greater Than“ are conflicting.]]></item>
+ <item name="wcf.user.condition.activityPoints.lessThan"><![CDATA[Points Less Than]]></item>
+ <item name="wcf.user.condition.avatar"><![CDATA[Avatar]]></item>
+ <item name="wcf.user.condition.avatar.avatar"><![CDATA[Own Avatar]]></item>
+ <item name="wcf.user.condition.avatar.gravatar"><![CDATA[Gravatar]]></item>
+ <item name="wcf.user.condition.avatar.noAvatar"><![CDATA[No Avatar]]></item>
+ <item name="wcf.user.condition.conditionGroup.contents"><![CDATA[Contents]]></item>
+ <item name="wcf.user.condition.conditionGroup.general"><![CDATA[General Data]]></item>
+ <item name="wcf.user.condition.conditionGroup.userOptions"><![CDATA[Personal Data]]></item>
+ <item name="wcf.user.condition.groupIDs"><![CDATA[in User Groups]]></item>
+ <item name="wcf.user.condition.groupIDs.description"><![CDATA[Users have to be a member of the selected user groups.]]></item>
+ <item name="wcf.user.condition.integerProperty.error.maxValue"><![CDATA[The value may not be less than {#$minValue}.]]></item>
+ <item name="wcf.user.condition.integerProperty.error.minValue"><![CDATA[The value has to be greater than {#$minValue}.]]></item>
+ <item name="wcf.user.condition.languages"><![CDATA[Languages]]></item>
+ <item name="wcf.user.condition.likesReceived.greaterThan"><![CDATA[Likes Received Greater Than]]></item>
+ <item name="wcf.user.condition.likesReceived.greaterThan.error.lessThan"><![CDATA[The values in “Likes Received Less Than“ and “Likes Received Greater Than“ are conflicting.]]></item>
+ <item name="wcf.user.condition.likesReceived.lessThan"><![CDATA[Likes Received Less Than]]></item>
+ <item name="wcf.user.condition.notGroupIDs"><![CDATA[not in User Groups]]></item>
+ <item name="wcf.user.condition.notGroupIDs.description"><![CDATA[Users may not be a member of the selected user groups.]]></item>
+ <item name="wcf.user.condition.notGroupIDs.error.groupIDsIntersection"><![CDATA[The selected user groups in “in User Groups“ and “not in User Groups“ are conflicting.]]></item>
+ <item name="wcf.user.condition.registrationDate"><![CDATA[Registration Date]]></item>
+ <item name="wcf.user.condition.registrationDate.error.endBeforeStart"><![CDATA[The end date is prior to the start date.]]></item>
+ <item name="wcf.user.condition.registrationDate.error.endNotValid"><![CDATA[The start date is not valid.]]></item>
+ <item name="wcf.user.condition.registrationDate.error.startNotValid"><![CDATA[The end date is not valid.]]></item>
+ <item name="wcf.user.condition.registrationDateInterval.greaterThan"><![CDATA[registered less than X days ago]]></item>
+ <item name="wcf.user.condition.registrationDateInterval.greaterThan.error.lessThan"><![CDATA[The values in “registered less than X days ago“ and “registered more than X days ago“ are conflicting.]]></item>
+ <item name="wcf.user.condition.registrationDateInterval.lessThan"><![CDATA[registered more than X days ago]]></item>
+ <item name="wcf.user.condition.state"><![CDATA[State]]></item>
+ <item name="wcf.user.condition.state.isBanned"><![CDATA[Banned]]></item>
+ <item name="wcf.user.condition.state.isBanned.error.conflict"><![CDATA[You may not simultaneously select “Banned“ and “Not Banned“.]]></item>
+ <item name="wcf.user.condition.state.isDisabled"><![CDATA[Awaiting Approval]]></item>
+ <item name="wcf.user.condition.state.isEnabled"><![CDATA[Approved]]></item>
+ <item name="wcf.user.condition.state.isEnabled.error.conflict"><![CDATA[You may not simultaneously select “Approved“ and “Awaiting Approval“.]]></item>
+ <item name="wcf.user.condition.state.isNotBanned"><![CDATA[Not Banned]]></item>
+ </category>
+
<category name="wcf.user.notification">
<item name="wcf.user.notification.button.confirmed"><![CDATA[OK]]></item>
<item name="wcf.user.notification.count"><![CDATA[if (data.returnValues.count == 0) { "No Notifications" } else if (data.returnValues.count == 1) { "1 Notification" } else { data.returnValues.count + " Notifications" }]]></item>
KEY lastResponseTime (userID, time)
);
+DROP TABLE IF EXISTS wcf1_condition;
+CREATE TABLE wcf1_condition (
+ conditionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ objectTypeID INT(10) NOT NULL,
+ objectID INT(10) NOT NULL,
+ conditionData MEDIUMTEXT
+);
+
DROP TABLE IF EXISTS wcf1_core_object;
CREATE TABLE wcf1_core_object (
objectID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
showOnTeamPage TINYINT(1) NOT NULL DEFAULT 0
);
+DROP TABLE IF EXISTS wcf1_user_group_assignment;
+CREATE TABLE wcf1_user_group_assignment (
+ assignmentID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ groupID INT(10) NOT NULL,
+ title VARCHAR(255) NOT NULL,
+ isDisabled TINYINT(1) NOT NULL DEFAULT 0
+);
+
DROP TABLE IF EXISTS wcf1_user_group_option;
CREATE TABLE wcf1_user_group_option (
optionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
ALTER TABLE wcf1_clipboard_page ADD FOREIGN KEY (actionID) REFERENCES wcf1_clipboard_action (actionID) ON DELETE CASCADE;
ALTER TABLE wcf1_clipboard_page ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
+ALTER TABLE wcf1_condition ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
+
ALTER TABLE wcf1_core_object ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
ALTER TABLE wcf1_cronjob ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_collapsible_content ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_collapsible_content ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
+ALTER TABLE wcf1_user_group_assignment ADD FOREIGN KEY (groupID) REFERENCES wcf1_user_group (groupID) ON DELETE CASCADE;
+
ALTER TABLE wcf1_user_group_option ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_group_option_category ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;