Пример #1
0
 /**
  * Starts chat process.
  *
  * @param Request $request Incoming request.
  * @return string|\Symfony\Component\HttpFoundation\RedirectResponse Rendered
  *   page content or a redirect response.
  */
 public function startAction(Request $request)
 {
     $operator = $this->getOperator();
     $thread_id = $request->attributes->getInt('thread_id');
     // Check if the thread can be loaded.
     $thread = Thread::load($thread_id);
     if (!$thread || !isset($thread->lastToken)) {
         return $this->showErrors(array(getlocal('Wrong thread')));
     }
     $view_only = $request->query->get('viewonly') == 'true';
     $force_take = $request->query->get('force') == 'true';
     $try_take_over = !$view_only && $thread->state == Thread::STATE_CHATTING && $operator['operatorid'] != $thread->agentId;
     if ($try_take_over) {
         if (!is_capable(CAN_TAKEOVER, $operator)) {
             return $this->showErrors(array(getlocal('Cannot take over')));
         }
         if ($force_take == false) {
             $link = $this->generateUrl('chat_operator_start', array('thread_id' => $thread_id, 'force' => 'true'));
             $page = array('user' => $thread->userName, 'agent' => $thread->agentName, 'link' => $link, 'title' => getlocal('Change operator'));
             // Show confirmation page.
             return $this->render('confirm', $page);
         }
     }
     if (!$view_only) {
         if (!$thread->take($operator)) {
             return $this->showErrors(array(getlocal('Cannot take thread')));
         }
     } elseif (!is_capable(CAN_VIEWTHREADS, $operator)) {
         return $this->showErrors(array(getlocal('Cannot view threads')));
     }
     // Redrect the operator to initialized chat page
     $redirect_to = $this->generateUrl('chat_operator', array('thread_id' => intval($thread_id), 'token' => urlencode($thread->lastToken)));
     return $this->redirect($redirect_to);
 }
Пример #2
0
 /**
  * Process submitting of the mail form.
  *
  * @param Request $request Incoming request.
  * @return string Rendered page content.
  * @throws NotFoundException If the thread with specified ID and token is
  * not found.
  */
 public function submitFormAction(Request $request)
 {
     $errors = array();
     $thread_id = $request->attributes->get('thread_id');
     $token = $request->attributes->get('token');
     // Try to load the thread
     $thread = Thread::load($thread_id, $token);
     if (!$thread) {
         throw new NotFoundException('The thread is not found.');
     }
     $email = $request->request->get('email');
     $group = $thread->groupId ? group_by_id($thread->groupId) : null;
     if (!$email) {
         $errors[] = no_field('Your email');
     } elseif (!MailUtils::isValidAddress($email)) {
         $errors[] = wrong_field('Your email');
     }
     if (count($errors) > 0) {
         $request->attributes->set('errors', $errors);
         // Render the mail form again
         return $this->showFormAction($request);
     }
     $history = '';
     $last_id = -1;
     $messages = $thread->getMessages(true, $last_id);
     foreach ($messages as $msg) {
         $history .= message_to_text($msg);
     }
     // Load mail templates and substitute placeholders there.
     $mail_template = MailTemplate::loadByName('user_history', get_current_locale());
     if ($mail_template) {
         $this->sendMail(MailUtils::buildMessage($email, MIBEW_MAILBOX, $mail_template->buildSubject(), $mail_template->buildBody(array($thread->userName, $history, Settings::get('title'), Settings::get('hosturl')))));
     } else {
         trigger_error('Cannot send e-mail because "user_history" mail template cannot be loaded.', E_USER_WARNING);
     }
     $page = setup_logo($group);
     $page['email'] = $email;
     return $this->render('mailsent', $page);
 }
Пример #3
0
/**
 * Close old invitations.
 *
 * Triggers {@link \Mibew\EventDispatcher\Events::INVITATION_IGNORE} event.
 */
