* @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ namespace PrestaShop\PrestaShop\Core\Domain\CustomerService\CommandHandler; use Contact; use Context; use CustomerMessage; use Db; use Employee; use Mail; use Order; use PrestaShop\PrestaShop\Core\ConfigurationInterface; use PrestaShop\PrestaShop\Core\Domain\CustomerService\Command\ForwardCustomerThreadCommand; use PrestaShop\PrestaShop\Core\Domain\CustomerService\Exception\CustomerServiceException; use PrestaShop\PrestaShop\Core\Domain\CustomerService\ValueObject\CustomerThreadId; use Symfony\Contracts\Translation\TranslatorInterface; use Tools; use Validate; /** * @internal */ class ForwardCustomerThreadHandler implements ForwardCustomerThreadHandlerInterface { /** * @var Context */ private $context; /** * @var TranslatorInterface */ private $translator; /** * @var ConfigurationInterface */ private $configuration; /** * @param Context $context * @param ConfigurationInterface $configuration */ public function __construct(Context $context, ConfigurationInterface $configuration) { $this->context = $context; $this->translator = $this->context->getTranslator(); $this->configuration = $configuration; } /** * {@inheritdoc} */ public function handle(ForwardCustomerThreadCommand $command) { if ($command->forwardToEmployee()) { $this->forwardToEmployee($command); } else { $this->forwardToSomeoneElse($command); } } /** * Forward customer thread to another employee * * @param ForwardCustomerThreadCommand $command */ private function forwardToEmployee(ForwardCustomerThreadCommand $command) { $customerThreadMessage = $this->getCustomerThreadMessage($command->getCustomerThreadId()); $content = $this->renderMessage( $customerThreadMessage, $command->getEmployeeId()->getValue() ); $customerMessage = $this->createCustomerMessage($command); $employee = new Employee($command->getEmployeeId()->getValue()); $params = [ '{messages}' => stripslashes($content), '{employee}' => $this->context->employee->firstname . ' ' . $this->context->employee->lastname, '{comment}' => stripslashes(Tools::nl2br($command->getComment())), '{firstname}' => $employee->firstname, '{lastname}' => $employee->lastname, ]; $forwardEmailSent = Mail::Send( $this->context->language->id, 'forward_msg', $this->context->getTranslator()->trans( 'Fwd: Customer message', [], 'Emails.Subject', $this->context->language->locale ), $params, $employee->email, $employee->firstname . ' ' . $employee->lastname, $this->context->employee->email, $this->context->employee->firstname . ' ' . $this->context->employee->lastname, null, null, _PS_MAIL_DIR_, true ); if ($forwardEmailSent) { $customerMessage->private = true; $customerMessage->message = sprintf( '%s %s %s %s %s %s', $this->translator->trans('Message forwarded to', [], 'Admin.Catalog.Feature'), $employee->firstname, $employee->lastname, PHP_EOL, $this->translator->trans('Comment:', [], 'Admin.Catalog.Feature'), $command->getComment() ); $customerMessage->add(); } } /** * Forward customer thread to someone else * * @param ForwardCustomerThreadCommand $command */ private function forwardToSomeoneElse(ForwardCustomerThreadCommand $command) { $customerThreadMessage = $this->getCustomerThreadMessage($command->getCustomerThreadId()); $content = $this->renderMessage($customerThreadMessage); $params = [ '{messages}' => Tools::nl2br(stripslashes($content)), '{employee}' => $this->context->employee->firstname . ' ' . $this->context->employee->lastname, '{comment}' => stripslashes($command->getComment()), '{firstname}' => '', '{lastname}' => '', ]; $customerMessage = $this->createCustomerMessage($command); $forwardEmailSent = Mail::Send( $this->context->language->id, 'forward_msg', $this->translator->trans( 'Fwd: Customer message', [], 'Emails.Subject', $this->context->language->locale ), $params, $command->getEmail()->getValue(), null, $this->context->employee->email, $this->context->employee->firstname . ' ' . $this->context->employee->lastname, null, null, _PS_MAIL_DIR_, true ); if ($forwardEmailSent) { $customerMessage->message = sprintf( '%s %s %s %s %s', $this->translator->trans('Message forwarded to', [], 'Admin.Catalog.Feature'), $command->getEmail()->getValue(), PHP_EOL, $this->translator->trans('Comment:', [], 'Admin.Catalog.Feature'), $command->getComment() ); $customerMessage->add(); } } /** * @param array $message * @param int|null $id_employee * * @return string */ protected function renderMessage(array $message, $id_employee = null) { $tpl = $this->context->smarty->createTemplate( 'controllers' . DIRECTORY_SEPARATOR . 'customer_threads/message.tpl', $this->context->smarty ); $contacts = Contact::getContacts($this->context->language->id); $contact_array = []; foreach ($contacts as $contact) { $contact_array[$contact['id_contact']] = [ 'id_contact' => $contact['id_contact'], 'name' => $contact['name'], ]; } $contacts = $contact_array; if (!empty($message['id_product']) && empty($message['employee_name']) ) { $id_order_product = Order::getIdOrderProduct( (int) $message['id_customer'], (int) $message['id_product'] ); } $message['date_add'] = Tools::displayDate($message['date_add'], true); $message['user_agent'] = strip_tags($message['user_agent']); $message['message'] = $this->replaceUrlsWithTags($message['message']); $isValidOrderId = true; $order = new Order((int) $message['id_order']); if (!Validate::isLoadedObject($order)) { $isValidOrderId = false; } $baseAdminLink = Tools::getAdminUrl(basename(_PS_ADMIN_DIR_)); $threadUrl = $baseAdminLink . '/' . $this->context->link->getAdminLink('AdminCustomerThreads', true, [], [ 'id_customer_thread' => (int) $message['id_customer_thread'], 'viewcustomer_thread' => 1, ]); $tpl->assign([ 'thread_url' => $threadUrl, 'link' => $this->context->link, 'token' => Tools::getAdminToken( 'AdminCustomerThreads' . (int) $message['id_customer_thread'] . (int) $this->context->employee->id ), 'message' => $message, 'id_order_product' => isset($id_order_product) ? $id_order_product : null, 'email' => true, 'id_employee' => $id_employee, 'PS_SHOP_NAME' => $this->configuration->get('PS_SHOP_NAME'), 'file_name' => file_exists(_PS_UPLOAD_DIR_ . $message['file_name']), 'contacts' => $contacts, 'is_valid_order_id' => $isValidOrderId, ]); return $tpl->fetch(); } /** * @param CustomerThreadId $customerThreadId * * @return array */ private function getCustomerThreadMessage(CustomerThreadId $customerThreadId) { return Db::getInstance()->getRow(' SELECT ct.*, cm.*, cl.name subject, CONCAT(e.firstname, \' \', e.lastname) employee_name, CONCAT(c.firstname, \' \', c.lastname) customer_name, c.firstname FROM ' . _DB_PREFIX_ . 'customer_thread ct LEFT JOIN ' . _DB_PREFIX_ . 'customer_message cm ON (ct.id_customer_thread = cm.id_customer_thread) LEFT JOIN ' . _DB_PREFIX_ . 'contact_lang cl ON (cl.id_contact = ct.id_contact AND cl.id_lang = ' . (int) $this->context->language->id . ') LEFT OUTER JOIN ' . _DB_PREFIX_ . 'employee e ON e.id_employee = cm.id_employee LEFT OUTER JOIN ' . _DB_PREFIX_ . 'customer c ON (c.email = ct.email) WHERE ct.id_customer_thread = ' . (int) $customerThreadId->getValue() . ' ORDER BY cm.date_add DESC '); } /** * @param ForwardCustomerThreadCommand $command * * @return CustomerMessage */ private function createCustomerMessage(ForwardCustomerThreadCommand $command) { $customerMessage = new CustomerMessage(); $customerMessage->id_employee = (int) $this->context->employee->id; $customerMessage->id_customer_thread = (int) $command->getCustomerThreadId()->getValue(); $customerMessage->ip_address = (string) (int) ip2long(Tools::getRemoteAddr()); if (false === $customerMessage->validateField('message', $command->getComment())) { throw new CustomerServiceException( sprintf('Comment "%s" is not valid.', $command->getComment()), CustomerServiceException::INVALID_COMMENT ); } return $customerMessage; } /** * Replaces URLs with tags in string. * * @param string $text * * @return string */ private function replaceUrlsWithTags($text) { return preg_replace( '/(https?:\/\/[a-z0-9#%&_=\(\)\.\? \+\-@\/]{6,1000})([\s\n<])/Uui', '\1\2', html_entity_decode( $text, ENT_QUOTES, 'UTF-8' ) ); } }