Файл: library/XenForo/Model/Moderator.php
Строк: 906
<?php
/**
* Model for moderators.
*
* @package XenForo_Moderator
*/
class XenForo_Model_Moderator extends XenForo_Model
{
/**
* Gets a general moderator records based on user ID.
*
* @param integer $userId
*
* @return array|false
*/
public function getGeneralModeratorByUserId($userId)
{
return $this->_getDb()->fetchRow('
SELECT moderator.*, user.username
FROM xf_moderator AS moderator
INNER JOIN xf_user AS user ON (user.user_id = moderator.user_id)
WHERE moderator.user_id = ?
', $userId);
}
/**
* Gets all general moderators, potentially limited by super moderator status.
*
* @param boolean|null $isSuperModerator If not null, limits to super or non-super mods only
*
* @return array Format: [user id] => info
*/
public function getAllGeneralModerators($isSuperModerator = null)
{
if ($isSuperModerator === null)
{
$moderatorClause = '1=1';
}
else if ($isSuperModerator)
{
$moderatorClause = 'moderator.is_super_moderator = 1';
}
else
{
$moderatorClause = 'moderator.is_super_moderator = 0';
}
return $this->fetchAllKeyed('
SELECT moderator.*, user.username,
user.avatar_date, user.gravatar
FROM xf_moderator AS moderator
INNER JOIN xf_user AS user ON (user.user_id = moderator.user_id)
WHERE ' . $moderatorClause . '
ORDER BY user.username
', 'user_id');
}
/**
* Gets a matching content moderator.
*
* @param array $conditions
* @param array $fetchOptions
*
* @return array|false
*/
public function getContentModerator(array $conditions, array $fetchOptions = array())
{
$moderators = $this->getContentModerators($conditions, $fetchOptions);
return reset($moderators);
}
/**
* Gets all matching content moderators.
*
* @param array $conditions
* @param array $fetchOptions
*
* @return array Format: [moderator id] => info
*/
public function getContentModerators(array $conditions = array(), array $fetchOptions = array())
{
$whereConditions = $this->prepareContentModeratorConditions($conditions, $fetchOptions);
$limitOptions = $this->prepareLimitFetchOptions($fetchOptions);
$sqlClauses = $this->prepareContentModeratorFetchOptions($fetchOptions);
return $this->fetchAllKeyed($this->limitQueryResults(
'
SELECT moderator_content.*, user.username
' . $sqlClauses['selectFields'] . '
FROM xf_moderator_content AS moderator_content
INNER JOIN xf_user AS user ON (user.user_id = moderator_content.user_id)
' . $sqlClauses['joinTables'] . '
WHERE ' . $whereConditions . '
' . $sqlClauses['orderClause'] . '
', $limitOptions['limit'], $limitOptions['offset']
), 'moderator_id');
}
/**
* Prepares the set of content moderator conditions.
*
* @param array $conditions
* @param array $fetchOptions
*
* @return string SQL clause value for conditions
*/
public function prepareContentModeratorConditions(array $conditions, array &$fetchOptions)
{
$sqlConditions = array();
$db = $this->_getDb();
if (isset($conditions['moderator_id']))
{
$sqlConditions[] = 'moderator_content.moderator_id = ' . $db->quote($conditions['moderator_id']);
}
if (!empty($conditions['content']))
{
if (is_array($conditions['content']))
{
$sqlConditions[] = 'moderator_content.content_type = ' . $db->quote($conditions['content'][0]);
$sqlConditions[] = 'moderator_content.content_id = ' . $db->quote($conditions['content'][1]);
}
else
{
$sqlConditions[] = 'moderator_content.content_type = ' . $db->quote($conditions['content']);
}
}
if (isset($conditions['user_id']))
{
$sqlConditions[] = 'moderator_content.user_id = ' . $db->quote($conditions['user_id']);
}
return $this->getConditionsForClause($sqlConditions);
}
/**
* Prepares the content moderator fetch options into select fields, joins, and ordering.
*
* @param array $fetchOptions
*
* @return array Keys: selectFields, joinTables, orderClause
*/
public function prepareContentModeratorFetchOptions(array $fetchOptions)
{
$selectFields = '';
$joinTables = '';
$orderBy = '';
if (isset($fetchOptions['order']))
{
switch ($fetchOptions['order'])
{
case 'username':
$orderBy = 'user.username';
break;
}
}
else
{
$orderBy = 'user.username';
}
return array(
'selectFields' => $selectFields,
'joinTables' => $joinTables,
'orderClause' => ($orderBy ? "ORDER BY $orderBy" : '')
);
}
/**
* Gets a content moderator by its unique ID.
*
* @param integer $id
*
* @return array|false
*/
public function getContentModeratorById($id)
{
return $this->getContentModerator(array('moderator_id' => $id));
}
/**
* Gets a content moderator by the unique combination of content and user ID.
*
* @param string $contentType
* @param integer $contentId
* @param integer $userId
*
* @return array|false
*/
public function getContentModeratorByContentAndUserId($contentType, $contentId, $userId)
{
return $this->getContentModerator(array(
'content' => array($contentType, $contentId),
'user_id' => $userId
));
}
/**
* Gets all content moderator info for a specified user ID
*
* @param integer $userId
*
* @return array Format: [moderator id] => info
*/
public function getContentModeratorsByUserId($userId)
{
return $this->getContentModerators(
array('user_id' => $userId),
array('order' => false)
);
}
/**
* Inserts or updates the necessary content moderator record.
*
* @param integer $userId
* @param string $contentType
* @param integer $contentId
* @param array $modPerms List of moderator permissions to apply to this content
* @param array $extra Extra info. Includes general_moderator_permissions and extra_user_group_ids
*
* @return integer Moderator ID
*/
public function insertOrUpdateContentModerator($userId, $contentType, $contentId, array $modPerms, array $extra = array())
{
$contentModerator = $this->getContentModeratorByContentAndUserId($contentType, $contentId, $userId);
$dw = XenForo_DataWriter::create('XenForo_DataWriter_ModeratorContent');
if ($contentModerator)
{
$dw->setExistingData($contentModerator, true);
}
else
{
$dw->set('content_type', $contentType);
$dw->set('content_id', $contentId);
$dw->set('user_id', $userId);
}
if (isset($extra['general_moderator_permissions']))
{
$dw->setExtraData(XenForo_DataWriter_ModeratorContent::DATA_GENERAL_PERMISSIONS, $extra['general_moderator_permissions']);
}
if (isset($extra['extra_user_group_ids']))
{
$dw->setExtraData(XenForo_DataWriter_ModeratorContent::DATA_EXTRA_GROUP_IDS, $extra['extra_user_group_ids']);
}
if (isset($extra['is_staff']))
{
$dw->setOption(XenForo_DataWriter_ModeratorContent::OPTION_SET_IS_STAFF, $extra['is_staff']);
}
$dw->set('moderator_permissions', $modPerms);
$dw->save();
return $dw->get('moderator_id');
}
/**
* Inserts or updates the necessary general moderator record.
*
* @param integer $userId
* @param array $modPerms General moderator permissions. Does not include content-specific super mod perms.
* @param boolean|null $isSuperModerator If non-null, the new super moderator setting
* @param array $extra Extra data, including extra_user_group_ids and super_moderator_permissions
*
* @return integer Moderator ID
*/
public function insertOrUpdateGeneralModerator($userId, array $modPerms, $isSuperModerator = null, array $extra = array())
{
$moderator = $this->getGeneralModeratorByUserId($userId);
$dw = XenForo_DataWriter::create('XenForo_DataWriter_Moderator');
if ($moderator)
{
$dw->setExistingData($moderator, true);
}
else
{
$dw->set('user_id', $userId);
}
if ($isSuperModerator !== null)
{
$dw->set('is_super_moderator', $isSuperModerator);
}
if (isset($extra['extra_user_group_ids']))
{
$dw->set('extra_user_group_ids', $extra['extra_user_group_ids']);
}
if (isset($extra['is_staff']))
{
$dw->setOption(XenForo_DataWriter_Moderator::OPTION_SET_IS_STAFF, $extra['is_staff']);
}
if (isset($extra['super_moderator_permissions']))
{
$modPerms = $this->mergeModeratorPermissions($modPerms, $extra['super_moderator_permissions']);
}
$dw->set('moderator_permissions', $modPerms);
$dw->save();
return $userId;
}
/**
* Merges 2 sets of "grouped" moderator permissions.
*
* @param array $modPerms Existing permissions like [group][permission] => info
* @param array $merge Merging permissions like [group][permission] => info
*
* @return array Merged set
*/
public function mergeModeratorPermissions(array $modPerms, array $merge)
{
foreach ($merge AS $generalGroupId => $generalGroup)
{
foreach ($generalGroup AS $generalId => $general)
{
$modPerms[$generalGroupId][$generalId] = $general;
}
}
return $modPerms;
}
/**
* Merges only general moderator permissions into a set of grouped permissions.
* The initial set may contain more than general moderator permissions.
*
* @param array $modPerms Existing permissions like [group][permission] => info
* @param array $merge Merging permissions like [group][permission] => info
*
* @return array Merged set
*/
public function mergeGeneralModeratorPermissions(array $modPerms, array $merge)
{
$generalModeratorPermissions = $this->getGeneralModeratorPermissions();
foreach ($merge AS $generalGroupId => $generalGroup)
{
foreach ($generalGroup AS $generalId => $general)
{
if (isset($generalModeratorPermissions[$generalGroupId][$generalId]))
{
$modPerms[$generalGroupId][$generalId] = $general;
}
}
}
return $modPerms;
}
/**
* Merges a set of permission differences for setting/updating permission entries.
*
* @param array|string $newPermissions Set of new permissions (ie, new effective value). May be serialized.
* @param array|string $existingPermissions Set of old permissions (ie, old effective value). May be serialized.
* @param string $allowValue If a permission is to be allowed, the name of the allow state (allow or content_allow).
*
* @return array New effective permissions, with non-matching old values returned to "unset" state
*/
public function getModeratorPermissionsForUpdate($newPermissions, $existingPermissions, $allowValue = 'allow')
{
$finalPermissions = array();
if (is_string($newPermissions))
{
$newPermissions = unserialize($newPermissions);
}
else if (!is_array($newPermissions))
{
$newPermissions = array();
}
foreach ($newPermissions AS $permissionGroupId => $permissionGroup)
{
foreach ($permissionGroup AS $permissionId => $value)
{
$finalPermissions[$permissionGroupId][$permissionId] = $allowValue;
}
}
if (is_string($existingPermissions))
{
$existingPermissions = unserialize($existingPermissions);
}
else if (!is_array($existingPermissions))
{
$existingPermissions = array();
}
foreach ($existingPermissions AS $permissionGroupId => $permissionGroup)
{
foreach ($permissionGroup AS $permissionId => $value)
{
if (!isset($finalPermissions[$permissionGroupId][$permissionId]))
{
$finalPermissions[$permissionGroupId][$permissionId] = 'unset';
}
}
}
return $finalPermissions;
}
/**
* Gets the permission interface group IDs that apply to all general moderators.
*
* @return array
*/
public function getGeneralModeratorInterfaceGroupIds()
{
return array('generalModeratorPermissions', 'profilePostModeratorPermissions', 'conversationModeratorPermissions');
}
/**
* Gets the permission interface group IDs that apply to the moderator in question.
* If a content moderator, only includes general and that content's groups;
* if a super moderator, includes all matching groups;
* otherwise, includes only the general groups.
*
* @param array $moderator
*
* @return array List of interface group IDs
*/
public function getModeratorInterfaceGroupIds(array $moderator)
{
$interfaceGroupIds = $this->getGeneralModeratorInterfaceGroupIds();
if (!empty($moderator['content_type']))
{
$handler = $this->getContentModeratorHandlers($moderator['content_type']);
$interfaceGroupIds = array_merge($interfaceGroupIds, $handler->getModeratorInterfaceGroupIds());
}
else if (!empty($moderator['is_super_moderator']))
{
foreach($this->getContentModeratorHandlers() AS $handler)
{
$interfaceGroupIds = array_merge($interfaceGroupIds, $handler->getModeratorInterfaceGroupIds());
}
}
return $interfaceGroupIds;
}
/**
* Gets all general moderator permissions.
*
* @return array Format: [group id][permission id] => permission info
*/
public function getGeneralModeratorPermissions()
{
return $this->getModeratorPermissions($this->getGeneralModeratorInterfaceGroupIds());
}
/**
* Gets moderator permissions from the specified interface groups.
*
* @param array $interfaceGroupIds
*
* @return array Format: [group id][permission id] => permission info
*/
public function getModeratorPermissions(array $interfaceGroupIds)
{
$permissions = $this->_getLocalCacheData('permissions');
if ($permissions === false)
{
$permissions = $this->_getPermissionModel()->getAllPermissions();
$this->setLocalCacheData('permissions', $permissions);
}
$validPermissions = array();
foreach ($permissions AS $permission)
{
if ($permission['permission_type'] != 'flag')
{
continue;
}
if (in_array($permission['interface_group_id'], $interfaceGroupIds))
{
$validPermissions[$permission['permission_group_id']][$permission['permission_id']] = $permission;
}
}
return $validPermissions;
}
/**
* Gets the necessary moderator permissions and interface groups for the UI,
*
* @param array $interfaceGroupIds List of interface groups to pull permissions from
* @param array $existingPermissions Existing permissions ([group id][permission id]), for selected values
*
* @return array List of interface groups, with "permissions" key (flat array)
*/
public function getModeratorPermissionsForInterface(array $interfaceGroupIds, array $existingPermissions = array())
{
$permissionModel = $this->_getPermissionModel();
$interfaceGroups = $permissionModel->getAllPermissionInterfaceGroups();
foreach ($interfaceGroups AS $interfaceGroupId => &$interfaceGroup)
{
if (!in_array($interfaceGroupId, $interfaceGroupIds))
{
unset($interfaceGroups[$interfaceGroupId]);
}
else
{
$interfaceGroup = $permissionModel->preparePermissionInterfaceGroup($interfaceGroup);
}
}
foreach ($this->getModeratorPermissions($interfaceGroupIds) AS $groupId => $group)
{
foreach ($group AS $permissionId => $permission)
{
if (isset($interfaceGroups[$permission['interface_group_id']]))
{
$permission = $permissionModel->preparePermission($permission);
$interfaceGroups[$permission['interface_group_id']]['permissions'][] = array(
'label' => $permission['title'],
'name' => "[$permission[permission_group_id]][$permission[permission_id]]",
'selected' => !empty($existingPermissions[$permission['permission_group_id']][$permission['permission_id']])
);
}
}
}
return $interfaceGroups;
}
/**
* Gets the list of possible extra user groups in "option" format.
*
* @param string|array $extraGroupIds List of existing extra group IDs; may be serialized.
*
* @return array List of user group options (keys: label, value, selected)
*/
public function getExtraUserGroupOptions($extraGroupIds)
{
return $this->getModelFromCache('XenForo_Model_UserGroup')->getUserGroupOptions(
$extraGroupIds
);
}
/**
* Gets all content moderator handler objects, or one for the specified content type.
*
* @param string|array|null $limitContentType If specified, gets handler for specified type(s) only
*
* @return XenForo_ModeratorHandler_Abstract|array|false
*/
public function getContentModeratorHandlers($limitContentType = null)
{
$contentTypes = $this->_getLocalCacheData('moderatorHandlerPairs');
if ($contentTypes === false)
{
$contentTypes = $this->getContentTypesWithField('moderator_handler_class');
$this->setLocalCacheData('moderatorHandlerPairs', $contentTypes);
}
if (is_string($limitContentType))
{
if (isset($contentTypes[$limitContentType]))
{
$class = $contentTypes[$limitContentType];
if (!class_exists($class))
{
return false;
}
$class = XenForo_Application::resolveDynamicClass($class);
return new $class();
}
else
{
return false;
}
}
else if (is_array($limitContentType))
{
$handlers = array();
foreach ($contentTypes AS $contentType => $handlerClass)
{
if (in_array($contentType, $limitContentType))
{
if (!class_exists($handlerClass))
{
continue;
}
$handlerClass = XenForo_Application::resolveDynamicClass($handlerClass);
$handlers[$contentType] = new $handlerClass();
}
}
}
else
{
$handlers = array();
foreach ($contentTypes AS $contentType => $handlerClass)
{
if (!class_exists($handlerClass))
{
continue;
}
$handlerClass = XenForo_Application::resolveDynamicClass($handlerClass);
$handlers[$contentType] = new $handlerClass();
}
}
return $handlers;
}
/**
* Goes through a list of content moderators and fetches the content titles for all of them.
* Items that are not returned by the handler will not have a "title" key.
*
* @param array $moderators
*
* @return array Moderators with "title" key where given
*/
public function addContentTitlesToModerators(array $moderators)
{
$types = array();
foreach ($moderators AS $key => $moderator)
{
if (!$moderator['content_type'])
{
continue;
}
$types[$moderator['content_type']][$key] = $moderator['content_id'];
}
if ($types)
{
$handlers = $this->getContentModeratorHandlers(array_keys($types));
foreach ($handlers AS $contentType => $handler)
{
$titles = $handler->getContentTitles($types[$contentType]);
foreach ($titles AS $key => $title)
{
$moderators[$key]['title'] = $title;
}
}
}
return $moderators;
}
/**
* Fetches an array containing $value for the value of each permission.
* Useful for automatically populating super moderator records with a full permission set.
*
* @param mixed Value for every permission
*
* @return array $permissionSet[$groupId][$permId] = $value;
*/
public function getFullPermissionSet($value = true)
{
$permissionSet = array();
foreach ($this->getModeratorPermissions($this->getModeratorInterfaceGroupIds(array('is_super_moderator' => true))) AS $groupId => $group)
{
foreach ($group AS $permId => $perm)
{
$permissionSet[$groupId][$permId] = $value;
}
}
return $permissionSet;
}
/**
* Returns the total number of members who are moderators
* Note: distinct on user_id
*
* @return integer
*/
public function countModerators()
{
return $this->_getDb()->fetchOne('SELECT COUNT(*) FROM xf_moderator');
}
/**
* @return XenForo_Model_Permission
*/
protected function _getPermissionModel()
{
return $this->getModelFromCache('XenForo_Model_Permission');
}
}