function invitation_close_old()
{
    // Run only one instance of cleaning process.
    $lock = new ProcessLock('invitations_close_old');
    if ($lock->get()) {
        // Freeze the time for the whole cleaning process.
        $now = time();
        $db = Database::getInstance();
        // Remove links between visitors and invitations that will be closed.
        $db->query("UPDATE {sitevisitor} v, {thread} t SET " . "v.threadid = NULL " . "WHERE t.istate = :state_invited " . "AND t.invitationstate = :invitation_wait " . "AND (:now - t.dtmcreated) > :lifetime", array(':invitation_wait' => Thread::INVITATION_WAIT, ':state_invited' => Thread::STATE_INVITED, ':lifetime' => Settings::get('invitation_lifetime'), ':now' => $now));
        // Get all invitations to close
        $threads = $db->query("SELECT * FROM {thread} " . "WHERE istate = :state_invited " . "AND invitationstate = :invitation_wait " . "AND (:now - dtmcreated) > :lifetime", array(':invitation_wait' => Thread::INVITATION_WAIT, ':state_invited' => Thread::STATE_INVITED, ':lifetime' => Settings::get('invitation_lifetime'), ':now' => $now), array('return_rows' => Database::RETURN_ALL_ROWS));
        // Close the invitations
        foreach ($threads as $thread_info) {
            $thread = Thread::createFromDbInfo($thread_info);
            $thread->invitationState = Thread::INVITATION_IGNORED;
            $thread->state = Thread::STATE_CLOSED;
            $thread->closed = $now;
            $thread->save();
            // Notify the operator about autoclosing
            $thread->postMessage(Thread::KIND_FOR_AGENT, getlocal('Visitor ignored invitation and it was closed automatically', null, $thread->locale, true));
            $args = array('invitation' => $thread);
            EventDispatcher::getInstance()->triggerEvent(Events::INVITATION_IGNORE, $args);
            unset($thread);
        }
        // Release the lock
        $lock->release();
    }
}
Пример #4
0
    /**
     * Process chat in an invitation block.
     *
     * @param Request $request Incoming request.
     * @return string|\Symfony\Component\HttpFoundation\RedirectResponse Rendered
     *   page content or a redirect response.
     */
    public function invitationAction(Request $request)
    {
        // Check if an user tries to use invitation functionality when it's
        // disabled.
        if (!Settings::get('enabletracking')) {
            return $this->redirect($this->generateUrl('chat_user_start'));
        }

        // Check if we should force the user to use SSL.
        $ssl_redirect = $this->sslRedirect($request);
        if ($ssl_redirect !== false) {
            return $ssl_redirect;
        }

        // Check if user invited to chat.
        $invitation_state = invitation_state($_SESSION[SESSION_PREFIX . 'visitorid']);

        if (!$invitation_state['invited'] || !$invitation_state['threadid']) {
            return $this->redirect($this->generateUrl('chat_user_start'));
        }

        $thread = Thread::load($invitation_state['threadid']);

        // 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;

        // Prepare page
        $page = setup_invitation_view($thread);

        // Build js application options
        $page['invitationOptions'] = $page['invitation'];

        // Initialize client side application
        $this->getAssetManager()->attachJs('js/compiled/chat_app.js');
        $this->getAssetManager()->attachJs(
            $this->startJsApplication($request, $page),
            AssetManagerInterface::INLINE,
            1000
        );

        // Expand page
        return $this->render('chat', $page);
    }
