Вход Регистрация
Файл: library/XenForo/Model/InlineMod/Thread.php
Строк: 1295
<?php

/**
 * Model to handle inline mod-style actions on threads. Generally, these are simply
 * bulk actions. They can be applied to other circumstances if desired.
 *
 * @package XenForo_Thread
 */
class XenForo_Model_InlineMod_Thread extends XenForo_Model
{
    public 
$enableLogging true;

    
/**
     * Determines if the selected thread IDs can be generally edited (titles, prefixes etc.)
     *
     * @param array $threadIds List of thread IDs check
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canEditThreads(array $threadIds, &$errorKey ''$viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canEditThreadsData($threads$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be generally edited (titles, prefixes etc.)
     *
     * @param array $threads List of information about threads to be checked
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canEditThreadsData(array $threads, array $forums, &$errorKey ''$viewingUser null)
    {
        return 
$this->_checkPermissionOnThreads('canEditThread'$threads$forums$errorKey$viewingUser);
    }

    
/**
     * Apply a thread prefix to the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to change
     * @param integer $prefixId ID of the thread prefix to apply
     * @param array $unchangedThreadIds Array of thread IDs that were not updated by this action
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function applyThreadPrefix(array $threadIds$prefixId, &$unchangedThreadIds = array(), array $options = array(), &$errorKey '', array $viewingUser null)
    {
        
$prefixModel $this->_getPrefixModel();

        
$prefixPerms = array();

        if (!
$this->canEditThreads($threadIds$errorKey$viewingUser))
        {
            return 
false;
        }

        foreach (
$threadIds AS $threadId)
        {
            
$dw XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'XenForo_DataWriter::ERROR_SILENT);
            if (!
$dw->setExistingData($threadId))
            {
                continue;
            }

            
$thread $dw->getMergedData();

            
$nodeId $dw->get('node_id');
            if (!isset(
$prefixPerms[$nodeId]))
            {
                
$prefixPerms[$nodeId] = $prefixModel->verifyPrefixIsUsable($prefixId$nodeId$viewingUser);
            }

            if (!
$prefixPerms[$nodeId])
            {
                
$unchangedThreadIds[] = $threadId;
                continue;
            }

            
$dw->set('prefix_id'$prefixId);
            
$dw->save();

            if (
$thread['prefix_id'] != $prefixId)
            {
                if (
$thread['prefix_id'])
                {
                    
$phrase = new XenForo_Phrase('thread_prefix_' $thread['prefix_id']);
                    
$oldValue $phrase->render();
                }
                else
                {
                    
$oldValue '-';
                }

                
XenForo_Model_Log::logModeratorAction('thread'$thread'prefix', array('old' => $oldValue));
            }
        }

        return 
true;
    }

    
/**
     * Determines if the selected thread IDs can be deleted.
     *
     * @param array $threadIds List of thread IDs check
     * @param string $deleteType The type of deletion being requested (soft or hard)
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canDeleteThreads(array $threadIds$deleteType 'soft', &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canDeleteThreadsData($threads$deleteType$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be deleted. This is a slightly more
     * "internal" version of the canDeleteThreads() function, as the required data
     * must already be retrieved.
     *
     * @param array $threads List of information about threads to be checked
     * @param string $deleteType Type of deletion (soft or hard)
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canDeleteThreadsData(array $threads$deleteType, array $forums, &$errorKey '', array $viewingUser null)
    {
        
// note: this cannot use _checkPermissionOnThreads because of extra param

        
if (!$threads)
        {
            return 
true;
        }

        
$this->standardizeViewingUserReference($viewingUser);

        
$threadModel $this->_getThreadModel();

        foreach (
$threads AS $thread)
        {
            
$forum $this->_getForumFromThread($thread$forums);

            if (!
$threadModel->canViewThreadAndContainer($thread$forum$null$forum['nodePermissions'], $viewingUser))
            {
                return 
false;
            }

            if (!
$threadModel->canDeleteThread($thread$forum$deleteType$errorKey$forum['nodePermissions'], $viewingUser))
            {
                return 
false;
            }
        }

        return 
true;
    }

    
/**
     * Deletes the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to delete
     * @param array $options Options that control the delete. Supports deleteType (soft or hard).
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function deleteThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        
$options array_merge(
            array(
                
'deleteType' => '',
                
'reason' => ''
            
), $options
        
);

        if (!
$options['deleteType'])
        {
            throw new 
XenForo_Exception('No deletion type specified.');
        }

        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canDeleteThreadsData($threads$options['deleteType'], $forums$errorKey$viewingUser))
        {
            return 
false;
        }

        foreach (
$threads AS $thread)
        {
            
$dw XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'XenForo_DataWriter::ERROR_SILENT);
            if (!
$dw->setExistingData($thread))
            {
                continue;
            }

            if (
array_key_exists($dw->get('node_id'), $forums))
            {
                
$dw->setExtraData(XenForo_DataWriter_Discussion_Thread::DATA_FORUM$forums[$dw->get('node_id')]);
            }

            if (
$options['deleteType'] == 'hard')
            {
                
$dw->delete();

                if (
$this->enableLogging)
                {
                    
XenForo_Model_Log::logModeratorAction('thread'$thread'delete_hard');
                }
            }
            else
            {
                
$dw->setExtraData(XenForo_DataWriter_Discussion::DATA_DELETE_REASON$options['reason']);
                
$dw->set('discussion_state''deleted');
                
$dw->save();

                if (
$this->enableLogging)
                {
                    
XenForo_Model_Log::logModeratorAction('thread'$thread'delete_soft', array('reason' => $options['reason']));
                }
            }
        }

        return 
true;
    }

    
/**
     * Determines if the selected thread IDs can be undeleted.
     *
     * @param array $threadIds List of thread IDs check
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canUndeleteThreads(array $threadIds, &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canUndeleteThreadsData($threads$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be undeleted. This is a slightly more
     * "internal" version of the canUndeleteThreads() function, as the required data
     * must already be retrieved.
     *
     * @param array $threads List of information about threads to be checked
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canUndeleteThreadsData(array $threads, array $forums, &$errorKey '', array $viewingUser null)
    {
        return 
$this->_checkPermissionOnThreads('canUndeleteThread'$threads$forums$errorKey$viewingUser);
    }

    
/**
     * Undeletes the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to undelete
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function undeleteThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canUndeleteThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$this->_updateThreadsDiscussionState($threads$forums'visible''deleted');

        return 
true;
    }

    
/**
     * Determines if the selected thread IDs can be approved/unapproved.
     *
     * @param array $threadIds List of thread IDs check
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canApproveUnapproveThreads(array $threadIds, &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canApproveUnapproveThreadsData($threads$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be approved/unapproved. This is a slightly more
     * "internal" version of the canApproveUnapproveThreads() function, as the required data
     * must already be retrieved.
     *
     * @param array $threads List of information about threads to be checked
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canApproveUnapproveThreadsData(array $threads, array $forums, &$errorKey '', array $viewingUser null)
    {
        return 
$this->_checkPermissionOnThreads('canApproveUnapproveThread'$threads$forums$errorKey$viewingUser);
    }

    
/**
     * Approves the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to approve
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function approveThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canApproveUnapproveThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$this->_updateThreadsDiscussionState($threads$forums'visible''moderated');

        return 
true;
    }

    
/**
     * Unapproves the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to unapprove
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function unapproveThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canApproveUnapproveThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$this->_updateThreadsDiscussionState($threads$forums'moderated''visible');

        return 
true;
    }

    
/**
     * Determines if the selected thread IDs can be locked/unlocked.
     *
     * @param array $threadIds List of thread IDs check
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canLockUnlockThreads(array $threadIds, &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canLockUnlockThreadsData($threads$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be locked/unlocked. This is a slightly more
     * "internal" version of the canLockUnlockThreads() function, as the required data
     * must already be retrieved.
     *
     * @param array $threads List of information about threads to be checked
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canLockUnlockThreadsData(array $threads, array $forums, &$errorKey '', array $viewingUser null)
    {
        return 
$this->_checkPermissionOnThreads('canLockUnlockThread'$threads$forums$errorKey$viewingUser);
    }

    
/**
     * Locks the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to change
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function lockThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canLockUnlockThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$this->_updateThreadsBulk($threads$forums, array('discussion_open' => 0), 'lock');

        return 
true;
    }

    
/**
     * Unlocks the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to change
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function unlockThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canLockUnlockThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$this->_updateThreadsBulk($threads$forums, array('discussion_open' => 1), 'unlock');

        return 
true;
    }

    
/**
     * Determines if the selected thread IDs can be stickied/unstickied.
     *
     * @param array $threadIds List of thread IDs check
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canStickUnstickThreads(array $threadIds, &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canStickUnstickThreadsData($threads$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be stickied/unstickied. This is a slightly more
     * "internal" version of the canStickUnstickThreads() function, as the required data
     * must already be retrieved.
     *
     * @param array $threads List of information about threads to be checked
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canStickUnstickThreadsData(array $threads, array $forums, &$errorKey '', array $viewingUser null)
    {
        return 
$this->_checkPermissionOnThreads('canStickUnstickThread'$threads$forums$errorKey$viewingUser);
    }

    
/**
     * Stickies the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to change
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function stickThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canStickUnstickThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$this->_updateThreadsBulk($threads$forums, array('sticky' => 1), 'stick');

        return 
true;
    }

    
/**
     * Stickies the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to change
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function unstickThreads(array $threadIds, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canStickUnstickThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$this->_updateThreadsBulk($threads$forums, array('sticky' => 0), 'unstick');

        return 
true;
    }

    
/**
     * Determines if the selected thread IDs can be moved.
     *
     * @param array $threadIds List of thread IDs check
     * @param integer $targetNodeId ID of node where threads are being moved to. Use 0 if unknown.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canMoveThreads(array $threadIds$targetNodeId, &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canMoveThreadsData($threads$targetNodeId$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be moved. This is a slightly more
     * "internal" version of the canMoveThreads() function, as the required data
     * must already be retrieved.
     *
     * @param array $threads List of information about threads to be checked
     * @param integer $targetNodeId ID of node where threads are being moved to. Use 0 if unknown.
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canMoveThreadsData(array $threads$targetNodeId, array $forums, &$errorKey '', array $viewingUser null)
    {
        if (
$targetNodeId 0)
        {
            
$forum $this->_getForumModel()->getForumById($targetNodeId);
            if (!
$forum)
            {
                
$errorKey 'please_select_valid_forum';
                return 
false;
            }
        }

        return 
$this->_checkPermissionOnThreads('canMoveThread'$threads$forums$errorKey$viewingUser);
    }

    
/**
     * Moves the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to change
     * @param integer $targetNodeId ID of node where threads are being moved to. Use 0 if unknown.
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function moveThreads(array $threadIds$targetNodeId, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canMoveThreadsData($threads$targetNodeId$forums$errorKey$viewingUser))
        {
            return 
false;
        }
        if (
$targetNodeId 1)
        {
            return 
false;
        }

        
$options array_merge(
            array(
                
'redirect' => false,
                
'redirectExpiry' => 0,
                
'checkSameForum' => true,
                
'approveModerated' => false,
                
'notifyWatch' => false
            
),
            
$options
        
);

        if (
$options['checkSameForum'])
        {
            
$allSameForum true;
            foreach (
$threads AS $thread)
            {
                if (
$thread['node_id'] != $targetNodeId)
                {
                    
$allSameForum false;
                    break;
                }
            }

            if (
$allSameForum)
            {
                
$errorKey 'all_threads_in_destination_forum';
                return 
false;
            }
        }

        
$updateOptions = array('node_id' => $targetNodeId);
        if (isset(
$options['prefix_id']))
        {
            
$updateOptions['prefix_id'] = $options['prefix_id'];
        }

        foreach (
$threads AS $thread)
        {
            
$dw XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'XenForo_DataWriter::ERROR_SILENT);
            if (!
$dw->setExistingData($thread))
            {
                continue;
            }
            
$dw->bulkSet($updateOptions);

            if (
array_key_exists($dw->get('node_id'), $forums))
            {
                
$dw->setExtraData(XenForo_DataWriter_Discussion_Thread::DATA_FORUM$forums[$dw->get('node_id')]);
            }

            if (
$options['approveModerated'] && $dw->get('discussion_state') == 'moderated')
            {
                
$dw->set('discussion_state''visible');
            }

            
$dw->save();
        }

        if (
$this->enableLogging)
        {
            foreach (
$threads AS $thread)
            {
                if (
$thread['node_id'] != $targetNodeId)
                {
                    
$forum $this->_getForumFromThread($thread$forums);
                    
$forumTitle = ($forum $forum['title'] : '');

                    
XenForo_Model_Log::logModeratorAction('thread'$thread'move', array('from' => $forumTitle));
                }

                if (isset(
$options['prefix_id']) && $thread['prefix_id'] != $options['prefix_id'])
                {
                    if (
$thread['prefix_id'])
                    {
                        
$prefixTitle = new XenForo_Phrase($this->_getPrefixModel()->getPrefixTitlePhraseName($thread['prefix_id']));
                        
$prefixTitle $prefixTitle->render();
                    }
                    else
                    {
                        
$prefixTitle '-';
                    }

                    
XenForo_Model_Log::logModeratorAction('thread'$thread'prefix', array('old' => $prefixTitle));
                }
            }
        }

        if (
$options['redirect'])
        {
            
/** @var XenForo_Model_ThreadRedirect $threadRedirectModel */
            
$threadRedirectModel $this->getModelFromCache('XenForo_Model_ThreadRedirect');
            foreach (
$threads AS $thread)
            {
                if (
$targetNodeId == $thread['node_id'])
                {
                    continue;
                }

                
$threadRedirectModel->createRedirectThread(
                    
XenForo_Link::buildPublicLink('threads'$thread), $thread,
                    
"thread-$thread[thread_id]-$thread[node_id]-"$options['redirectExpiry']
                );
            }
        }

        if (
$options['notifyWatch'])
        {
            
/** @var XenForo_Model_ForumWatch $watchModel */
            
$watchModel $this->getModelFromCache('XenForo_Model_ForumWatch');

            
/** @var XenForo_Model_Post $postModel */
            
$postModel $this->getModelFromCache('XenForo_Model_Post');

            foreach (
$threads AS $thread)
            {
                if (
$targetNodeId == $thread['node_id'])
                {
                    continue;
                }

                
$firstPost $postModel->getPostById($thread['first_post_id']);
                if (
$firstPost && $firstPost['thread_id'] == $thread['thread_id'])
                {
                    
$watchModel->sendNotificationToWatchUsersOnMove(
                        
$firstPost$thread['node_id']
                    );
                }
            }
        }

        return 
