coreRegistry = $coreRegistry; $this->storeManager = $storeManager; $this->customerSession = $customerSession; $this->cookieManager = $cookieManager; $this->cookieMetadataFactory = $cookieMetadataFactory; $this->messageManager = $messageManager; $this->orderFactory = $orderFactory; $this->resultRedirectFactory = $resultRedirectFactory; $this->orderRepository = $orderRepository ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Sales\Api\OrderRepositoryInterface::class); $this->searchCriteriaBuilder = $searchCriteria?: \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\Framework\Api\SearchCriteriaBuilder::class); parent::__construct( $context ); } /** * Try to load valid order by $_POST or $_COOKIE * * @param App\RequestInterface $request * @return \Magento\Framework\Controller\Result\Redirect|bool * @throws \RuntimeException * @throws InputException * @throws CookieSizeLimitReachedException * @throws FailureToSendException */ public function loadValidOrder(App\RequestInterface $request) { if ($this->customerSession->isLoggedIn()) { return $this->resultRedirectFactory->create()->setPath('sales/order/history'); } $post = $request->getPostValue(); $fromCookie = $this->cookieManager->getCookie(self::COOKIE_NAME); if (empty($post) && !$fromCookie) { return $this->resultRedirectFactory->create()->setPath('sales/guest/form'); } // It is unique place in the class that process exception and only InputException. It is need because by // input data we found order and one more InputException could be throws deeper in stack trace try { $order = (!empty($post) && isset($post['oar_order_id'], $post['oar_type']) && !$this->hasPostDataEmptyFields($post)) ? $this->loadFromPost($post) : $this->loadFromCookie($fromCookie); $this->coreRegistry->register('current_order', $order); return true; } catch (InputException $e) { $this->messageManager->addErrorMessage($e->getMessage()); return $this->resultRedirectFactory->create()->setPath('sales/guest/form'); } } /** * Get Breadcrumbs for current controller action * * @param \Magento\Framework\View\Result\Page $resultPage * @return void */ public function getBreadcrumbs(\Magento\Framework\View\Result\Page $resultPage) { $breadcrumbs = $resultPage->getLayout()->getBlock('breadcrumbs'); if (!$breadcrumbs) { return; } $breadcrumbs->addCrumb( 'home', [ 'label' => __('Home'), 'title' => __('Go to Home Page'), 'link' => $this->storeManager->getStore()->getBaseUrl() ] ); $breadcrumbs->addCrumb( 'cms_page', ['label' => __('Order Information'), 'title' => __('Order Information')] ); } /** * Set guest-view cookie * * @param string $cookieValue * @return void * @throws InputException * @throws CookieSizeLimitReachedException * @throws FailureToSendException */ private function setGuestViewCookie($cookieValue) { $metadata = $this->cookieMetadataFactory->createPublicCookieMetadata() ->setPath(self::COOKIE_PATH) ->setHttpOnly(true); $this->cookieManager->setPublicCookie(self::COOKIE_NAME, $cookieValue, $metadata); } /** * Load order from cookie * * @param string $fromCookie * @return Order * @throws InputException * @throws CookieSizeLimitReachedException * @throws FailureToSendException */ private function loadFromCookie($fromCookie) { $cookieData = explode(':', base64_decode($fromCookie)); $protectCode = isset($cookieData[0]) ? $cookieData[0] : null; $incrementId = isset($cookieData[1]) ? $cookieData[1] : null; if (!empty($protectCode) && !empty($incrementId)) { $order = $this->getOrderRecord($incrementId); if (hash_equals((string)$order->getProtectCode(), $protectCode)) { $this->setGuestViewCookie($fromCookie); return $order; } } throw new InputException(__($this->inputExceptionMessage)); } /** * Load order data from post * * @param array $postData * @return Order * @throws InputException * @throws CookieSizeLimitReachedException * @throws FailureToSendException */ private function loadFromPost(array $postData) { /** @var $order \Magento\Sales\Model\Order */ $order = $this->getOrderRecord($postData['oar_order_id']); if (!$this->compareStoredBillingDataWithInput($order, $postData)) { throw new InputException(__('You entered incorrect data. Please try again.')); } $toCookie = base64_encode($order->getProtectCode() . ':' . $postData['oar_order_id']); $this->setGuestViewCookie($toCookie); return $order; } /** * Check that billing data from the order and from the input are equal * * @param Order $order * @param array $postData * @return bool */ private function compareStoredBillingDataWithInput(Order $order, array $postData) { $type = $postData['oar_type']; $email = $postData['oar_email']; $lastName = $postData['oar_billing_lastname']; $zip = $postData['oar_zip']; $billingAddress = $order->getBillingAddress(); return strtolower($lastName) === strtolower($billingAddress->getLastname()) && ($type === 'email' && strtolower($email) === strtolower($billingAddress->getEmail()) || $type === 'zip' && strtolower($zip) === strtolower($billingAddress->getPostcode())); } /** * Check post data for empty fields * * @param array $postData * @return bool */ private function hasPostDataEmptyFields(array $postData) { return empty($postData['oar_order_id']) || empty($postData['oar_billing_lastname']) || empty($postData['oar_type']) || empty($this->storeManager->getStore()->getId()) || !in_array($postData['oar_type'], ['email', 'zip'], true) || ('email' === $postData['oar_type'] && empty($postData['oar_email'])) || ('zip' === $postData['oar_type'] && empty($postData['oar_zip'])); } /** * Get order by increment_id and store_id * * @param string $incrementId * @return \Magento\Sales\Api\Data\OrderInterface * @throws InputException */ private function getOrderRecord($incrementId) { $records = $this->orderRepository->getList( $this->searchCriteriaBuilder ->addFilter('increment_id', $incrementId) ->addFilter('store_id', $this->storeManager->getStore()->getId()) ->create() ); $items = $records->getItems(); if (empty($items)) { throw new InputException(__($this->inputExceptionMessage)); } return array_shift($items); } }