Пример #5
0
    /**
     * 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)
            );
        }
    }
Пример #6
0
/**
 * 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;
}
Пример #7
0
 /**
  * Builds a page with form for add/edit ban.
  *
  * @param Request $request Incoming request.
  * @return string Rendered page content.
  * @throws NotFoundException If the ban with specified ID is not found in
  *   the system.
  * @throws BadRequestException If "thread" GET param is specified but has a
  *   wrong format.
  */
 public function showEditFormAction(Request $request)
 {
     $operator = $this->getOperator();
     $page = array('banId' => '', 'saved' => false, 'thread' => '', 'threadid' => '', 'errors' => $request->attributes->get('errors', array()));
     if ($request->attributes->has('ban_id')) {
         $ban_id = $request->attributes->getInt('ban_id');
         // Retrieve ban information from the database
         $ban = Ban::load($ban_id);
         if (!$ban) {
             throw new NotFoundException('The ban is not found.');
         }
         $page['banId'] = $ban->id;
         $page['formaddress'] = $ban->address;
         $page['formdays'] = round(($ban->till - time()) / 86400);
         $page['formcomment'] = $ban->comment;
     } elseif ($request->query->has('thread')) {
         // Prepopulate form using thread data
         $thread_id = $request->query->has('thread');
         if (!preg_match("/^\\d{1,10}\$/", $thread_id)) {
             throw new BadRequestException('Wrong value of "thread" argument.');
         }
         $thread = Thread::load($thread_id);
         if ($thread) {
             $page['thread'] = htmlspecialchars($thread->userName);
             $page['threadid'] = $thread_id;
             $page['formaddress'] = $thread->remote;
             $page['formdays'] = 15;
         }
     }
     // Override form fields from the request if it is needed
     if ($request->isMethod('POST')) {
         $page['formaddress'] = $request->request->get('address');
         $page['formdays'] = $request->request->get('days');
         $page['formcomment'] = $request->request->get('comment');
         $page['threadid'] = $request->request->get('threadid');
     }
     $page['title'] = getlocal('Block address');
     $page['formaction'] = $request->getBaseUrl() . $request->getPathInfo();
     $page = array_merge($page, prepare_menu($operator, false));
     return $this->render('ban', $page);
 }
Пример #8
0
 /**
  * Returns content of the chat button.
  *
  * @param Request $request
  * @return string Rendered page content
  */
 public function indexAction(Request $request)
 {
     $referer = $request->server->get('HTTP_REFERER', '');
     // We need to display message about visited page only if the visitor
     // really change it.
     $new_page = empty($_SESSION[SESSION_PREFIX . 'last_visited_page']) || $_SESSION[SESSION_PREFIX . 'last_visited_page'] != $referer;
     // Display message about page change
     if ($referer && isset($_SESSION[SESSION_PREFIX . 'threadid']) && $new_page) {
         $thread = Thread::load($_SESSION[SESSION_PREFIX . 'threadid']);
         if ($thread && $thread->state != Thread::STATE_CLOSED) {
             $msg = getlocal("Visitor navigated to {0}", array($referer), $thread->locale, true);
             $thread->postMessage(Thread::KIND_FOR_AGENT, $msg);
         }
     }
     $_SESSION[SESSION_PREFIX . 'last_visited_page'] = $referer;
     $image = $request->query->get('i', '');
     if (!preg_match("/^\\w+\$/", $image)) {
         $image = 'mibew';
     }
     $lang = $request->query->get('lang', '');
     if (!preg_match("/^[\\w-]{2,5}\$/", $lang)) {
         $lang = '';
     }
     if (!$lang || !locale_is_available($lang)) {
         $lang = get_current_locale();
     }
     $group_id = $request->query->get('group', '');
     if (!preg_match("/^\\d{1,8}\$/", $group_id)) {
         $group_id = false;
     }
     if ($group_id) {
         if (Settings::get('enablegroups') == '1') {
             $group = group_by_id($group_id);
             if (!$group) {
                 $group_id = false;
             }
         } else {
             $group_id = false;
         }
     }
     // Get image file content
     $image_postfix = has_online_operators($group_id) ? "on" : "off";
     $file_name = "locales/{$lang}/button/{$image}_{$image_postfix}.png";
     $content_type = 'image/png';
     if (!is_readable($file_name)) {
         // Fall back to .gif image
         $file_name = "locales/{$lang}/button/{$image}_{$image_postfix}.gif";
         $content_type = 'image/gif';
     }
     $fh = fopen($file_name, 'rb');
     if ($fh) {
         // Create response with image in body
         $file_size = filesize($file_name);
         $content = fread($fh, $file_size);
         fclose($fh);
         $response = new Response($content, 200);
         // Set correct content info
         $response->headers->set('Content-Type', $content_type);
         $response->headers->set('Content-Length', $file_size);
     } else {
         $response = new Response('Not found', 404);
     }
     // Disable caching
     $response->headers->addCacheControlDirective('no-cache', true);
     $response->headers->addCacheControlDirective('no-store', true);
     $response->headers->addCacheControlDirective('must-revalidate', true);
     $response->setExpires(new \DateTime('yesterday noon'));
     $response->headers->set('Pragma', 'no-cache');
     return $response;
 }
 /**
  * Generates a page with a user history.
  *
  * @param Request $request
  * @return string Rendered page content
  */
 public function userAction(Request $request)
 {
     $operator = $this->getOperator();
     $user_id = $request->attributes->get('user_id', '');
     $page = array();
     if (!empty($user_id)) {
         $db = Database::getInstance();
         $query = "SELECT {thread}.* " . "FROM {thread} " . "WHERE userid=:user_id " . "AND (invitationstate = :invitation_accepted " . "OR invitationstate = :invitation_not_invited) " . "ORDER BY dtmcreated DESC";
         $found = $db->query($query, array(':user_id' => $user_id, ':invitation_accepted' => Thread::INVITATION_ACCEPTED, ':invitation_not_invited' => Thread::INVITATION_NOT_INVITED), array('return_rows' => Database::RETURN_ALL_ROWS));
     } else {
         $found = null;
     }
     $page = array_merge($page, prepare_menu($operator));
     // Setup pagination
     $pagination = setup_pagination($found, 6);
     $page['pagination'] = $pagination['info'];
     $page['pagination.items'] = $pagination['items'];
     if (!empty($page['pagination.items'])) {
         foreach ($page['pagination.items'] as $key => $item) {
             $thread = Thread::createFromDbInfo($item);
             $page['pagination.items'][$key] = array('threadId' => $thread->id, 'userName' => $thread->userName, 'userAddress' => get_user_addr($thread->remote), 'agentName' => $thread->agentName, 'chatTime' => $thread->modified - $thread->created, 'chatCreated' => $thread->created);
         }
     }
     $page['title'] = getlocal("Visit history");
     $page['menuid'] = "history";
     return $this->render('history_user', $page);
 }
