Вход Регистрация
Файл: library/XenForo/DataWriter/ConversationMaster.php
Строк: 543
<?php

/**
* Data writer for conversation masters.
*
* @package XenForo_Conversation
*/
class XenForo_DataWriter_ConversationMaster extends XenForo_DataWriter
{
    
/**
     * Constant for extra data that holds information about the user that is sending the message,
     * or inviting additional users to the conversation.
     *
     * @var string
     */
    
const DATA_ACTION_USER = 'actionUser';

    
/**
     * Constant for extra data that holds the message information
     *
     * @var string
     */
    
const DATA_MESSAGE = 'messageBbCode';

    
/**
     * Additional recipients to add to the conversation.
     *
     * @var array List of user IDs
     */
    
protected $_newRecipients = array();

    
/**
     * The first message data writer. This is applicable only
     * when inserting the initial conversation.
     *
     * @var XenForo_DataWriter_ConversationMessage
     */
    
protected $_firstMessageDw = null;

    
/**
    * Gets the fields that are defined for the table. See parent for explanation.
    *
    * @return array
    */
    
protected function _getFields()
    {
        return array(
            
'xf_conversation_master' => array(
                
'conversation_id'       => array('type' => self::TYPE_UINT,   'autoIncrement' => true),
                
'title'                 => array('type' => self::TYPE_STRING, 'required' => true, 'maxLength' => 100,
                        
'requiredError' => 'please_enter_valid_title'
                
),
                
'user_id'               => array('type' => self::TYPE_UINT,   'required' => true),
                
'username'              => array('type' => self::TYPE_STRING, 'required' => true, 'maxLength' => 50),
                
'start_date'            => array('type' => self::TYPE_UINT,   'default' => 0),
                
'open_invite'           => array('type' => self::TYPE_BOOLEAN, 'default' => 0),
                
'conversation_open'     => array('type' => self::TYPE_BOOLEAN, 'default' => 1),
                
'reply_count'           => array('type' => self::TYPE_UINT,   'default' => 0),
                
'recipient_count'       => array('type' => self::TYPE_UINT,   'default' => 0),
                
'first_message_id'      => array('type' => self::TYPE_UINT,   'default' => 0),
                
'last_message_date'     => array('type' => self::TYPE_UINT,   'default' => 0),
                
'last_message_id'       => array('type' => self::TYPE_UINT,   'default' => 0),
                
'last_message_user_id'  => array('type' => self::TYPE_UINT,   'default' => 0),
                
'last_message_username' => array('type' => self::TYPE_STRING, 'default' => '', 'maxLength' => 50),
                
'recipients'            => array('type' => self::TYPE_SERIALIZED, 'default' => '')
            )
        );
    }

    
/**
    * Gets the actual existing data out of data that was passed in. See parent for explanation.
    *
    * @param mixed
    *
    * @return array|false
    */
    
protected function _getExistingData($data)
    {
        if (!
$id = $this->_getExistingPrimaryKey($data))
        {
            return 
false;
        }

        return array(
'xf_conversation_master' => $this->_getConversationModel()->getConversationMasterById($id));
    }

    
/**
    * Gets SQL condition to update the existing record.
    *
    * @return string
    */
    
protected function _getUpdateCondition($tableName)
    {
        return 
'conversation_id = ' . $this->_db->quote($this->getExisting('conversation_id'));
    }

    
/**
     * Add recipients via a list of user IDs. These users are not checked for sending permissions!
     *
     * @param array $userIds
     */
    
public function addRecipientUserIds(array $userIds)
    {
        
$this->_newRecipients = array_unique(array_merge($this->_newRecipients, $userIds));
    }

    
/**
     * Add recipients via a list of user names. This checks that the visitor/invite user can send to the recipients.
     *
     * @param array $usernames
     */
    
public function addRecipientUserNames(array $usernames)
    {
        
$permUser = $this->getExtraData(self::DATA_ACTION_USER);
        if (!
$permUser || $permUser == XenForo_Visitor::getUserId())
        {
            
$permUser = null;
            
$permUserId = XenForo_Visitor::getUserId();
        }
        else
        {
            
$permUserId = $permUser['user_id'];
        }

        
$users = $this->_getUserModel()->getUsersByNames(
            
$usernames,
            array(
                
'join' => XenForo_Model_User::FETCH_USER_PRIVACY | XenForo_Model_User::FETCH_USER_OPTION
                    
| XenForo_Model_User::FETCH_USER_PERMISSIONS,
                
'followingUserId' => $permUserId
            
),
            
$notFound
        
);

        if (
$notFound)
        {
            
$this->error(new XenForo_Phrase('the_following_recipients_could_not_be_found_x', array('names' => implode(', ', $notFound))), 'recipients');
        }
        else
        {
            
$conversationModel = $this->_getConversationModel();
            
$noStart = array();
            foreach (
$users AS $key => $user)
            {
                if (
$permUserId == $user['user_id'])
                {
                    
// skip trying to add self
                    
unset($users[$key]);
                    continue;
                }

                if (!
$conversationModel->canStartConversationWithUser($user, $null, $permUser))
                {
                    
$noStart[] = $user['username'];
                }
            }

            if (
$noStart)
            {
                
$this->error(new XenForo_Phrase('you_may_not_start_a_conversation_with_the_following_recipients_x', array('names' => implode(', ', $noStart))), 'recipients');
            }
            else
            {
                
$this->_newRecipients = array_merge($this->_newRecipients, array_keys($users));

                
$remaining = $conversationModel->allowedAdditionalConversationRecipients($this->getMergedExistingData(), $permUser);
                if (
$remaining > -1 && count($this->_newRecipients) > $remaining)
                {
                    
$this->error(new XenForo_Phrase('you_may_only_invite_x_members_to_join_this_conversation', array('count' => $remaining)), 'recipients');
                }
            }
        }
    }

    
/**
     * Adds the data from a reply to the conversation. This does not actually
     * add the reply; it will normally be called by the message DW.
     *
     * @param array $reply Information about the reply
     */
    
public function addReply(array $reply)
    {
        if (
$this->isUpdate())
        {
            
$master = $this->_db->fetchRow('
                SELECT *
                FROM xf_conversation_master
                WHERE conversation_id = ?
                FOR UPDATE
            '
, $this->get('conversation_id'));
            if (
$master)
            {
                
$this->_existingData['xf_conversation_master'] = $master;
            }
        }

        
$this->set('reply_count', $this->get('reply_count') + 1);
        if (
$reply['message_date'] > $this->get('last_message_date'))
        {
            
$this->set('last_message_date',     $reply['message_date']);
            
$this->set('last_message_id',       $reply['message_id']);
            
$this->set('last_message_user_id',  $reply['user_id']);
            
$this->set('last_message_username', $reply['username']);
        }
    }

    
/**
     * Pre-save handling.
     */
    
protected function _preSave()
    {
        if (
$this->_newRecipients)
        {
            
$creatorUserId = $this->get('user_id');
            foreach (
$this->_newRecipients AS $key => $recipientUserId)
            {
                if (
$recipientUserId == $creatorUserId)
                {
                    unset(
$this->_newRecipients[$key]);
                }
            }
        }

        if (
$this->_newRecipients)
        {
            
$recipients = @unserialize($this->get('recipients'));
            if (!
$recipients)
            {
                
$recipients = array();
            }
            
$recipients += $this->_getUserModel()->getUsersByIds($this->_newRecipients);

            
$this->_updateRecipients($recipients);
        }

        if (
$this->isInsert() && !$this->_newRecipients)
        {
            
$this->error(new XenForo_Phrase('please_enter_at_least_one_valid_recipient'), 'recipients', false);
        }

        if (
$this->isInsert() && !$this->_firstMessageDw)
        {
            throw new 
XenForo_Exception('Must create a first message DW on insert.');
        }

        if (
$this->isInsert())
        {
            if (!
$this->isChanged('start_date'))
            {
                
$this->set('start_date', XenForo_Application::$time);
            }

            
$fieldMap = array(
                
'last_message_date' => 'start_date',
                
'last_message_user_id' => 'user_id',
                
'last_message_username' => 'username'
            
);
            foreach (
$fieldMap AS $childField => $parentField)
            {
                if (!
$this->isChanged($childField))
                {
                    
$this->set($childField, $this->get($parentField));
                }
            }
        }

        if (
$this->_firstMessageDw)
        {
            
$messageDw = $this->_firstMessageDw;
            
$messageDw->set('conversation_id', 0);

            foreach (
$this->_newData AS $table => $newData)
            {
                foreach (
$newData AS $field => $value)
                {
                    
$messageDw->set($field, $value, '', array('ignoreInvalidFields' => true));
                }
            }

            
$messageDw->preSave();
            
$firstMessageErrors = $messageDw->getErrors();
            if (
$firstMessageErrors)
            {
                
$this->_errors = array_merge($this->_errors, $firstMessageErrors);
            }
        }
    }

