From 94ab0b8b071ff6f00a1117e968d8a1cc904c2d73 Mon Sep 17 00:00:00 2001 From: Dmitriy Simushev Date: Mon, 2 Jun 2014 09:56:27 +0000 Subject: [PATCH] Replace "operator/agent.php" with a controller --- src/mibew/libs/chat.php | 6 +- .../Controller/Chat/AbstractController.php | 69 +++++++ .../Chat/Operator/ChatController.php | 189 ++++++++++++++++++ .../Mibew/Controller/InvitationController.php | 10 +- src/mibew/libs/routing.yml | 9 + src/mibew/operator/agent.php | 141 ------------- .../server_side/users.handlebars | 2 +- 7 files changed, 278 insertions(+), 148 deletions(-) create mode 100644 src/mibew/libs/classes/Mibew/Controller/Chat/AbstractController.php create mode 100644 src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php delete mode 100644 src/mibew/operator/agent.php diff --git a/src/mibew/libs/chat.php b/src/mibew/libs/chat.php index 04da9865..855c6cea 100644 --- a/src/mibew/libs/chat.php +++ b/src/mibew/libs/chat.php @@ -569,7 +569,7 @@ function setup_chatview_for_operator(Thread $thread, $operator) // Set SSL link if (Settings::get('enablessl') == "1" && !is_secure_request()) { $data['chat']['links']['ssl'] = get_app_location(true, true) - . "/operator/agent.php?thread=" + . "/operator/chat?thread=" . $thread->id . "&token=" . $thread->lastToken; @@ -614,9 +614,9 @@ function setup_chatview_for_operator(Thread $thread, $operator) } // Set link to user redirection page $params = "thread=" . $thread->id . "&token=" . $thread->lastToken; - $data['chat']['links']['redirect'] = MIBEW_WEB_ROOT . "/operator/agent.php?" + $data['chat']['links']['redirect'] = MIBEW_WEB_ROOT . "/operator/chat?" . $params - . "&act=redirect"; + . "&redirect=1"; $data['namePostfix'] = ""; diff --git a/src/mibew/libs/classes/Mibew/Controller/Chat/AbstractController.php b/src/mibew/libs/classes/Mibew/Controller/Chat/AbstractController.php new file mode 100644 index 00000000..8d898e7c --- /dev/null +++ b/src/mibew/libs/classes/Mibew/Controller/Chat/AbstractController.php @@ -0,0 +1,69 @@ +style)) { + $this->style = new ChatStyle(ChatStyle::getDefaultStyle()); + } + + return $this->style; + } + + /** + * Checks if the user should be forced to use SSL connections. + * + * @param Request $request Request to check. + * @return boolean|\Symfony\Component\HttpFoundation\RedirectResponse False + * if the redirect is not needed and redirect response object otherwise. + */ + protected function sslRedirect(Request $request) + { + $need_redirect = Settings::get('enablessl') == '1' + && Settings::get('forcessl') == '1' + && !$request->isSecure(); + + if (!$need_redirect) { + return false; + } + + if (null !== ($qs = $request->getQueryString())) { + $qs = '?'.$qs; + } + + $path = 'https://' . $request->getHttpHost() . $request->getBasePath() + . $request->getPathInfo() . $qs; + + return $this->redirect($path); + } +} diff --git a/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php b/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php new file mode 100644 index 00000000..1585c487 --- /dev/null +++ b/src/mibew/libs/classes/Mibew/Controller/Chat/Operator/ChatController.php @@ -0,0 +1,189 @@ +sslRedirect($request); + if ($ssl_redirect !== false) { + return $ssl_redirect; + } + + $operator = $this->getOperator(); + + // Get and validate thread id + $thread_id = $request->query->get('thread'); + if (!preg_match("/^\d{1,10}$/", $thread_id)) { + throw new BadRequestException('Wrong value of "thread" argument.'); + } + + if (!$request->query->has('token')) { + // There is no token in the request so we need to start the chat + return $this->startChat($request); + } + + // Get token and verify it + $token = $request->query->get('token'); + if (!preg_match("/^\d{1,10}$/", $token)) { + throw new BadRequestException('Wrong value of "token" argument.'); + } + + $thread = Thread::load($thread_id, $token); + if (!$thread) { + throw new BadRequestException('Wrong thread.'); + } + + // Check if the current operator has enough permissions to use the thread + if ($thread->agentId != $operator['operatorid'] && !is_capable(CAN_VIEWTHREADS, $operator)) { + return $this->showErrors(array('Cannot view threads')); + } + + $page = setup_chatview_for_operator($thread, $operator); + + if ($request->query->get('redirect')) { + $page = array_merge_recursive( + $page, + setup_redirect_links($thread_id, $operator, $token) + ); + + // Render the page with redirection links. + return $this->render('redirect', $page); + } else { + // Build js application options + $page['chatOptions'] = json_encode($page['chat']); + + // Render the page with chat. + return $this->render('chat', $page); + } + } + + /** + * Starts chat process. + * + * @param Request $request Incoming request. + * @return string|\Symfony\Component\HttpFoundation\RedirectResponse Rendered + * page content or a redirect response. + * @throws BadRequestException If the thread cannot be loaded by some + * reasons. + */ + protected function startChat(Request $request) + { + $operator = $this->getOperator(); + $thread_id = $request->query->getInt('thread'); + + // Check operator's browser level because old browsers aren't supported. + $remote_level = get_remote_level($request->headers->get('User-Agent')); + if ($remote_level != 'ajaxed') { + return $this->showErrors(array(getlocal('thread.error.old_browser'))); + } + + // Check if the thread can be loaded. + $thread = Thread::load($thread_id); + if (!$thread || !isset($thread->lastToken)) { + return $this->showErrors(array(getlocal('thread.error.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('thread.error.cannot_take_over'))); + } + + if ($force_take == false) { + $link = $this->generateUrl( + 'chat_operator_start', + array( + 'thread' => $thread_id, + 'force' => true, + ) + ); + $page = array( + 'user' => $thread->userName, + 'agent' => $thread->agentName, + 'link' => $link, + 'title' => getlocal('confirm.take.head'), + ); + $page_style = new PageStyle(PageStyle::getCurrentStyle()); + + // Show confirmation page. + // TODO: Move this template to chat style. + return $page_style->render('confirm', $page); + } + } + + if (!$view_only) { + if (!$thread->take($operator)) { + return $this->showErrors(array(getlocal('thread.error.cannot_take'))); + } + } elseif (!is_capable(CAN_VIEWTHREADS, $operator)) { + return $this->showErrors(array(getlocal('thread.error.cannot_view'))); + } + + // Redrect the operator to initialized chat page + $redirect_to = $this->generateUrl( + 'chat_operator', + array( + 'thread' => intval($thread_id), + 'token' => urlencode($thread->lastToken), + ) + ); + + return $this->redirect($redirect_to); + } + + /** + * Displays error page. + * + * @param array $errors List of erorr messages to display. + * @return string Rendered content of chat's error page. + */ + protected function showErrors($errors) + { + $page = array( + 'errors' => $errors, + ); + + return $this->render('error', $page); + } +} diff --git a/src/mibew/libs/classes/Mibew/Controller/InvitationController.php b/src/mibew/libs/classes/Mibew/Controller/InvitationController.php index 940fd829..fa314890 100644 --- a/src/mibew/libs/classes/Mibew/Controller/InvitationController.php +++ b/src/mibew/libs/classes/Mibew/Controller/InvitationController.php @@ -49,9 +49,13 @@ class InvitationController extends AbstractController } // Open chat window for operator - $redirect_to = $request->getBasePath() - . '/operator/agent.php?thread=' . intval($thread->id) - . '&token=' . urlencode($thread->lastToken); + $redirect_to = $this->generateUrl( + 'chat_operator', + array( + 'thread' => intval($thread->id), + 'token' => urlencode($thread->lastToken), + ) + ); return $this->redirect($redirect_to); } diff --git a/src/mibew/libs/routing.yml b/src/mibew/libs/routing.yml index 7b31e0dd..5e37eb87 100644 --- a/src/mibew/libs/routing.yml +++ b/src/mibew/libs/routing.yml @@ -1,3 +1,12 @@ +# Chat actions + +## Operator's chat +chat_operator: + path: /operator/chat + defaults: + _controller: Mibew\Controller\Chat\Operator\ChatController::indexAction + _access_check: Mibew\AccessControl\Check\LoggedInCheck + # Pages that are available for all users button: path: /b diff --git a/src/mibew/operator/agent.php b/src/mibew/operator/agent.php deleted file mode 100644 index 95e8c438..00000000 --- a/src/mibew/operator/agent.php +++ /dev/null @@ -1,141 +0,0 @@ - array(), -); - -// Initialize chat style which is currently used in system -$chat_style = new ChatStyle(ChatStyle::getCurrentStyle()); - -$page_style = new PageStyle(PageStyle::getCurrentStyle()); - -if (!isset($_GET['token'])) { - - $remote_level = get_remote_level($_SERVER['HTTP_USER_AGENT']); - if ($remote_level != "ajaxed") { - $page['errors'][] = getlocal("thread.error.old_browser"); - $chat_style->render('error', $page); - exit; - } - - $thread = Thread::load($thread_id); - if (!$thread || !isset($thread->lastToken)) { - $page['errors'][] = getlocal("thread.error.wrong_thread"); - $chat_style->render('error', $page); - exit; - } - - $view_only = verify_param("viewonly", "/^true$/", false); - - $force_take = verify_param("force", "/^true$/", false); - if (!$view_only && $thread->state == Thread::STATE_CHATTING && $operator['operatorid'] != $thread->agentId) { - - if (!is_capable(CAN_TAKEOVER, $operator)) { - $page['errors'][] = getlocal("thread.error.cannot_take_over"); - $chat_style->render('error', $page); - exit; - } - - if ($force_take == false) { - $page = array( - 'user' => $thread->userName, - 'agent' => $thread->agentName, - 'link' => $_SERVER['PHP_SELF'] . "?thread=$thread_id&force=true", - 'title' => getlocal("confirm.take.head"), - ); - $page_style->render('confirm', $page); - exit; - } - } - - if (!$view_only) { - if (!$thread->take($operator)) { - $page['errors'][] = getlocal("thread.error.cannot_take"); - $chat_style->render('error', $page); - exit; - } - } elseif (!is_capable(CAN_VIEWTHREADS, $operator)) { - $page['errors'][] = getlocal("thread.error.cannot_view"); - $chat_style->render('error', $page); - exit; - } - - $token = $thread->lastToken; - $redirect_to = MIBEW_WEB_ROOT . "/operator/agent.php?thread=" - . intval($thread_id) . "&token=" . urlencode($token); - header("Location: " . $redirect_to); - exit; -} - -$token = verify_param("token", "/^\d{1,8}$/"); - -$thread = Thread::load($thread_id, $token); -if (!$thread) { - die("wrong thread"); -} - -if ($thread->agentId != $operator['operatorid'] && !is_capable(CAN_VIEWTHREADS, $operator)) { - $page['errors'][] = "Cannot view threads"; - $chat_style->render('error', $page); - exit; -} - -$page = array_merge_recursive( - $page, - setup_chatview_for_operator($thread, $operator) -); - -start_html_output(); - -$pparam = verify_param("act", "/^(redirect)$/", "default"); -if ($pparam == "redirect") { - $page = array_merge_recursive( - $page, - setup_redirect_links($thread_id, $operator, $token) - ); - $chat_style->render('redirect', $page); -} else { - // Build js application options - $page['chatOptions'] = json_encode($page['chat']); - // Render the page - $chat_style->render('chat', $page); -} diff --git a/src/mibew/styles/pages/default/templates_src/server_side/users.handlebars b/src/mibew/styles/pages/default/templates_src/server_side/users.handlebars index 3f462b90..ea579a43 100644 --- a/src/mibew/styles/pages/default/templates_src/server_side/users.handlebars +++ b/src/mibew/styles/pages/default/templates_src/server_side/users.handlebars @@ -98,7 +98,7 @@ threadTag: "{{[coreStyles.threadTag]}}", visitorTag: "{{[coreStyles.visitorTag]}}", - agentLink: "{{mibewRoot}}/operator/agent.php", + agentLink: "{{mibewRoot}}/operator/chat", geoLink: "{{geoLink}}", trackedLink: "{{mibewRoot}}/operator/history/user-track", banLink: "{{mibewRoot}}/operator/ban",