true;
    }

    
/**
     * Determines if the selected thread IDs can be merged.
     *
     * @param array $threadIds List of thread IDs check
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canMergeThreads(array $threadIds, &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);
        return 
$this->canMergeThreadsData($threads$forums$errorKey$viewingUser);
    }

    
/**
     * Determines if the selected threads can be merged. This is a slightly more
     * "internal" version of the canMergeThreads() function, as the required data
     * must already be retrieved.
     *
     * @param array $threads List of information about threads to be checked
     * @param array $forums List of information about forums the threads are in; must include unserialized permissions in 'nodePermissions' key
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
public function canMergeThreadsData(array $threads, array $forums, &$errorKey '', array $viewingUser null)
    {
        if (
count($threads) <= 1)
        {
            
$errorKey 'please_select_more_one_thread_merge';
            return 
false;
        }

        
$threadModel $this->_getThreadModel();

        foreach (
$threads AS $thread)
        {
            if (
$threadModel->isRedirect($thread))
            {
                
$errorKey 'cannot_merge_thread_redirection_notice';
                return 
false;
            }
        }

        return 
$this->_checkPermissionOnThreads('canMergeThread'$threads$forums$errorKey$viewingUser);
    }

    
/**
     * Merge the specified threads if permissions are sufficient.
     *
     * @param array $threadIds List of thread IDs to change
     * @param integer $targetThreadId ID of the thread (in the list) that the merging will happen into
     * @param array $options Options that control the action. Nothing supported at this time.
     * @param string $errorKey Modified by reference. If no permission, may include a key of a phrase that gives more info
     * @param array|null $viewingUser
     *
     * @return boolean True if permissions were ok
     */
    
