Файл: library/XenForo/Model/ProfilePost.php
Строк: 1401
<?php
/**
* Model for profile post related functions.
*
* @package XenForo_ProfilePost
*/
class XenForo_Model_ProfilePost extends XenForo_Model
{
/**
* Constants to allow joins to extra tables in certain queries
*
* @var integer Join user table (poster)
* @var integer Join user table (receiver)
* @var integer Join user privacy table (receiver)
* @var integer Join deletion log
*/
const FETCH_USER_POSTER = 0x01;
const FETCH_USER_RECEIVER = 0x02;
const FETCH_USER_RECEIVER_PRIVACY = 0x04;
const FETCH_DELETION_LOG = 0x08;
/**
* Gets the specified profile post.
*
* @param integer $id
* @param array $fetchOptions
*
* @return array|false
*/
public function getProfilePostById($id, array $fetchOptions = array())
{
$sqlClauses = $this->prepareProfilePostFetchOptions($fetchOptions);
return $this->_getDb()->fetchRow('
SELECT profile_post.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post AS profile_post
' . $sqlClauses['joinTables'] . '
WHERE profile_post.profile_post_id = ?
', $id);
}
/**
* Gets profile posts for the specified user that meet the given conditions.
*
* @param integer $userId
* @param array $conditions
* @param array $fetchOptions
*
* @return array [profile post id] => info
*/
public function getProfilePostsForUserId($userId, array $conditions = array(), array $fetchOptions = array())
{
$conditions['user_id'] = $userId;
$whereClause = $this->prepareProfilePostConditions($conditions, $fetchOptions);
$sqlClauses = $this->prepareProfilePostFetchOptions($fetchOptions);
$limitOptions = $this->prepareLimitFetchOptions($fetchOptions);
return $this->fetchAllKeyed($this->limitQueryResults(
'
SELECT profile_post.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post AS profile_post
' . $sqlClauses['joinTables'] . '
WHERE ' . $whereClause . '
ORDER BY profile_post.post_date DESC
', $limitOptions['limit'], $limitOptions['offset']
), 'profile_post_id');
}
/**
* Counts the profile posts that were left for the specified user (with the given conditions).
*
* @param integer $userId
* @param array $conditions
*
* @return integer
*/
public function countProfilePostsForUserId($userId, array $conditions = array())
{
$fetchOptions = array();
$conditions['user_id'] = $userId;
$whereClause = $this->prepareProfilePostConditions($conditions, $fetchOptions);
$sqlClauses = $this->prepareProfilePostFetchOptions($fetchOptions);
return $this->_getDb()->fetchOne('
SELECT COUNT(*)
FROM xf_profile_post AS profile_post
' . $sqlClauses['joinTables'] . '
WHERE ' . $whereClause
);
}
/**
* Gets the specified profile posts.
*
* @param array $messageIds
* @param array $fetchOptions
*
* @return array [profile post id] => info
*/
public function getProfilePostsByIds(array $messageIds, array $fetchOptions = array())
{
if (!$messageIds)
{
return array();
}
$sqlClauses = $this->prepareProfilePostFetchOptions($fetchOptions);
return $this->fetchAllKeyed('
SELECT profile_post.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post AS profile_post
' . $sqlClauses['joinTables'] . '
WHERE profile_post.profile_post_id IN(' . $this->_getDb()->quote($messageIds) . ')
', 'profile_post_id');
}
/**
* Fetches all profile posts posted by the specified user, on their own and others' profile pages.
*
* @param integer $userId
* @param array $fetchOptions
*
* @return array
*/
public function getProfilePostsByUserId($userId, array $fetchOptions = array())
{
$sqlClauses = $this->prepareProfilePostFetchOptions($fetchOptions);
return $this->fetchAllKeyed('
SELECT profile_post.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post AS profile_post
' . $sqlClauses['joinTables'] . '
WHERE profile_post.user_id = ?
', 'profile_post_id', $userId);
}
/**
* Gets profile post IDs in the specified range. The IDs returned will be those immediately
* after the "start" value (not including the start), up to the specified limit.
*
* @param integer $start IDs greater than this will be returned
* @param integer $limit Number of posts to return
*
* @return array List of IDs
*/
public function getProfilePostIdsInRange($start, $limit)
{
$db = $this->_getDb();
return $db->fetchCol($db->limit('
SELECT profile_post_id
FROM xf_profile_post
WHERE profile_post_id > ?
ORDER BY profile_post_id
', $limit), $start);
}
/**
* Prepares a collection of profile post fetching related conditions into an SQL clause
*
* @param array $conditions List of conditions
* @param array $fetchOptions Modifiable set of fetch options (may have joins pushed on to it)
*
* @return string SQL clause (at least 1=1)
*/
public function prepareProfilePostConditions(array $conditions, array &$fetchOptions)
{
$sqlConditions = array();
$db = $this->_getDb();
if (!empty($conditions['user_id']))
{
$sqlConditions[] = "profile_post.profile_user_id = " . $db->quote($conditions['user_id']);
}
if (!empty($conditions['post_date']) && is_array($conditions['post_date']))
{
list($operator, $cutOff) = $conditions['post_date'];
$this->assertValidCutOffOperator($operator);
$sqlConditions[] = "profile_post.post_date $operator " . $db->quote($cutOff);
}
if (isset($conditions['deleted']) || isset($conditions['moderated']))
{
$sqlConditions[] = $this->prepareStateLimitFromConditions($conditions, 'profile_post', 'message_state');
}
return $this->getConditionsForClause($sqlConditions);
}
/**
* Checks the 'join' key of the incoming array for the presence of the FETCH_x bitfields in this class
* and returns SQL snippets to join the specified tables if required
*
* @param array $fetchOptions containing a 'join' integer key build from this class's FETCH_x bitfields
*
* @return array Containing 'selectFields' and 'joinTables' keys. Example: selectFields = ', user.*, foo.title'; joinTables = ' INNER JOIN foo ON (foo.id = other.id) '
*/
public function prepareProfilePostFetchOptions(array $fetchOptions)
{
$selectFields = '';
$joinTables = '';
$db = $this->_getDb();
if (!empty($fetchOptions['join']))
{
if ($fetchOptions['join'] & self::FETCH_USER_POSTER)
{
$selectFields .= ',
posting_user.*,
IF(posting_user.username IS NULL, profile_post.username, posting_user.username) AS username';
$joinTables .= '
LEFT JOIN xf_user AS posting_user ON
(posting_user.user_id = profile_post.user_id)';
}
if ($fetchOptions['join'] & self::FETCH_USER_RECEIVER)
{
$selectFields .= ',
receiving_user.username
AS profile_username,
receiving_user.gender
AS profile_gender,
receiving_user.user_state
AS profile_user_state,
receiving_user.is_banned
AS profile_is_banned,
receiving_user.is_admin
AS profile_is_admin,
receiving_user.is_moderator
AS profile_is_moderator,
receiving_user.avatar_date
AS profile_avatar_date,
receiving_user.gravatar
AS profile_gravatar,
receiving_user.warning_points
AS profile_warning_points,
receiving_user.permission_combination_id
AS profile_permission_combination_id';
$joinTables .= '
LEFT JOIN xf_user AS receiving_user ON
(receiving_user.user_id = profile_post.profile_user_id)';
}
if ($fetchOptions['join'] & self::FETCH_USER_RECEIVER_PRIVACY)
{
$visitingUser = (isset($fetchOptions['visitingUser']) ? $fetchOptions['visitingUser'] : XenForo_Visitor::getInstance());
$selectFields .= ',
receiving_user_privacy.allow_view_profile
AS profile_allow_view_profile,
receiving_user_privacy.allow_post_profile
AS profile_allow_post_profile,
receiving_user_privacy.allow_send_personal_conversation
AS profile_allow_send_personal_conversation,
receiving_user_privacy.allow_view_identities
AS profile_allow_view_identities,
receiving_user_privacy.allow_receive_news_feed
AS profile_allow_allow_receive_news_feed,
IF (receiving_user_follow.follow_user_id, 1, 0)
AS following_' . intval($visitingUser->getUserId());
$joinTables .= '
LEFT JOIN xf_user_privacy AS receiving_user_privacy ON
(receiving_user_privacy.user_id = profile_post.profile_user_id)
LEFT JOIN xf_user_follow AS receiving_user_follow ON
(receiving_user_follow.user_id = profile_post.profile_user_id AND follow_user_id = ' . $db->quote($visitingUser->getUserId()) . ')';
}
if ($fetchOptions['join'] & self::FETCH_DELETION_LOG)
{
$selectFields .= ',
deletion_log.delete_date, deletion_log.delete_reason,
deletion_log.delete_user_id, deletion_log.delete_username';
$joinTables .= '
LEFT JOIN xf_deletion_log AS deletion_log ON
(deletion_log.content_type = 'profile_post' AND deletion_log.content_id = profile_post.profile_post_id)';
}
}
if (isset($fetchOptions['likeUserId']))
{
if (empty($fetchOptions['likeUserId']))
{
$selectFields .= ',
0 AS like_date';
}
else
{
$selectFields .= ',
liked_content.like_date';
$joinTables .= '
LEFT JOIN xf_liked_content AS liked_content
ON (liked_content.content_type = 'profile_post'
AND liked_content.content_id = profile_post.profile_post_id
AND liked_content.like_user_id = ' .$db->quote($fetchOptions['likeUserId']) . ')';
}
}
return array(
'selectFields' => $selectFields,
'joinTables' => $joinTables
);
}
/**
* Prepares a profile post.
*
* @param array $profilePost
* @param array $user User whose profile the post is on
* @param array|null $viewingUser Viewing user reference
*
* @return array
*/
public function prepareProfilePost(array $profilePost, array $user, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
$profilePost['canDelete'] = $this->canDeleteProfilePost($profilePost, $user, 'soft', $null, $viewingUser);
$profilePost['canEdit'] = $this->canEditProfilePost($profilePost, $user, $null, $viewingUser);
$profilePost['canLike'] = $this->canLikeProfilePost($profilePost, $user, $null, $viewingUser);
$profilePost['canComment'] = $this->canCommentOnProfilePost($profilePost, $user, $null, $viewingUser);
$profilePost['canReport'] = $this->canReportProfilePost($profilePost, $user, $null, $viewingUser);
$profilePost['canWarn'] = $this->canWarnProfilePost($profilePost, $user, $null, $viewingUser);
$profilePost['isDeleted'] = ($profilePost['message_state'] == 'deleted');
$profilePost['isModerated'] = ($profilePost['message_state'] == 'moderated');
$profilePost['canCleanSpam'] = (
$profilePost['canDelete']
&& $user['user_id']
&& XenForo_Permission::hasPermission($viewingUser['permissions'], 'general', 'cleanSpam')
&& $this->_getUserModel()->couldBeSpammer($profilePost)
);
if (!empty($profilePost['delete_date']))
{
$profilePost['deleteInfo'] = array(
'user_id' => $profilePost['delete_user_id'],
'username' => $profilePost['delete_username'],
'date' => $profilePost['delete_date'],
'reason' => $profilePost['delete_reason'],
);
}
if (!empty($profilePost['profile_username']))
{
$profilePost['profileUser'] = $this->getProfileUserFromProfilePost($profilePost);
}
if ($profilePost['likes'])
{
$profilePost['likeUsers'] = unserialize($profilePost['like_users']);
}
if (array_key_exists('user_group_id', $profilePost))
{
$profilePost = $this->getModelFromCache('XenForo_Model_User')->prepareUser($profilePost);
}
return $profilePost;
}
/**
* Prepares a batch of profile posts.
*
* @param array $profilePosts
* @param array $user User whose profile the post is on
* @param array|null $viewingUser Viewing user reference
*
* @return array
*/
public function prepareProfilePosts(array $profilePosts, array $user, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
foreach ($profilePosts AS &$profilePost)
{
$profilePost = $this->prepareProfilePost($profilePost, $user, $viewingUser);
}
return $profilePosts;
}
/**
* Extracts the data relating to a profile owner user from a profile post,
* that has been fetched with XenForo_Model_ProfilePost::FETCH_USER_RECEIVER
*
* @param array $profilePost
*
* @return array
*/
public function getProfileUserFromProfilePost(array $profilePost, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
$user = array();
$followingKey = 'following_' . $viewingUser['user_id'];
if (isset($profilePost[$followingKey]))
{
$user[$followingKey] = $profilePost[$followingKey];
}
foreach ($profilePost AS $key => $val)
{
if (preg_match('/^profile_(.+)$/', $key, $match))
{
$user[$match[1]] = $val;
}
}
return $user;
}
/**
* Determines if the given profile post can be viewed. This does not
* check user profile viewing permissions.
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canViewProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'view'))
{
return false;
}
if ($profilePost['message_state'] == 'moderated'
&& !XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'viewModerated')
)
{
if (!$viewingUser['user_id'] || $viewingUser['user_id'] != $profilePost['user_id'])
{
return false;
}
}
else if ($profilePost['message_state'] == 'deleted'
&& !XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'viewDeleted')
)
{
return false;
}
return $this->_getUserProfileModel()->canViewProfilePosts($user, $errorPhraseKey, $viewingUser);
}
/**
* Determines if the given profile post can be viewed. This checks parent permissions.
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canViewProfilePostAndContainer(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!$this->_getUserProfileModel()->canViewFullUserProfile($user, $errorPhraseKey, $viewingUser))
{
return false;
}
return $this->canViewProfilePost($profilePost, $user, $errorPhraseKey, $viewingUser);
}
/**
* Determines if the given profile post can be edited. This does not
* check parent (viewing) permissions.
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canEditProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!$viewingUser['user_id'])
{
return false;
}
if ($viewingUser['user_id'] == $profilePost['user_id'])
{
return XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'editOwn');
}
else
{
return XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'editAny');
}
}
/**
* Determines if the given profile post can be deleted. This does not
* check parent (viewing) permissions.
*
* @param array $profilePost
* @param array $user
* @param string $deleteType Type of deletion (soft or hard)
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canDeleteProfilePost(array $profilePost, array $user, $deleteType = 'soft', &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!$viewingUser['user_id'])
{
return false;
}
if ($deleteType != 'soft' && !XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'hardDeleteAny'))
{
return false;
}
if (XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'deleteAny'))
{
return true;
}
if ($viewingUser['user_id'] == $profilePost['user_id'])
{
return XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'deleteOwn');
}
else if ($viewingUser['user_id'] == $profilePost['profile_user_id'])
{
return XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'manageOwn');
}
else
{
return false;
}
}
/**
* Determines if the given profile post can be undeleted. This does not
* check parent (viewing) permissions.
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canUndeleteProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
return ($viewingUser['user_id'] && XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'undelete'));
}
/**
* Determines if the given profile post can be approved/unapproved. This does not
* check parent (viewing) permissions.
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canApproveUnapproveProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
return ($viewingUser['user_id'] && XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'approveUnapprove'));
}
/**
* Determines if the given profile post can be warned. This does not
* check parent (viewing) permissions.
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canWarnProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
if ($profilePost['warning_id'] || empty($profilePost['user_id']))
{
return false;
}
if (!empty($profilePost['is_admin']) || !empty($profilePost['is_moderator']))
{
return false;
}
$this->standardizeViewingUserReference($viewingUser);
return ($viewingUser['user_id'] && XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'warn'));
}
/**
* Determines if the profile post can be liked with the given permissions.
* This does not check profile post viewing permissions.
*
* @param array $profilePost Profile post info
* @param array $user User info for where profile post is posted
* @param string $errorPhraseKey Returned phrase key for a specific error
* @param array|null $viewingUser
*
* @return boolean
*/
public function canLikeProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!$viewingUser['user_id'])
{
return false;
}
if ($profilePost['message_state'] != 'visible')
{
return false;
}
if ($profilePost['user_id'] == $viewingUser['user_id'])
{
$errorPhraseKey = 'liking_own_content_cheating';
return false;
}
return XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'like');
}
/**
* Determines if the given profile post can be commented on. This does not
* check parent (viewing) permissions.
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canCommentOnProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!$viewingUser['user_id'])
{
return false;
}
if ($profilePost['message_state'] != 'visible')
{
return false;
}
return (
XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'view')
&& XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'comment')
&& $this->_getUserModel()->passesPrivacyCheck($user['allow_post_profile'], $user, $viewingUser)
);
}
/**
* Determines if the viewing user can view the IP of the stated profile post
*
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canViewIps(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
return $this->getModelFromCache('XenForo_Model_User')->canViewIps($errorPhraseKey, $viewingUser);
}
/**
* Checks that the viewing user may report the specified profile post
*
* @param array $profilePost
* @param array $user
* @param string
* @param boolean $errorPhraseKey
* @param array|null $viewingUser
*
* @return boolean
*/
public function canReportProfilePost(array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
return $this->getModelFromCache('XenForo_Model_User')->canReportContent($errorPhraseKey, $viewingUser);
}
/**
* Adds the inline mod option to a profile post.
*
* @param array $profilePost Profile post. By reference; canInlineMod key added
* @param array $user
* @param array|null $viewingUser
*
* @return array List of inline mod options the user can do
*/
public function addInlineModOptionToProfilePost(array &$profilePost, array $user, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
$options = array();
$canInlineMod = ($viewingUser['user_id'] && (
XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'deleteAny')
|| XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'undelete')
|| XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'approveUnapprove')
));
if ($canInlineMod)
{
if ($this->canDeleteProfilePost($profilePost, $user, 'soft', $null, $viewingUser))
{
$options['delete'] = true;
}
if ($this->canUndeleteProfilePost($profilePost, $user, $null, $viewingUser))
{
$options['undelete'] = true;
}
if ($this->canApproveUnapproveProfilePost($profilePost, $user, $null, $viewingUser))
{
$options['approve'] = true;
$options['unapprove'] = true;
}
}
$profilePost['canInlineMod'] = (count($options) > 0);
return $options;
}
/**
* Adds the inline mod option to a batch of profile posts.
*
* @param array $profilePosts Batch of profile posts. By reference; all modified to add canInlineMod key
* @param array $user
* @param array|null $viewingUser
*
* @return array List of inline mod options the user can do on at least one post
*/
public function addInlineModOptionToProfilePosts(array &$profilePosts, array $user, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
$options = array();
foreach ($profilePosts AS &$profilePost)
{
$options += $this->addInlineModOptionToProfilePost($profilePost, $user, $viewingUser);
}
return $options;
}
/**
* Gets permission-based conditions that apply to profile post fetching functions.
*
* @param array $user User the profile posts will belong to
* @param array|null $viewingUser Viewing user ref; defaults to visitor
*
* @return array Keys: deleted (boolean), moderated (boolean, integer if can only view specific user ID)
*/
public function getPermissionBasedProfilePostConditions(array $user, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'viewModerated'))
{
$viewModerated = true;
}
else if ($viewingUser['user_id'])
{
$viewModerated = $viewingUser['user_id'];
}
else
{
$viewModerated = false;
}
return array(
'deleted' => XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'viewDeleted'),
'moderated' => $viewModerated
);
}
/**
* Gets the message state for a newly inserted profile post by the viewing user.
*
* @param array $user User whose profile is being posted on
* @param array|null $viewingUser
*
* @return string Message state (visible, moderated, deleted)
*/
public function getProfilePostInsertMessageState(array $user, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if ($viewingUser['user_id'] && XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'approveUnapprove'))
{
return 'visible';
}
else if (XenForo_Permission::hasPermission($viewingUser['permissions'], 'general', 'followModerationRules'))
{
return 'visible'; // TODO: follow profile-level settings when they exist
}
else
{
return 'moderated';
}
}
/**
* Constant for fetching the info about the comment user.
*
* @var integer
*/
const FETCH_COMMENT_USER = 0x01;
/**
* Prepares the fetching options for profile post comments.
*
* @param array $fetchOptions
*
* @return array
*/
public function prepareProfilePostCommentFetchOptions(array $fetchOptions)
{
$selectFields = '';
$joinTables = '';
if (!empty($fetchOptions['join']))
{
if ($fetchOptions['join'] & self::FETCH_COMMENT_USER)
{
$selectFields .= ',
user.*,
IF(user.username IS NULL, profile_post_comment.username, user.username) AS username';
$joinTables .= '
LEFT JOIN xf_user AS user ON
(user.user_id = profile_post_comment.user_id)';
}
}
return array(
'selectFields' => $selectFields,
'joinTables' => $joinTables
);
}
/**
* Gets the specified profile post comment.
*
* @param integer $profilePostCommentId
* @param array $fetchOptions
*
* @return array|false
*/
public function getProfilePostCommentById($profilePostCommentId, array $fetchOptions = array())
{
$sqlClauses = $this->prepareProfilePostCommentFetchOptions($fetchOptions);
return $this->_getDb()->fetchRow('
SELECT profile_post_comment.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post_comment AS profile_post_comment
' . $sqlClauses['joinTables'] . '
WHERE profile_post_comment.profile_post_comment_id = ?
', $profilePostCommentId);
}
/**
* Gets the profile post comments with the specified IDs.
*
* @param array $ids
* @param array $fetchOptions
*
* @return array [id] => info
*/
public function getProfilePostCommentsByIds(array $ids, array $fetchOptions = array())
{
if (!$ids)
{
return array();
}
$sqlClauses = $this->prepareProfilePostCommentFetchOptions($fetchOptions);
return $this->fetchAllKeyed('
SELECT profile_post_comment.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post_comment AS profile_post_comment
' . $sqlClauses['joinTables'] . '
WHERE profile_post_comment.profile_post_comment_id IN (' . $this->_getDb()->quote($ids) . ')
', 'profile_post_comment_id');
}
/**
* Gets the profile post comments make by a particular user.
*
* @param array $ids
* @param array $fetchOptions
*
* @return array [id] => info
*/
public function getProfilePostCommentsByUserId($userId, array $fetchOptions = array())
{
$sqlClauses = $this->prepareProfilePostCommentFetchOptions($fetchOptions);
return $this->fetchAllKeyed('
SELECT profile_post_comment.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post_comment AS profile_post_comment
' . $sqlClauses['joinTables'] . '
WHERE profile_post_comment.user_id = ?
', 'profile_post_comment_id', $userId);
}
/**
* Gets all comments that belong to the specified post. If a limit is specified,
* more recent comments are returned.
*
* @param integer $profilePostId
* @param integer $beforeDate If specified, gets posts before specified date only
* @param array $fetchOptions
*
* @return array [id] => info
*/
public function getProfilePostCommentsByProfilePost($profilePostId, $beforeDate = 0, array $fetchOptions = array())
{
$sqlClauses = $this->prepareProfilePostCommentFetchOptions($fetchOptions);
$limitOptions = $this->prepareLimitFetchOptions($fetchOptions);
if ($beforeDate)
{
$beforeCondition = 'AND profile_post_comment.comment_date < ' . $this->_getDb()->quote($beforeDate);
}
else
{
$beforeCondition = '';
}
$results = $this->fetchAllKeyed($this->limitQueryResults(
'
SELECT profile_post_comment.*
' . $sqlClauses['selectFields'] . '
FROM xf_profile_post_comment AS profile_post_comment
' . $sqlClauses['joinTables'] . '
WHERE profile_post_comment.profile_post_id = ?
' . $beforeCondition . '
ORDER BY profile_post_comment.comment_date DESC
', $limitOptions['limit'], $limitOptions['offset']
), 'profile_post_comment_id', $profilePostId);
return array_reverse($results, true);
}
/**
* Merges comments into existing profile post data.
*
* @param array $profilePosts
* @param array $fetchOptions
*
* @return array Posts with comments merged
*/
public function addProfilePostCommentsToProfilePosts(array $profilePosts, array $fetchOptions = array())
{
$commentIdMap = array();
foreach ($profilePosts AS &$profilePost)
{
if ($profilePost['latest_comment_ids'])
{
foreach (explode(',', $profilePost['latest_comment_ids']) AS $commentId)
{
$commentIdMap[intval($commentId)] = $profilePost['profile_post_id'];
}
}
$profilePost['comments'] = array();
}
if ($commentIdMap)
{
$comments = $this->getProfilePostCommentsByIds(array_keys($commentIdMap), $fetchOptions);
foreach ($commentIdMap AS $commentId => $profilePostId)
{
if (isset($comments[$commentId]))
{
if (!isset($profilePosts[$profilePostId]['first_shown_comment_date']))
{
$profilePosts[$profilePostId]['first_shown_comment_date'] = $comments[$commentId]['comment_date'];
}
$profilePosts[$profilePostId]['comments'][$commentId] = $comments[$commentId];
}
}
}
return $profilePosts;
}
/**
* Gets the user IDs that have commented on a profile post.
*
* @param integer $profilePostId
*
* @return array
*/
public function getProfilePostCommentUserIds($profilePostId)
{
return $this->_getDb()->fetchCol('
SELECT DISTINCT user_id
FROM xf_profile_post_comment
WHERE profile_post_id = ?
', $profilePostId);
}
/**
* Determines if the given profile post comment can be deleted. This does not
* check parent (viewing) permissions.
*
* @param array $comment
* @param array $profilePost
* @param array $user
* @param string $errorPhraseKey By ref. More specific error, if available.
* @param array|null $viewingUser Viewing user reference
*
* @return boolean
*/
public function canDeleteProfilePostComment(array $comment, array $profilePost, array $user, &$errorPhraseKey = '', array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!$viewingUser['user_id'])
{
return false;
}
if (XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'deleteAny'))
{
return true;
}
if ($viewingUser['user_id'] == $comment['user_id'])
{
return XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'deleteOwn');
}
else if ($viewingUser['user_id'] == $profilePost['profile_user_id'])
{
return XenForo_Permission::hasPermission($viewingUser['permissions'], 'profilePost', 'manageOwn');
}
else
{
return false;
}
}
/**
* Prepares a profile post comment for display.
*
* @param array $comment
* @param array $profilePost
* @param array $user
* @param array|null $viewingUser
*
* @return array
*/
public function prepareProfilePostComment(array $comment, array $profilePost, array $user, array $viewingUser = null)
{
$comment['canDelete'] = $this->canDeleteProfilePostComment($comment, $profilePost, $user, $null, $viewingUser);
if (array_key_exists('user_group_id', $comment))
{
$comment = $this->getModelFromCache('XenForo_Model_User')->prepareUser($comment);
}
return $comment;
}
/**
* Fetch view parameters for profile posts, primarily for meta controls like warn, view IPs etc.
*
* @param array $profilePosts
* @param array $user (owner of the profile on which the profile posts are shown)
* @param array $viewingUser
*
* @return array
*/
public function getProfilePostViewParams(array $profilePosts, array $user, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
$userModel = $this->_getUserModel();
return array(
'profilePosts' => $profilePosts,
'canViewIps' => $userModel->canViewIps(),
'canViewWarnings' => $userModel->canViewWarnings(),
'canWarn' => $userModel->canWarnUser($user),
);
}
/**
* Attempts to update any instances of an old username in like_users with a new username
*
* @param integer $oldUserId
* @param integer $newUserId
* @param string $oldUsername
* @param string $newUsername
*/
public function batchUpdateLikeUser($oldUserId, $newUserId, $oldUsername, $newUsername)
{
$db = $this->_getDb();
// note that xf_liked_content should have already been updated with $newUserId
$db->query('
UPDATE (
SELECT content_id FROM xf_liked_content
WHERE content_type = 'profile_post'
AND like_user_id = ?
) AS temp
INNER JOIN xf_profile_post AS profile_post ON (profile_post.profile_post_id = temp.content_id)
SET like_users = REPLACE(like_users, ' .
$db->quote('i:' . $oldUserId . ';s:8:"username";s:' . strlen($oldUsername) . ':"' . $oldUsername . '";') . ', ' .
$db->quote('i:' . $newUserId . ';s:8:"username";s:' . strlen($newUsername) . ':"' . $newUsername . '";') . ')
', $newUserId);
}
public function alertTaggedMembers(
array $profilePost, array $profileUser, array $tagged, array $alreadyAlerted = array(),
$isComment = false
)
{
$userIds = XenForo_Application::arrayColumn($tagged, 'user_id');
$userIds = array_diff($userIds, $alreadyAlerted);
$alertedUserIds = array();
if ($userIds)
{
$userModel = $this->_getUserModel();
$users = $userModel->getUsersByIds($userIds, array(
'join' => XenForo_Model_User::FETCH_USER_OPTION
| XenForo_Model_User::FETCH_USER_PROFILE
| XenForo_Model_User::FETCH_USER_PERMISSIONS
));
foreach ($users AS $user)
{
if (isset($alertedUserIds[$user['user_id']])
|| $user['user_id'] == $profilePost['user_id']
|| $user['user_id'] == $profileUser['user_id']
)
{
continue;
}
$user['permissions'] = XenForo_Permission::unserializePermissions($user['global_permission_cache']);
if (!$userModel->isUserIgnored($user, $profilePost['user_id'])
&& !$userModel->isUserIgnored($user, $profileUser['user_id'])
&& XenForo_Model_Alert::userReceivesAlert($user, 'profile_post', 'tag')
&& $this->canViewProfilePostAndContainer($profilePost, $profileUser, $null, $user)
)
{
$alertedUserIds[$user['user_id']] = true;
XenForo_Model_Alert::alert($user['user_id'],
$profilePost['user_id'], $profilePost['username'],
'profile_post', $profilePost['profile_post_id'],
$isComment ? 'tag_comment' : 'tag'
);
}
}
}
return array_keys($alertedUserIds);
}
/**
* @return XenForo_Model_User
*/
protected function _getUserModel()
{
return $this->getModelFromCache('XenForo_Model_User');
}
/**
* @return XenForo_Model_UserProfile
*/
protected function _getUserProfileModel()
{
return $this->getModelFromCache('XenForo_Model_UserProfile');
}
}