PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.3
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.3
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
fluent-cart / app / Http / Routes / WebRoutes.php

WebRoutes.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.5.3, at app/Http/Routes/WebRoutes.php

349 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Http\Routes;
4
5 use FluentCart\Api\Resource\FrontendResource\CartResource;
6 use FluentCart\Api\StoreSettings;
7 use FluentCart\App\App;
8
9 use FluentCart\App\Helpers\CartHelper;
10 use FluentCart\App\Helpers\Helper;
11 use FluentCart\App\Hooks\Handlers\ShortCodes\Checkout\CheckoutPageHandler;
12 use FluentCart\App\Hooks\Handlers\ShortCodes\ReceiptHandler;
13 use FluentCart\App\Http\Controllers\WebController\FileDownloader;
14 use FluentCart\App\Models\Cart;
15 use FluentCart\App\Models\ProductVariation;
16 use FluentCart\App\Modules\PaymentMethods\PayPalGateway\API\PayPalPartnerRenderer;
17 use FluentCart\App\Modules\Templating\AssetLoader;
18 use FluentCart\App\Services\FrontendView;
19 use FluentCart\App\Services\PrintService;
20 use FluentCart\App\Services\Renderer\CartRenderer;
21 use FluentCart\App\Services\TemplateService;
22 use FluentCart\App\Services\URL;
23 use FluentCart\App\Vite;
24 use FluentCart\Framework\Support\Arr;
25 use FluentCart\App\Services\Renderer\CheckoutRenderer;
26 use FluentCart\App\Services\Renderer\ModalCheckoutRenderer;
27
28 class WebRoutes
29 {
30 public static function register()
31 {
32
33 add_action('init', function () {
34 self::registerRoutes();
35 });
36 }
37
38 public static function renderModalCheckout() {
39 add_action('wp_footer', function () {
40 if (!AssetLoader::isFrontendAssetsMarked() && !AssetLoader::isFluentCartContext()) {
41 return;
42 }
43
44 AssetLoader::loadModalCheckoutAssets();
45
46 if (
47 isset($_SERVER['HTTP_SEC_FETCH_DEST']) &&
48 $_SERVER['HTTP_SEC_FETCH_DEST'] === 'iframe'
49 ) {
50 return;
51 }
52
53 $cart = CartHelper::getCart();
54
55 if (!$cart) {
56 $cart = new Cart();
57 }
58
59 (new ModalCheckoutRenderer($cart))->render();
60 });
61 }
62
63 public static function registerRoutes()
64 {
65 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
66 $page = sanitize_text_field(wp_unslash($_REQUEST['fluent-cart'] ?? ''));
67
68 if (empty($page)) {
69 return;
70 }
71
72 $page = sanitize_text_field($page);
73
74 if (!$page) {
75 return;
76 }
77
78 if ($page === 'instant_checkout') {
79 $requestData = App::request()->all();
80 $variationId = sanitize_text_field(App::request()->get('item_id'));
81 $quantity = App::request()->get('quantity', 1);
82 // Raw request flag; actual validation and normalization
83 // happens in CartResource.
84 $isCustom = (bool)Arr::get($requestData, 'is_custom', false);
85
86 if(!$isCustom) {
87 if (!is_numeric($variationId)) {
88 return;
89 }
90 }
91
92 if (is_numeric($quantity)) {
93 $quantity = intval($quantity);
94 $quantity = max($quantity, 1);
95 } else {
96 $quantity = 1;
97 }
98
99 if($isCustom) {
100 $variation = apply_filters('fluent_cart/cart/validate_custom_item', null, [
101 'item_id' => $variationId,
102 'quantity' => $quantity,
103 'is_custom' => $isCustom,
104 'action' => 'instant_checkout',
105 ]);
106
107 if (!is_object($variation)) {
108 $variation = (object) $variation;
109 }
110
111 } else {
112 $variation = ProductVariation::query()->find($variationId);
113 }
114
115 if (empty($variation)) {
116 return;
117 }
118
119 $soldIndividually = $isCustom
120 ? !empty($variation->sold_individually)
121 : (bool) $variation->soldIndividually();
122
123 if ($soldIndividually) {
124 $quantity = 1;
125 }
126
127 $cart = CartResource::generateCartForInstantCheckout($variationId, $quantity, [
128 'is_custom' => $isCustom,
129 'variation' => $variation
130 ]);
131
132 if (is_wp_error($cart)) {
133 (new CheckoutPageHandler())->enqueueStyles();
134 ob_start();
135 (new CartRenderer([]))->renderEmpty(
136 $cart->get_error_message()
137 );
138 $view = ob_get_clean();
139 FrontendView::make(__('Product Not Found', 'fluent-cart'), $view);
140 die();
141 }
142
143 $coupons = App::request()->get('coupons', '');
144 if ($coupons) {
145 $coupons = explode(',', $coupons);
146 $coupons = array_map('sanitize_text_field', $coupons);
147 $cart->applyCoupon($coupons);
148 }
149
150 $target_path = (new StoreSettings())->getCheckoutPage();
151
152 $redirectTo = App::request()->get('redirect_to');
153 if (!empty($redirectTo)) {
154 $url = sanitize_url(wp_unslash($redirectTo));
155 $allowedHosts = [parse_url(home_url(), PHP_URL_HOST)];
156 $allowedHosts = apply_filters('fluent_cart/instant_checkout/allowed_redirect_hosts', $allowedHosts, [
157 'allowed_hosts' => $allowedHosts
158 ]);
159 if (!empty($url) && filter_var($url, FILTER_VALIDATE_URL) && in_array(parse_url($url, PHP_URL_HOST), $allowedHosts, true)) {
160 $target_path = $url;
161 }
162 }
163
164
165 // Step 1: Get current query string and parse to array
166
167 $queryArray = [];
168 $queryString = Arr::get( App::request()->server(), 'QUERY_STRING');
169 if ( isset($queryString) ) {
170 parse_str($queryString, $queryArray);
171 }
172
173 unset($queryArray['fluent-cart']);
174 unset($queryArray['item_id']);
175 unset($queryArray['quantity']);
176 unset($queryArray['coupons']);
177 unset($queryArray['redirect_to']);
178
179 if (isset($queryArray['is_custom'])) {
180 unset($queryArray['is_custom']);
181 }
182
183 $queryArray['fct_cart_hash'] = $cart->cart_hash;
184
185 $redirect_url = URL::appendQueryParams($target_path, $queryArray);
186
187 wp_redirect($redirect_url);
188 exit;
189 }
190
191 $served = self::handleMainRoutes($page);
192
193 // Handle faker routes if enabled and not already served
194 if (!$served && App::config()->get('using_faker') === true) {
195 $served = FakerRoutes::handle($page);
196 }
197
198 if (has_action('fluent_cart_action_' . $page)) {
199 $requestData = App::request()->all();
200 do_action('fluent_cart_action_' . $page, $requestData);
201 die();
202 }
203
204 if ($served) {
205 die();
206 }
207
208 return '';
209 }
210
211 private static function handleMainRoutes($page): bool
212 {
213 $request = App::request();
214 switch ($page) {
215 case 'fluent_cart_payment_authenticate':
216 (new PayPalPartnerRenderer($request->mode))->render(
217 $request->all()
218 );
219 return true;
220 case 'download-by-id':
221 case 'download-file':
222 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped in view template
223 echo (new FileDownloader())->index(App::request());
224 return true;
225
226 case 'receipt':
227 $receiptHandler = new ReceiptHandler();
228
229 $view = $receiptHandler->renderRedirectPage([
230 'type' => 'receipt'
231 ]);
232
233 FrontendView::make(
234 __('Order Receipt', 'fluent-cart'),
235 $view,
236 [
237 'styles' => [
238 'public/checkout/style/confirmation.scss'
239 ],
240 'scripts' => [
241 [
242 'source' => 'public/lib/printThis-2.0.0.min.js',
243 'isStatic' => true
244 ],
245 'public/print/Print.js'
246 ],
247 'enqueue_prefix' => 'fluent-cart-checkout-order-receipt',
248 'wp_head' => false,
249 'wp_footer' => false,
250 ]);
251 return true;
252
253
254 case 'print-invoice':
255 return self::handlePrintRoute('invoice');
256
257 case 'print-packing-slip':
258 return self::handlePrintRoute('packingSlip');
259
260 case 'print-delivery-slip':
261 return self::handlePrintRoute('deliverySlip');
262
263 case 'print-shipping-slip':
264 return self::handlePrintRoute('shippingSlip');
265
266 case 'print-dispatch-slip':
267 return self::handlePrintRoute('dispatchSlip');
268
269 case 'modal_checkout':
270 return self::handleModalCheckout();
271
272 default:
273 return false;
274 }
275 }
276
277 private static function handleModalCheckout(): bool
278 {
279 $variationId = App::request()->get('item_id');
280 $quantity = App::request()->get('quantity', 1);
281
282 if (!is_numeric($variationId)) {
283 return false;
284 }
285
286 if (is_numeric($quantity)) {
287 $quantity = intval($quantity);
288 $quantity = max($quantity, 1);
289 } else {
290 $quantity = 1;
291 }
292
293 $variation = ProductVariation::query()->find($variationId);
294
295 if (empty($variation)) {
296 return false;
297 }
298
299 $soldIndividually = $variation->soldIndividually();
300
301 if ($soldIndividually) {
302 $quantity = 1;
303 }
304
305 $cart = CartResource::generateCartForInstantCheckout($variationId, $quantity);
306
307 if ($cart) {
308 $modalCheckoutRenderer = new ModalCheckoutRenderer($cart);
309 ob_start();
310 $modalCheckoutRenderer->renderForm();
311 $checkoutContent = ob_get_clean();
312
313 AssetLoader::loadCheckoutAssets($cart);
314
315 Vite::enqueueStyle(
316 'fluentcart-modal-checkout-iframe-css',
317 'public/checkout/style/checkout-iframe.scss'
318 );
319
320 // Vite::enqueueScript(
321 // 'fluentcart-modal-checkout-form-js',
322 // 'public/checkout/ModalCheckoutForm.js',
323 // []
324 // );
325
326 FrontendView::make(__('Checkout', 'fluent-cart'), $checkoutContent);
327 die();
328 }
329
330 return false;
331
332
333 }
334
335 private static function handlePrintRoute($method): bool
336 {
337 if (!is_user_logged_in() || !current_user_can('manage_options')) {
338 return false;
339 }
340
341 $order = App::request()->get('order');
342 if (!empty($order)) {
343 PrintService::$method($order);
344 return true;
345 }
346 return false;
347 }
348 }
349