public function mergeThreads(array $threadIds$targetThreadId, array $options = array(), &$errorKey '', array $viewingUser null)
    {
        list(
$threads$forums) = $this->getThreadsAndParentData($threadIds$viewingUser);

        if (empty(
$options['skipPermissions']) && !$this->canMergeThreadsData($threads$forums$errorKey$viewingUser))
        {
            return 
false;
        }

        
$options['log'] = $this->enableLogging;

        return 
$this->_getThreadModel()->mergeThreads($threads$targetThreadId$options);
    }

    
/**
     * Checks a standard thread permission against a collection of threads.
     * True is returned only if the action is possible on all threads.
     *
     * @param string $permissionMethod Name of the permission method to call in the thread model
     * @param array $threads List of threads to check
     * @param array $forums List of forums the threads are in
     * @param string $errorKey Returned by reference. Phrase key if an error occurs
     * @param array|null $viewingUser
     *
     * @return boolean
     */
    
protected function _checkPermissionOnThreads($permissionMethod, array $threads, array $forums, &$errorKey '', array $viewingUser null)
    {
        if (!
$threads)
        {
            return 
true;
        }

        
$this->standardizeViewingUserReference($viewingUser);

        
$threadModel $this->_getThreadModel();

        foreach (
$threads AS $thread)
        {
            
$forum $this->_getForumFromThread($thread$forums);

            if (!
$threadModel->canViewThreadAndContainer($thread$forum$null$forum['nodePermissions'], $viewingUser))
            {
                return 
false;
            }

            if (
$permissionMethod && !$threadModel->$permissionMethod($thread$forum$errorKey$forum['nodePermissions'], $viewingUser))
            {
                return 
false;
            }
        }

        return 
true;
    }

    