Пример #10
0
 /**
  * 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;
 }
Пример #11
0
 /**
  * Update chat window state. API function
  * Call periodically by chat window.
  *
  * @param array $args Associative array of arguments. It must contains the
  *   following keys:
  *    - 'agentId': Id of the agent related to users window
  */
 protected function apiUpdate($args)
 {
     // Check access and get operator array
     $operator = $this->checkOperator($args['agentId']);
     // Update operator status
     notify_operator_alive($operator['operatorid'], $operator['istatus']);
     // Close old threads
     Thread::closeOldThreads();
     // Load stored requests
     $stored_requests = $this->getRequestsFromBuffer('users_' . $args['agentId']);
     if ($stored_requests !== false) {
         $this->responses = array_merge($this->responses, $stored_requests);
     }
 }
Пример #12
0
 /**
  * Save the thread to the database
  *
  * Triggers {@link \Mibew\EventDispatcher\Events::THREAD_UPDATE} and
  * {@link \Mibew\EventDispatcher\Events::THREAD_CREATE} events.
  *
  * @param boolean $update_revision Indicates if last modified time and last
  *   revision should be updated.
  */
 public function save($update_revision = true)
 {
     // Update modification time and revision number only if needed
     if ($update_revision) {
         $this->lastRevision = $this->nextRevision();
         $this->modified = time();
     }
     $db = Database::getInstance();
     if (!$this->id) {
         $db->query('INSERT INTO {thread} (' . 'username, userid, agentname, agentid, ' . 'dtmcreated, dtmchatstarted, dtmmodified, dtmclosed, ' . 'lrevision, istate, invitationstate, ltoken, remote, ' . 'referer, nextagent, locale, lastpinguser, ' . 'lastpingagent, usertyping, agenttyping, ' . 'shownmessageid, useragent, messagecount, groupid' . ') VALUES (' . ':user_name, :user_id, :agent_name, :agent_id, ' . ':created, :chat_started, :modified, :closed, ' . ':revision, :state, :invitation_state, :token, :remote, ' . ':referer, :next_agent, :locale, :last_ping_user, ' . ':last_ping_agent, :user_typing, :agent_typing, ' . ':shown_message_id, :user_agent, :message_count, :group_id ' . ')', array(':user_name' => $this->userName, ':user_id' => $this->userId, ':agent_name' => $this->agentName, ':agent_id' => $this->agentId, ':created' => $this->created, ':chat_started' => $this->chatStarted, ':modified' => $this->modified, ':closed' => $this->closed, ':revision' => $this->lastRevision, ':state' => $this->state, ':invitation_state' => $this->invitationState, ':token' => $this->lastToken, ':remote' => $this->remote, ':referer' => $this->referer, ':next_agent' => $this->nextAgent, ':locale' => $this->locale, ':last_ping_user' => $this->lastPingUser, ':last_ping_agent' => $this->lastPingAgent, ':user_typing' => $this->userTyping, ':agent_typing' => $this->agentTyping, ':shown_message_id' => $this->shownMessageId, ':user_agent' => $this->userAgent, ':message_count' => $this->messageCount, ':group_id' => $this->groupId));
         $this->id = $db->insertedId();
         $args = array('thread' => $this);
         EventDispatcher::getInstance()->triggerEvent(Events::THREAD_CREATE, $args);
     } else {
         // Get the original state of the thread to trigger event later.
         $original_thread = Thread::load($this->id);
         $db->query('UPDATE {thread} SET ' . 'username = :user_name, userid = :user_id, ' . 'agentname = :agent_name, agentid = :agent_id, ' . 'dtmcreated = :created, dtmchatstarted = :chat_started, ' . 'dtmmodified = :modified, dtmclosed = :closed, ' . 'lrevision = :revision, istate = :state, ' . 'invitationstate = :invitation_state, ltoken = :token, ' . 'remote = :remote, referer = :referer, ' . 'nextagent = :next_agent, locale = :locale, ' . 'lastpinguser = :last_ping_user, ' . 'lastpingagent = :last_ping_agent, ' . 'usertyping = :user_typing, agenttyping = :agent_typing, ' . 'shownmessageid = :shown_message_id, ' . 'useragent = :user_agent, messagecount = :message_count, ' . 'groupid = :group_id ' . 'WHERE threadid = :thread_id', array(':thread_id' => $this->id, ':user_name' => $this->userName, ':user_id' => $this->userId, ':agent_name' => $this->agentName, ':agent_id' => $this->agentId, ':created' => $this->created, ':chat_started' => $this->chatStarted, ':modified' => $this->modified, ':closed' => $this->closed, ':revision' => $this->lastRevision, ':state' => $this->state, ':invitation_state' => $this->invitationState, ':token' => $this->lastToken, ':remote' => $this->remote, ':referer' => $this->referer, ':next_agent' => $this->nextAgent, ':locale' => $this->locale, ':last_ping_user' => $this->lastPingUser, ':last_ping_agent' => $this->lastPingAgent, ':user_typing' => $this->userTyping, ':agent_typing' => $this->agentTyping, ':shown_message_id' => $this->shownMessageId, ':user_agent' => $this->userAgent, ':message_count' => $this->messageCount, ':group_id' => $this->groupId));
         $args = array('thread' => $this, 'original_thread' => $original_thread);
         EventDispatcher::getInstance()->triggerEvent(Events::THREAD_UPDATE, $args);
     }
 }