    protected function 
_updateRecipients(array $recipients)
    {
            
$sort = array();
            foreach (
$recipients AS $key => $user)
            {
                if (
$user['user_id'])
                {
                    
$sort[$key] = utf8_strtolower($user['username']);
                }
                else
                {
                    
$sort[$key] = '';
                }
            }
            
asort($sort);

            
$finalRecipients = array();
            foreach (
$sort AS $key => $null)
            {
                
$recipient = $recipients[$key];

                
$hasRecord = is_string($recipient['username']) && strlen($recipient['username']) > 0;

                
$finalRecipients[$recipient['user_id']] = array(
                    
'user_id' => $hasRecord ? $recipient['user_id'] : 0,
                    
'username' => $hasRecord ? $recipient['username'] : ''
                
);
            }

            
$this->set('recipients', serialize($finalRecipients));
    }

    
/**
     * Post-save handling.
     */
    
protected function _postSave()
    {
        
$conversationId = $this->get('conversation_id');

        if (
$this->_firstMessageDw)
        {
            
$this->_firstMessageDw->set('conversation_id', $conversationId, '', array('setAfterPreSave' => true));
            
$this->_firstMessageDw->save();
            
$firstMessageId = $this->_firstMessageDw->get('message_id');

            
$toUpdate = array(
                
'first_message_id' => $firstMessageId,
                
'last_message_id' => $firstMessageId
            
);
            
$this->_db->update('xf_conversation_master', $toUpdate, 'conversation_id = ' . $this->_db->quote($conversationId));
            
$this->bulkSet($toUpdate, array('setAfterPreSave' => true));
        }

        
$conversationModel = $this->_getConversationModel();
        
$conversation = $this->getMergedData();

        
$actionUser = $this->getExtraData(self::DATA_ACTION_USER);
        
$messageInfo = array('message' => $this->getExtraData(self::DATA_MESSAGE));

        if (
$this->isUpdate() && $this->isChanged('reply_count'))
        {
            
$conversationModel->addConversationReplyToRecipients($conversation, $actionUser, $messageInfo);
        }
        else if (
$this->isInsert())
        {
            
$this->_newRecipients[] = $this->get('user_id');
        }

        if (
$recipients = $this->_getUserModel()->getUsersByIds($this->_newRecipients, array('join' => XenForo_Model_User::FETCH_USER_FULL)))
        {
            
// on initial insert, don't need to look for recipient records
            
$existingRecipient = ($this->isInsert() ? array() : null);
            
$alertAction = ($this->isInsert() ? 'insert' : 'join');

            
/* @var $userModel XenForo_Model_User */
            
$userModel = $this->getModelFromCache('XenForo_Model_User');

            foreach (
$recipients AS $recipient)
            {
                
$insertState = 'active';
                if (
$actionUser && $userModel->isUserIgnored($recipient, $actionUser['user_id']))
                {
                    
$insertState = 'deleted_ignored';
                }

                if (
$conversationModel->insertConversationRecipient($conversation, $recipient['user_id'], $existingRecipient, $insertState))
                {
                    
$conversationModel->insertConversationAlert($conversation, $recipient, $alertAction, $actionUser, null, $messageInfo);
                }
            }
        }
    }

    
/**
     * Post-delete handling.
     */
    
protected function _postDelete()
    {
        
$db = $this->_db;

        
$conversationIdQuoted = $db->quote($this->get('conversation_id'));

        
$db->query("
            UPDATE xf_user AS user
            INNER JOIN xf_conversation_user AS cuser ON
                (cuser.owner_user_id = user.user_id AND cuser.conversation_id = ?)
            SET user.conversations_unread = user.conversations_unread - 1
            WHERE user.conversations_unread > 0
        "
, $this->get('conversation_id'));

        
$messageIds = $db->fetchCol("
            SELECT message_id
            FROM xf_conversation_message
            WHERE conversation_id = ?
        "
, $this->get('conversation_id'));

        
$db->delete('xf_conversation_message', 'conversation_id = ' . $conversationIdQuoted);
        
$db->delete('xf_conversation_recipient', 'conversation_id = ' . $conversationIdQuoted);
        
$db->delete('xf_conversation_user', 'conversation_id = ' . $conversationIdQuoted);
        
$db->delete('xf_user_alert', 'content_type = 'conversation' AND content_id = ' . $conversationIdQuoted);

        
$this->getModelFromCache('XenForo_Model_Attachment')->deleteAttachmentsFromContentIds(
            
'conversation_message',
            
$messageIds
        
);
    }

    public function 
rebuildRecipients()
    {
        
$recipients = $this->_getConversationModel()->getConversationRecipients($this->get('conversation_id'));
        
$this->set('recipient_count', count($recipients));

        unset(
$recipients['deleted'], $recipients[$this->get('user_id')]);
        
$this->_updateRecipients($recipients);
    }

    
/**
     * Gets the first message DW. This can (and must) only be done on inserts.
     *
     * @return XenForo_DataWriter_ConversationMessage
     */
    
public function getFirstMessageDw()
    {
        if (
$this->isUpdate())
        {
            throw new 
XenForo_Exception('Cannot manage first message on updates.');
        }

        if (!
$this->_firstMessageDw)
        {
            
$this->_firstMessageDw = XenForo_DataWriter::create('XenForo_DataWriter_ConversationMessage', $this->_errorHandler);
            
$this->_firstMessageDw->setOption(XenForo_DataWriter_ConversationMessage::OPTION_UPDATE_CONVERSATION, false);
            
$this->_firstMessageDw->setOption(XenForo_DataWriter_ConversationMessage::OPTION_CHECK_SENDER_RECIPIENT, false);
        }

        return 
$this->_firstMessageDw;
    }

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