/**
     * Internal helper to update the discussion_state of a collection of threads.
     *
     * @param array $threads Information about the threads to update
     * @param array $forums Information about the forums that the threads are in
     * @param string $newState New message state (visible, moderated, deleted)
     * @param string|false $expectedOldState If specified, only updates if the old state matches
     */
    
protected function _updateThreadsDiscussionState(array $threads, array $forums$newState$expectedOldState false)
    {
        switch (
$newState)
        {
            case 
'visible':
                switch (
strval($expectedOldState))
                {
                    case 
'visible': return;
                    case 
'moderated'$logAction 'approve'; break;
                    case 
'deleted'$logAction 'undelete'; break;
                    default: 
$logAction 'undelete'; break;
                }
                break;

            case 
'moderated':
                switch (
strval($expectedOldState))
                {
                    case 
'visible'$logAction 'unapprove'; break;
                    case 
'moderated': return;
                    case 
'deleted'$logAction 'unapprove'; break;
                    default: 
$logAction 'unapprove'; break;
                }
                break;

            case 
'deleted':
                switch (
strval($expectedOldState))
                {
                    case 
'visible'$logAction 'delete_soft'; break;
                    case 
'moderated'$logAction 'delete_soft'; break;
                    case 
'deleted': return;
                    default: 
$logAction 'delete_soft'; break;
                }
                break;

            default: return;
        }

        foreach (
$threads AS $thread)
        {
            if (
$expectedOldState && $thread['discussion_state'] != $expectedOldState)
            {
                continue;
            }

            
$dw XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'XenForo_DataWriter::ERROR_SILENT);
            if (!
$dw->setExistingData($thread))
            {
                continue;
            }
            
$dw->set('discussion_state'$newState);

            if (
array_key_exists($dw->get('node_id'), $forums))
            {
                
$dw->setExtraData(XenForo_DataWriter_Discussion_Thread::DATA_FORUM$forums[$dw->get('node_id')]);
            }

            
$dw->save();

            if (
$this->enableLogging)
            {
                
XenForo_Model_Log::logModeratorAction('thread'$thread$logAction);
            }
        }
    }

    