Пример #13
0
 /**
  * Provides a gateway for widget requests.
  *
  * Triggers {@link \Mibew\EventDispatcher\Events::VISITOR_TRACK} event.
  *
  * @param Request $request
  * @return string Rendered page content
  */
 public function indexAction(Request $request)
 {
     $operator = array();
     $response_data = array('load' => array(), 'handlers' => array(), 'dependencies' => array(), 'data' => array());
     $tracking_allowed = Settings::get('enabletracking') == '1' && (Settings::get('trackoperators') == '1' || !$this->getOperator());
     if ($tracking_allowed) {
         $entry = $request->query->get('entry', '');
         $referer = $request->server->get('HTTP_REFERER', '');
         $user_id = $request->query->get('user_id', false);
         // Check if session was started
         if (isset($_SESSION[SESSION_PREFIX . 'visitorid']) && preg_match('/^[0-9]+$/', $_SESSION[SESSION_PREFIX . 'visitorid'])) {
             // Session was started. Just track the visitor.
             $visitor_id = track_visitor($_SESSION[SESSION_PREFIX . 'visitorid'], $entry, $referer);
             $visitor = track_get_visitor_by_id($visitor_id);
         } else {
             $visitor = track_get_visitor_by_user_id($user_id);
             if ($visitor !== false) {
                 // Session is not started but the visitor exists in
                 // database. Probably third-party cookies are disabled by
                 // the browser. Use tracking by local cookie at target site.
                 $visitor_id = track_visitor($visitor['visitorid'], $entry, $referer);
             } else {
                 // Start tracking session
                 $visitor_id = track_visitor_start($entry, $referer);
                 $visitor = track_get_visitor_by_id($visitor_id);
             }
         }
         if ($visitor_id) {
             $_SESSION[SESSION_PREFIX . 'visitorid'] = $visitor_id;
         }
         if ($user_id === false) {
             // Update local cookie value at target site
             $response_data['handlers'][] = 'updateUserId';
             $response_data['dependencies']['updateUserId'] = array();
             $response_data['data']['user']['id'] = $visitor['userid'];
         }
         // Provide an ability for others to make something on visitor
         // tracking
         $event_arguments = array('visitor' => $visitor);
         EventDispatcher::getInstance()->triggerEvent(Events::VISITOR_TRACK, $event_arguments);
         // Get invitation state
         $invitation_state = invitation_state($visitor_id);
         // Check if invitation is closed
         if (!$invitation_state['invited'] && !empty($_SESSION[SESSION_PREFIX . 'invitation_threadid'])) {
             $response_data['handlers'][] = 'invitationClose';
             $response_data['dependencies']['invitationClose'] = array();
             unset($_SESSION[SESSION_PREFIX . 'invitation_threadid']);
         }
         // Check if the visitor is just invited to chat
         $is_invited = $invitation_state['invited'] && (empty($_SESSION[SESSION_PREFIX . 'invitation_threadid']) ? true : $_SESSION[SESSION_PREFIX . 'invitation_threadid'] != $invitation_state['threadid']);
         if ($is_invited) {
             // Load invitation thread
             $thread = Thread::load($invitation_state['threadid']);
             // Get operator info
             $operator = operator_by_id($thread->agentId);
             $locale = $request->query->get('locale', '');
             $operator_name = $locale == get_home_locale() ? $operator['vclocalename'] : $operator['vccommonname'];
             $avatar_url = $operator['vcavatar'] ? $this->asset($operator['vcavatar'], AssetUrlGeneratorInterface::ABSOLUTE_URL) : false;
             // Show invitation dialog at widget side
             $response_data['handlers'][] = 'invitationCreate';
             $response_data['dependencies']['invitationCreate'] = array();
             $response_data['data']['invitation'] = array('operatorName' => htmlspecialchars($operator_name), 'avatarUrl' => htmlspecialchars($avatar_url), 'threadUrl' => $this->generateUrl('chat_user_invitation', array(), UrlGeneratorInterface::ABSOLUTE_URL), 'acceptCaption' => getlocal('Answer'));
             $_SESSION[SESSION_PREFIX . 'invitation_threadid'] = $thread->id;
         }
         // Check if the visitor rejects invitation
         if ($invitation_state['invited'] && $request->query->get('invitation_rejected')) {
             invitation_reject($visitor_id);
         }
         $event_arguments = array('visitor' => $visitor, 'request' => $request, 'response' => $response_data, 'route_url_generator' => $this->getRouter(), 'asset_url_generator' => $this->getAssetManager()->getUrlGenerator());
         EventDispatcher::getInstance()->triggerEvent(Events::WIDGET_RESPONSE_ALTER, $event_arguments);
         $response_data = $event_arguments['response'];
     }
     // Builds JSONP response
     $response = new JsonResponse($response_data);
     $response->setCallback("Mibew.Objects.widget.onResponse");
     // Add headers to overcome third-party cookies problem.
     $response->headers->set('P3P', 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
     return $response;
 }