#9761 - Don't use forCheckout outside of cart

This commit is contained in:
Max von Krusenstierna
2026-07-01 11:22:35 +02:00
committed by GitHub
parent 0eb8c83634
commit 4def81fc2a
10 changed files with 86 additions and 109 deletions
+25 -58
View File
@@ -3,19 +3,19 @@
use Photowall\Analytics\GA4ECommerce\AddToCartEvent;
use Photowall\Analytics\GA4ECommerce\AddToCartMultiEvent;
use Photowall\Analytics\GA4ECommerce\RemoveFromCartEvent;
use Photowall\Checkout\CartItem\WallpaperGlueItem;
use Photowall\Checkout\Helpers\TrialFramedPrintsQuantityDiscount;
use Photowall\Checkout\CartItem\{
SampleItem,
WallpaperKitItem,
WallpaperKitPeelAndStickItem,
WallPaintKitItem,
WallpaperGlueItem,
AdminProductItem,
CustomItem,
PaintCardSampleItem,
PaintItem,
ProductItem,
WallpaperKitPeelAndStickItem,
WallPaintKitItem,
};
use Photowall\Constants\Enums\OrderRowSubTypes;
use Photowall\Checkout\CartItem\Builders\PrintProduct\{
PosterBuilder,
CanvasBuilder,
@@ -56,9 +56,7 @@ class Cart_Controller extends Controller_Core
public function setQuantity()
{
$this->assertIsPost();
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$data = $this->getJsonPostBody();
$itemId = $data['id'];
$quantity = $data['quantity'];
@@ -84,62 +82,40 @@ class Cart_Controller extends Controller_Core
}
}
/**
* Manages adding of a wallpaper kit to the cart.
*
* @param ProductItem $item
* @return void
*/
private function addUpsellItemDispatcher(ProductItem $item)
public function addUpsellItem()
{
$data = $this->getJsonPostBody();
$cart = CartSession::instance();
$item = match ($data['type']) {
OrderRowSubTypes::WALLPAPER_KIT => WallpaperKitItem::create($cart),
OrderRowSubTypes::WALLPAPER_KIT_PEEL_AND_STICK => WallpaperKitPeelAndStickItem::create($cart),
OrderRowSubTypes::WALL_PAINT_KIT => WallPaintKitItem::create($cart),
OrderRowSubTypes::WALLPAPER_GLUE => WallpaperGlueItem::create($cart),
default => $this->jsonErrorResponse(400),
};
$cart->addProduct($item);
$cart->save();
if ($callback = $this->input->post("callback")) {
\url::redirect($callback);
return;
}
$ga4Event = new AddToCartEvent($item);
$response = ['ga4_event_data' => $ga4Event->getData()];
$response = [
'ga4_event_data' => $ga4Event->getData(),
];
$this->cartResponseWithIngrid($response);
if (!empty($data['forCheckout'])) {
return $this->cartResponseWithIngrid($response);
}
public function addWallpaperKit()
{
$this->addUpsellItemDispatcher(WallpaperKitItem::create(CartSession::instance()));
}
public function addWallpaperKitPeelAndStick()
{
$this->addUpsellItemDispatcher(WallpaperKitPeelAndStickItem::create(CartSession::instance()));
}
public function addWallPaintKit()
{
$this->addUpsellItemDispatcher(WallPaintKitItem::create(CartSession::instance()));
}
public function addWallpaperGlue()
{
$this->addUpsellItemDispatcher(WallpaperGlueItem::create(CartSession::instance()));
$this->jsonResponse([...['status' => 'ok', 'cart' => $cart->exportClient(true)], ...$response]);
}
public function removeItem()
{
$this->assertIsPost();
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$data = $this->getJsonPostBody();
$itemId = $data['id'];
if (!is_null($itemId)) {
$cart = CartSession::instance();
$item = $cart->getProduct($itemId);
if (!$item) {
throw new Kohana_404_Exception();
return $this->jsonErrorResponse(500);
}
$ga4Event = new RemoveFromCartEvent($item);
$cart->removeItem($itemId);
@@ -220,7 +196,6 @@ class Cart_Controller extends Controller_Core
public function addCanvasProduct()
{
$this->assertIsPost();
$item = CanvasBuilder::tryCreate($_POST)->getPrintProductItem();
$cart = CartSession::instance();
$cart->addProduct($item);
@@ -424,9 +399,7 @@ class Cart_Controller extends Controller_Core
*/
public function setDiscountCode()
{
$this->assertIsPost();
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$data = $this->getJsonPostBody();
// validate input
$post = new Validation($data);
$post->pre_filter('trim');
@@ -482,9 +455,7 @@ class Cart_Controller extends Controller_Core
return $this->jsonErrorResponse('Can\'t set delivery country. Cart does not exist', 404);
}
$this->assertIsPost();
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$data = $this->getJsonPostBody();
$countryCode = $data['countryCode'];
if (!is_null($countryCode) && $countryCode != "") {
$cart->data()->setCountry($countryCode);
@@ -501,9 +472,7 @@ class Cart_Controller extends Controller_Core
$this->jsonErrorResponse('Can\'t set customer type. Cart does not exist', 404);
}
$this->assertIsPost();
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$data = $this->getJsonPostBody();
$type = $data['customerType'];
$cart->setCustomerType($type);
$cart->save();
@@ -517,9 +486,7 @@ class Cart_Controller extends Controller_Core
if (!$cart) {
$this->jsonErrorResponse('Can\'t set contract customer code. Cart does not exist', 404);
}
$this->assertIsPost();
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$data = $this->getJsonPostBody();
$code = $data['contractCode'];
if (!is_null($code)) {
@@ -104,6 +104,8 @@
'feature-easy-installation',
'material-badge-most-popular',
'material-badge-new',
'material-badge-premium-matte',
'material-badge-peel-and-stick-matte',
'material-select-standard',
'material-select-matte',
'material-select-premium',
@@ -177,7 +179,6 @@
'measurements-tooltip-heading',
'measurements-tooltip-copy',
'trustpilot-score',
'material-badge-premium-matte',
'settings-select-material',
'material-info-link',
'total-price',
@@ -194,7 +195,6 @@
'feature-anti-glare-matte-finish',
'feature-stain-resistant',
'feature-removable',
'material-badge-peel-and-stick-matte',
] %}
@@ -243,6 +243,8 @@
'feature-easy-installation',
'material-badge-most-popular',
'material-badge-new',
'material-badge-premium-matte',
'material-badge-peel-and-stick-matte',
'material-select-standard',
'material-select-matte',
'material-select-premium',
@@ -251,6 +253,10 @@
'material-matte-selected',
'material-premium-selected',
'material-peel-and-stick-selected',
'materials-classic-matte-preamble',
'materials-standard-preamble',
'materials-premium-preamble',
'materials-peel-and-stick-preamble',
'settings-change-settings',
'settings-select-material',
'settings-options',
@@ -1,12 +1,13 @@
import useTexts from '@hooks/useTexts';
import { pwConfig } from '@react/global/config';
import { useAddToCartMutation } from '@redux/services/cart';
import { useCheckoutPostToCartMutation } from '@redux/services/cart';
import React from 'react';
import { sendEvent } from '../../../../../analytics/GA4';
import { GA4EventTypes } from '../../../../../analytics/GA4types';
import { sendEvent } from '@analytics/GA4';
import { GA4EventTypes } from '@analytics/GA4types';
import { useAppDispatch } from '@redux/hooks';
import { addLoader, removeLoader } from '@redux/slices/loaderSlice';
import DetailedCardUpsell from '../common/DetailedCard';
import { OrderRowSubTypes } from '@react/global/types/orderTypes';
interface IGlueUpsellCart {
className?: string;
@@ -27,7 +28,7 @@ const GlueUpsellCart = ({
const imageServerUrl = pwConfig('imageserver');
const { priceFormatted, orgPriceFormatted }: TGlueContent =
window.PW.config.i18n.glue;
const [addToCart] = useAddToCartMutation();
const [postToCart] = useCheckoutPostToCartMutation();
const dispatch = useAppDispatch();
const texts = getTexts([
'wp-glue-header',
@@ -50,9 +51,9 @@ const GlueUpsellCart = ({
),
);
dispatch(addLoader({ elSelector: '.upsell-loader-container' }));
const result = await addToCart({
path: `${window.PW.config.i18n.pathPrefix}/cart/addWallpaperGlue`,
body: null,
const result = await postToCart({
path: `${window.PW.config.i18n.pathPrefix}/cart/addUpsellItem`,
body: { type: OrderRowSubTypes.WALLPAPER_GLUE },
forCheckout: true,
});
@@ -1,6 +1,6 @@
import useTexts from '@hooks/useTexts';
import { pwConfig } from '@react/global/config';
import { useAddToCartMutation } from '@redux/services/cart';
import { useCheckoutPostToCartMutation } from '@redux/services/cart';
import React from 'react';
import { sendEvent } from '@analytics/GA4';
import { GA4EventTypes } from '@analytics/GA4types';
@@ -26,13 +26,14 @@ const KitUpsellCart = ({
const {
productId,
apiPath,
type: itemType,
priceFormatted,
orgPriceFormatted,
header,
subheader,
itemsInKit,
} = getKitUpsellTypeContentObject(type);
const [addToCart] = useAddToCartMutation();
const [postToCart] = useCheckoutPostToCartMutation();
const dispatch = useAppDispatch();
const handleAddToCart = async () => {
sendEvent(
@@ -48,9 +49,9 @@ const KitUpsellCart = ({
),
);
dispatch(addLoader({ elSelector: '.upsell-loader-container' }));
const result = await addToCart({
const result = await postToCart({
path: apiPath,
body: null,
body: { type: itemType },
forCheckout: true,
});
if (result?.data?.status === 'ok') {
@@ -1,10 +1,10 @@
import useTexts from '@hooks/useTexts';
import { pwConfig } from '@react/global/config';
import { useAddToCartMutation } from '@redux/services/cart';
import { PathPrefixes } from '@react/global/types/marketTypes';
import { OrderRowSubTypes } from '@react/global/types/orderTypes';
import React, { useEffect, useState } from 'react';
import { sendEvent } from '../../../../../analytics/GA4';
import { GA4EventTypes } from '../../../../../analytics/GA4types';
import { sendEvent } from '@analytics/GA4';
import { GA4EventTypes } from '@analytics/GA4types';
import { useAppDispatch } from '@redux/hooks';
import styled from 'styled-components';
import { breakpoint } from '@react/global/style/design-system';
@@ -32,8 +32,6 @@ type TGlueContent = {
inStock: boolean;
};
type AddGlueToCartPath = `${PathPrefixes}/cart/addWallpaperGlue`;
const GlueUpsellPopup = ({
className,
listWidth,
@@ -67,8 +65,8 @@ const GlueUpsellPopup = ({
),
);
await addToCart({
path: `${window.PW.config.i18n.pathPrefix}/cart/addWallpaperGlue` as AddGlueToCartPath,
body: null,
path: `${window.PW.config.i18n.pathPrefix}/cart/addUpsellItem`,
body: { type: OrderRowSubTypes.WALLPAPER_GLUE },
});
};
@@ -2,8 +2,8 @@ import useTexts from '@hooks/useTexts';
import { pwConfig } from '@react/global/config';
import { useAddToCartMutation } from '@redux/services/cart';
import React, { useEffect, useState } from 'react';
import { sendEvent } from '../../../../../analytics/GA4';
import { GA4EventTypes } from '../../../../../analytics/GA4types';
import { sendEvent } from '@analytics/GA4';
import { GA4EventTypes } from '@analytics/GA4types';
import { useAppDispatch } from '@redux/hooks';
import DetailedCardUpsell from '../common/DetailedCard';
import styled from 'styled-components';
@@ -38,6 +38,7 @@ const KitUpsellPopup = ({
const {
productId,
apiPath,
type,
priceFormatted,
orgPriceFormatted,
header,
@@ -64,7 +65,7 @@ const KitUpsellPopup = ({
);
await addToCart({
path: apiPath,
body: null,
body: { type },
});
};
@@ -1,12 +1,11 @@
import { PathPrefixes } from '@react/global/types/marketTypes';
import { OrderRowSubTypes } from '@react/global/types/orderTypes';
import { KitUpsellType } from '../types';
interface IKitUpsellContentObject {
productId: string;
apiPath:
| `${PathPrefixes}/cart/addWallpaperKit`
| `${PathPrefixes}/cart/addWallpaperKitPeelAndStick`
| `${PathPrefixes}/cart/addWallPaintKit`;
apiPath: `${PathPrefixes}/cart/addUpsellItem`;
type: OrderRowSubTypes;
inStock: boolean;
noInStockText: string;
priceFormatted: string;
@@ -24,7 +23,8 @@ export const getKitUpsellTypeContentObject = (
case KitUpsellType.WALLPAPER_NORMAL:
return {
productId: '47851',
apiPath: `${window.PW.config.i18n.pathPrefix}/cart/addWallpaperKit`,
apiPath: `${window.PW.config.i18n.pathPrefix}/cart/addUpsellItem`,
type: OrderRowSubTypes.WALLPAPER_KIT,
inStock: window.PW.config.i18n.kit.wallpaperNormal.inStock,
noInStockText: 'wallpaper-kit-out-of-stock',
priceFormatted:
@@ -48,7 +48,8 @@ export const getKitUpsellTypeContentObject = (
case KitUpsellType.WALLPAPER_PEELANDSTICK:
return {
productId: '92730',
apiPath: `${window.PW.config.i18n.pathPrefix}/cart/addWallpaperKitPeelAndStick`,
apiPath: `${window.PW.config.i18n.pathPrefix}/cart/addUpsellItem`,
type: OrderRowSubTypes.WALLPAPER_KIT_PEEL_AND_STICK,
inStock: window.PW.config.i18n.kit.wallpaperPeelAndStick.inStock,
noInStockText: 'wallpaper-kit-out-of-stock',
priceFormatted:
@@ -70,7 +71,8 @@ export const getKitUpsellTypeContentObject = (
case KitUpsellType.WALL_PAINT:
return {
productId: '94004',
apiPath: `${window.PW.config.i18n.pathPrefix}/cart/addWallPaintKit`,
apiPath: `${window.PW.config.i18n.pathPrefix}/cart/addUpsellItem`,
type: OrderRowSubTypes.WALL_PAINT_KIT,
inStock: window.PW.config.i18n.kit.wallPaint.inStock,
noInStockText: 'wallpaint-kit-out-of-stock',
priceFormatted: window.PW.config.i18n.kit.wallPaint.priceFormatted,
@@ -1,7 +1,6 @@
import useTexts from '@hooks/useTexts';
import { pwConfig } from '@react/global/config';
import { useAddToCartMutation, useGetCartQuery } from '@redux/services/cart';
import { PathPrefixes } from '@react/global/types/marketTypes';
import React, { useEffect } from 'react';
import { sendEvent } from '@analytics/GA4';
import { GA4EventTypes } from '@analytics/GA4types';
@@ -30,8 +29,6 @@ type TGlueContent = {
inStock: boolean;
};
type AddGlueToCartPath = `${PathPrefixes}/cart/addWallpaperGlue`;
const GlueUpsell = ({ className }: IGlueUpsell): JSX.Element => {
const { getTexts } = useTexts();
const imageServerUrl = pwConfig('imageserver');
@@ -63,8 +60,8 @@ const GlueUpsell = ({ className }: IGlueUpsell): JSX.Element => {
),
);
await addToCart({
path: `${window.PW.config.i18n.pathPrefix}/cart/addWallpaperGlue` as AddGlueToCartPath,
body: null,
path: `${window.PW.config.i18n.pathPrefix}/cart/addUpsellItem`,
body: { type: OrderRowSubTypes.WALLPAPER_GLUE },
});
};
+2 -1
View File
@@ -55,6 +55,7 @@ const KitUpsellPDP = ({ className, kitType }: IKitUpsell): JSX.Element => {
const {
productId,
apiPath,
type,
priceFormatted,
orgPriceFormatted,
header,
@@ -82,7 +83,7 @@ const KitUpsellPDP = ({ className, kitType }: IKitUpsell): JSX.Element => {
);
await addToCart({
path: apiPath,
body: null,
body: { type },
});
};
+17 -14
View File
@@ -257,12 +257,9 @@ interface IAddMultipleSamplesMutation {
}
interface IUpsellAddToCartMutation {
path:
| `${PathPrefixes}/cart/addWallpaperKit`
| `${PathPrefixes}/cart/addWallpaperKitPeelAndStick`
| `${PathPrefixes}/cart/addWallPaintKit`
| `${PathPrefixes}/cart/addWallpaperGlue`;
body?: null;
path: `${PathPrefixes}/cart/addUpsellItem`;
body: { type: string };
forCheckout?: boolean;
}
export interface IPaintAddToCartMutation {
@@ -370,7 +367,8 @@ type ICheckoutPostToCartMutation =
| IRemoveDiscountCodeMutation
| ICheckoutIngridPostToCartMutation
| IAddCustomerProductNameMutation
| IRemoveCustomerProductNameMutation;
| IRemoveCustomerProductNameMutation
| IUpsellAddToCartMutation;
const pathPrefix = window.PW.config.i18n.pathPrefix;
@@ -400,21 +398,26 @@ export const cartApi = createApi({
}),
addToCart: builder.mutation<ICartResponse, IAddItemToCartMutation>({
query: ({ path, body, forCheckout }) => {
if (path.endsWith('/cart/addUpsellItem')) {
// temporary fix for upsell items that can be added both in cart and outside
return {
url: path,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body ?? {}),
};
}
if (!body && !forCheckout) {
return { url: path, method: 'POST', body: '' };
}
const formData = new FormData();
for (const key in body) {
formData.append(key, body[key]);
for (const [key, value] of Object.entries(body)) {
formData.append(key, value);
}
if (forCheckout) {
formData.append('forCheckout', 'true');
}
return {
url: path,
method: 'POST',
body: formData,
};
return { url: path, method: 'POST', body: formData };
},
transformResponse: (response: ICartResponse) => {
window.PW.ga4dataLayer.push(response.ga4_event_data);