/**
     * Bulk update 1 or more fields in the given threads.
     *
     * @param array $threads List of threads to update
     * @param array $forums List of forums threads are in
     * @param array $updates Key-value pairs to update
     * @param string $logAction If specified, this action will be logged with this action
     */
    
protected function _updateThreadsBulk(array $threads, array $forums, array $updates$logAction '')
    {
        foreach (
$threads AS $thread)
        {
            
$dw XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'XenForo_DataWriter::ERROR_SILENT);
            if (!
$dw->setExistingData($thread))
            {
                continue;
            }
            
$dw->bulkSet($updates);

            if (
array_key_exists($dw->get('node_id'), $forums))
            {
                
$dw->setExtraData(XenForo_DataWriter_Discussion_Thread::DATA_FORUM$forums[$dw->get('node_id')]);
            }

            
$dw->save();

            if (
$dw->hasChanges() && $this->enableLogging && $logAction)
            {
                
XenForo_Model_Log::logModeratorAction('thread'$thread$logAction);
            }
        }
    }

    
/**
     * Gets information about the forum a thread belogns to.
     *
     * @param array $thread Info about the thread
     * @param array $forums List of forums that the thread could belong to
     *
     * @return array Forum info
     */
    
protected function _getForumFromThread(array $thread, array $forums)
    {
        return 
$forums[$thread['node_id']];
    }

    
/**
     * From a list of threads IDs, gets info about the threads and
     * the forums the threads are in.
     *
     * @param array $threadIds List of thread IDs
     * @param array|null $viewingUser
     *
     * @return array Format:  [0] => list of threads, [1] => list of forums
     */
    
public function getThreadsAndParentData(array $threadIds, array $viewingUser null)
    {
        
$this->standardizeViewingUserReference($viewingUser);
        return 
$this->_getThreadModel()->getThreadsAndParentData($threadIds$viewingUser['permission_combination_id']);
    }

    
/**
     * @return XenForo_Model_Thread
     */
    
protected function _getThreadModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_Thread');
    }

    
/**
     * @return XenForo_Model_ThreadPrefix
     */
    
protected function _getPrefixModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_ThreadPrefix');
    }

    
/**
     * @return XenForo_Model_Forum
     */
    
protected function _getForumModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_Forum');
    }
}
Онлайн: 2
Реклама