/** * Invite visitor by operator * * Triggers {@link \Mibew\EventDispatcher\Events::INVITATION_CREATE} event. * * @param int $visitor_id ID of the visitor, who must be invited. * @param array $operator Info for operator who invite the visitor * @return Thread|boolean Thread object related with invitation or boolean * false on failure */ function invitation_invite($visitor_id, $operator) { // Check if visitor already invited $invitation_state = invitation_state($visitor_id); if ($invitation_state['invited']) { return false; } // Get visitor info $visitor = track_get_visitor_by_id($visitor_id); // Get last page visited by the visitor $visitor_path = track_get_path($visitor); ksort($visitor_path); $last_visited_page = array_pop($visitor_path); // Get visitor details $visitor_details = track_retrieve_details($visitor); // Get some operator's info $operator_name = get_operator_name($operator); // Create thread for invitation $thread = new Thread(); // Populate thread and save it $thread->agentId = $operator['operatorid']; $thread->agentName = $operator_name; $thread->userName = $visitor['username']; $thread->remote = $visitor_details['remote_host']; $thread->referer = $last_visited_page; // User's locale is unknown, set operator locale to the thread $thread->locale = get_current_locale(); $thread->userId = $visitor['userid']; $thread->userAgent = $visitor_details['user_agent']; $thread->state = Thread::STATE_INVITED; $thread->invitationState = Thread::INVITATION_WAIT; $thread->save(); $db = Database::getInstance(); $db->query("UPDATE {sitevisitor} set " . "invitations = invitations + 1, " . "threadid = :thread_id " . "WHERE visitorid = :visitor_id", array(':thread_id' => $thread->id, ':visitor_id' => $visitor_id)); // Send some messages $thread->postMessage(Thread::KIND_FOR_AGENT, getlocal('Operator {0} invites visitor at {1} page', array($operator_name, $last_visited_page), get_current_locale(), true)); $thread->postMessage(Thread::KIND_AGENT, getlocal('Hello, how can I help you?', null, get_current_locale(), true), array('name' => $operator_name, 'operator_id' => $operator['operatorid'])); // Let plugins know about the invitation. $args = array('invitation' => $thread); EventDispatcher::getInstance()->triggerEvent(Events::INVITATION_CREATE, $args); return $thread; }
/** * Start chat thread for user * * @param int $group_id Id of group related to thread * @param array $requested_operator Array of requested operator info * @param string $visitor_id Id of the visitor * @param string $visitor_name Name of the visitor * @param string $referrer Page user came from * @param string $info User info * * @return Thread thread object */ function chat_start_for_user($group_id, $requested_operator, $visitor_id, $visitor_name, $referrer, $info) { // Get user info $remote_host = get_remote_host(); $user_browser = $_SERVER['HTTP_USER_AGENT']; // Check connection limit if (Thread::connectionLimitReached($remote_host)) { die("number of connections from your IP is exceeded, try again later"); } // Check if visitor was invited to chat $is_invited = false; if (Settings::get('enabletracking')) { $invitation_state = invitation_state($_SESSION[SESSION_PREFIX . 'visitorid']); if ($invitation_state['invited']) { $is_invited = true; } } // Get info about requested operator $requested_operator_online = false; if ($requested_operator) { $requested_operator_online = is_operator_online($requested_operator['operatorid']); } // Get thread object if ($is_invited) { // Get thread from invitation $thread = invitation_accept($_SESSION[SESSION_PREFIX . 'visitorid']); if (!$thread) { die("Cannot start thread"); } } else { // Create thread $thread = new Thread(); $thread->state = Thread::STATE_LOADING; $thread->agentId = 0; if ($requested_operator && $requested_operator_online) { $thread->nextAgent = $requested_operator['operatorid']; } } // Update thread fields $thread->groupId = $group_id; $thread->userName = $visitor_name; $thread->remote = $remote_host; $thread->referer = $referrer; $thread->locale = get_current_locale(); $thread->userId = $visitor_id; $thread->userAgent = $user_browser; $thread->save(); $_SESSION[SESSION_PREFIX . 'threadid'] = $thread->id; // Store own thread ids to restrict access for other people if (!isset($_SESSION[SESSION_PREFIX . 'own_threads'])) { $_SESSION[SESSION_PREFIX . 'own_threads'] = array(); } $_SESSION[SESSION_PREFIX . 'own_threads'][] = $thread->id; // Bind thread to the visitor if (Settings::get('enabletracking')) { track_visitor_bind_thread($visitor_id, $thread); } // Send several messages if ($is_invited) { $operator = operator_by_id($thread->agentId); $operator_name = get_operator_name($operator); $thread->postMessage(Thread::KIND_FOR_AGENT, getlocal('Visitor accepted invitation from operator {0}', array($operator_name), get_current_locale(), true)); } else { if ($referrer) { $thread->postMessage(Thread::KIND_FOR_AGENT, getlocal('Vistor came from page {0}', array($referrer), get_current_locale(), true)); } if ($requested_operator && !$requested_operator_online) { $thread->postMessage(Thread::KIND_INFO, getlocal('Thank you for contacting us. We are sorry, but requested operator <strong>{0}</strong> is offline. Another operator will be with you shortly.', array(get_operator_name($requested_operator)), get_current_locale(), true)); } else { $thread->postMessage(Thread::KIND_INFO, getlocal('Thank you for contacting us. An operator will be with you shortly.', null, get_current_locale(), true)); } } // TODO: May be move sending this message somewhere else? if ($info) { $thread->postMessage(Thread::KIND_FOR_AGENT, getlocal('Info: {0}', array($info), get_current_locale(), true)); } // Let plugins know that user is ready to chat. $dispatcher = EventDispatcher::getInstance(); $event_args = array('thread' => $thread); $dispatcher->triggerEvent(Events::THREAD_USER_IS_READY, $event_args); return $thread; }
/** * Process submitted leave message form. * * Send message to operator email and create special meil thread. * @param array $args Associative array of arguments. It must contains the * following keys: * - 'threadId': for this function this param equals to null; * - 'token': for this function this param equals to null; * - 'name': string, user name; * - 'email': string, user email; * - 'message': string, user message; * - 'info': string, some info about user; * - 'referrer': string, page user came from; * - 'captcha': string, captcha value; * - 'groupId': selected group id. * * @throws \Mibew\RequestProcessor\ThreadProcessorException Can throw an * exception if captcha or email is wrong. */ protected function apiProcessLeaveMessage($args) { // Check captcha if (Settings::get('enablecaptcha') == '1' && can_show_captcha()) { $captcha = $args['captcha']; $original = isset($_SESSION[SESSION_PREFIX . 'mibew_captcha']) ? $_SESSION[SESSION_PREFIX . 'mibew_captcha'] : ''; unset($_SESSION[SESSION_PREFIX . 'mibew_captcha']); if (empty($original) || empty($captcha) || $captcha != $original) { throw new ThreadProcessorException( getlocal('The letters you typed don\'t match the letters that were shown in the picture.'), ThreadProcessorException::ERROR_WRONG_CAPTCHA ); } } // Get form fields $email = $args['email']; $name = $args['name']; $message = $args['message']; $info = $args['info']; $referrer = $args['referrer']; if (!MailUtils::isValidAddress($email)) { throw new ThreadProcessorException( wrong_field("Your email"), ThreadProcessorException::ERROR_WRONG_EMAIL ); } // Verify group id $group_id = ''; if (Settings::get('enablegroups') == '1') { if (preg_match("/^\d{1,8}$/", $args['groupId']) != 0) { $group = group_by_id($args['groupId']); if ($group) { $group_id = $args['groupId']; } } } // Create thread for left message $remote_host = get_remote_host(); $user_browser = $_SERVER['HTTP_USER_AGENT']; $visitor = visitor_from_request(); // Get message locale $message_locale = Settings::get('left_messages_locale'); if (!locale_is_available($message_locale)) { $message_locale = get_home_locale(); } // Create thread $thread = new Thread(); $thread->groupId = $group_id; $thread->userName = $name; $thread->remote = $remote_host; $thread->referer = $referrer; $thread->locale = get_current_locale(); $thread->userId = $visitor['id']; $thread->userAgent = $user_browser; $thread->state = Thread::STATE_LEFT; $thread->closed = time(); $thread->save(); // Send some messages if ($referrer) { $thread->postMessage( Thread::KIND_FOR_AGENT, getlocal('Vistor came from page {0}', array($referrer), get_current_locale(), true) ); } if ($email) { $thread->postMessage( Thread::KIND_FOR_AGENT, getlocal('E-Mail: {0}', array($email), get_current_locale(), true) ); } if ($info) { $thread->postMessage( Thread::KIND_FOR_AGENT, getlocal('Info: {0}', array($info), get_current_locale(), true) ); } $thread->postMessage(Thread::KIND_USER, $message, array('name' => $name)); // Get email for message $inbox_mail = get_group_email($group_id); if (empty($inbox_mail)) { $inbox_mail = Settings::get('email'); } // Send email if ($inbox_mail) { // Prepare message to send by email $mail_template = MailTemplate::loadByName('leave_message', $message_locale); if (!$mail_template) { trigger_error( 'Cannot send e-mail because "leave_message" mail template cannot be loaded.', E_USER_WARNING ); return; } $subject = $mail_template->buildSubject(array($args['name'])); $body = $mail_template->buildBody(array( $args['name'], $email, $message, ($info ? $info . "\n" : ""), )); // Send $this->getMailerFactory()->getMailer()->send( MailUtils::buildMessage($inbox_mail, $email, $subject, $body) ); } }
/** * Redirects a chat thread to the operator with the specified ID. * * @param \Mibew\Thread $thread Chat thread to redirect. * @param int $group_id ID of the target operator. * @return boolean True if the thread was redirected and false on failure. */ protected function redirectToOperator(Thread $thread, $operator_id) { if ($thread->state != Thread::STATE_CHATTING) { // We can redirect only threads which are in proggress now. return false; } // Redirect the thread $thread->state = Thread::STATE_WAITING; $thread->nextAgent = $operator_id; $thread->agentId = 0; // Check if the target operator belongs to the current thread's group. // If not reset the current thread's group. if ($thread->groupId != 0) { $db = Database::getInstance(); list($groups_count) = $db->query("SELECT count(*) AS count " . "FROM {operatortoopgroup} " . "WHERE operatorid = ? AND groupid = ?", array($operator_id, $thread->groupId), array('return_rows' => Database::RETURN_ONE_ROW, 'fetch_type' => Database::FETCH_NUM)); if ($groups_count === 0) { $thread->groupId = 0; } } $thread->save(); // Send notification message $thread->postMessage(Thread::KIND_EVENTS, getlocal('Operator {0} redirected you to another operator. Please wait a while.', array(get_operator_name($this->getOperator())), $thread->locale, true)); return true; }