<?php
namespace App\Controller\Api;
use App\Entity\EndUser;
use App\Entity\Order;
use App\Entity\Product;
use App\Entity\ProductVariant;
use App\Helper\Order\OrderHelper;
use App\Service\DomainManager;
use App\Service\EndUserManager;
use App\Service\EventProvider\EventProvider;
use App\Service\EventProvider\FacebookProvider;
use App\Service\EventProviderManager;
use App\Service\ProductManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
class ApiEventController extends AbstractController
{
public function __construct(
private readonly EventProviderManager $eventProviderManager,
private readonly EntityManagerInterface $em,
private readonly ProductManager $productManager,
private readonly EndUserManager $endUserManager,
private readonly SessionInterface $session,
private readonly DomainManager $domainManager,
)
{}
/**
* @Route("/{_locale}/api/event/add_to_cart", name="api_event_add_to_cart", methods={"POST"})
* @param Request $request
* @return JsonResponse
*/
public function addToCartAction(Request $request): JsonResponse
{
try {
if (!$request->request->has('product_id') || !$request->request->has('variant_id')) {
return new JsonResponse(['status' => 'error', 'message' => 'Missing required fields'], 400);
}
$product = $this->em->getRepository(Product::class)->find($request->request->get('product_id'));
if (!$product) {
return new JsonResponse(['status' => 'error', 'message' => 'Product not found'], 404);
}
$productVariant = $this->productManager->getProductVariant($product, $request->request->get('variant_id'));
$endUser = null;
if($request->request->has('email') && !empty($request->request->get('email'))) {
$endUser = $this->endUserManager->findUserByEmail($request->request->get('email'));
}
// $endUser = new EndUser();
// if (!$endUser) {
// $endUser = new EndUser();
// $endUser
// ->setEmail($request->request->get('email'))
// ->setFirstName($request->request->get('first_name', ''))
// ->setLastName($request->request->get('last_name', ''));
//
// }
$actionURL = $request->request->get('action_url');
$this->eventProviderManager->sendEvent(
EventProvider::EVENT_ADD_TO_CART,
$productVariant,
null,
null,
false,
$actionURL
);
return new JsonResponse(['status' => 'success', 'message' => 'Checkout initiated successfully']);
} catch (\Exception $e) {
return new JsonResponse(['status' => 'error', 'message' => $e->getMessage()], 400);
}
}
/**
* @Route("/{_locale}/api/event/initiate_checkout", name="api_event_initiate_checkout", methods={"POST"})
* @param Request $request
* @return JsonResponse
*/
public function initiateCheckoutAction(Request $request): JsonResponse
{
try {
if (!$request->request->has('product_id') || !$request->request->has('variant_id') || !$request->request->get('email')) {
return new JsonResponse(['status' => 'error', 'message' => 'Missing required fields'], 400);
}
$product = $this->em->getRepository(Product::class)->find($request->request->get('product_id'));
if (!$product) {
return new JsonResponse(['status' => 'error', 'message' => 'Product not found'], 404);
}
$productVariant = $this->productManager->getProductVariant($product, $request->request->get('variant_id'));
$endUser = null;
if($request->request->has('email') && !empty($request->request->get('email'))) {
$endUser = $this->endUserManager->findUserByEmail($request->request->get('email'));
}
if (!$endUser) {
$endUser = new EndUser();
$endUser
->setEmail($request->request->get('email'))
->setFirstName($request->request->get('first_name', ''))
->setLastName($request->request->get('last_name', ''))
->setlocale($request->getLocale() ?? 'en');
}
$actionURL = $request->request->get('action_url');
$this->eventProviderManager->sendEvent(
EventProvider::EVENT_INITIATE_CHECKOUT,
$productVariant,
$endUser,
null,
false,
$actionURL
);
return new JsonResponse(['status' => 'success', 'message' => 'Checkout initiated successfully']);
} catch (\Exception $e) {
return new JsonResponse(['status' => 'error', 'message' => $e->getMessage()], 400);
}
}
/**
* @Route("/{_locale}/api/event/getData", name="api_event_get_data", methods={"POST"})
* @param Request $request
* @return JsonResponse
*/
public function getDataAction(Request $request): JsonResponse
{
try {
$productVariantParam = $request->request->get('variant_id', null);
$productVariant = $this->em->getRepository(ProductVariant::class)->find($productVariantParam);
if (!$productVariantParam) {
return new JsonResponse(['status' => 'error', 'message' => 'Missing required fields'], 400);
}
if (!$this->validateForFacebook()) {
return new JsonResponse(null, 204);
}
$product = $productVariant->getProduct();
$currency = $product->getDefaultCurrency();
$totalPrice = $productVariant->getTotalPrice();
$eventID = $request->cookies->get('eventID') ?? '';
$data = [
'eventID' => $request->cookies->get('eventID') ?? '',
'data' => [
'content_type' => 'product',
'currency' => strtoupper($currency),
'content_ids' => [$product->getProductDetail()->getSku()],
]
];
$contents[] = [
'id' => $product->getProductDetail()->getSku(),
'quantity' => $productVariant->getQuantity(),
'item_price' => $productVariant->getUnitPrice(),
'title' => $product->getProductDetail()->getTitle(),
'category' => 'main',
];
$sessionKey = OrderHelper::cartKey($product, ApiCheckoutController::SESSION_UPSELL_KEY);
if ($this->session->has($sessionKey)) {
$upsells = $this->session->get($sessionKey);
foreach ($upsells as $upsell) {
$productUpsell = $this->productManager->findProductById($upsell['productId']);
$productUpsellVariant = $productUpsell->getVariants()->first();
if (!$productUpsell || !$productUpsellVariant) {
continue;
}
$totalPrice += $productUpsellVariant->getTotalPrice();
$contents[] = [
'id' => $productUpsell->getProductDetail()->getSku(),
'quantity' => $productUpsellVariant->getQuantity(),
'item_price' => $productUpsellVariant->getUnitPrice(),
'title' => $productUpsell->getProductDetail()->getTitle(),
'category' => 'upsell',
];
}
}
$data['data']['value'] = round($totalPrice, 2);
$data['data']['contents'] = $contents;
return new JsonResponse(['status' => 'success', 'data' => $data]);
} catch (\Exception $e) {
return new JsonResponse(['status' => 'error', 'message' => $e->getMessage()], 400);
}
}
/**
* @Route("/{_locale}/api/event/getDataByOrder", name="api_event_get_data_by_order", methods={"POST"})
* @param Request $request
* @return JsonResponse
*/
public function getDataByOrderAction(Request $request): JsonResponse
{
try {
$orderId = $request->request->get('order_id', null);
$order = $this->em->getRepository(Order::class)->find($orderId);
if (!$order) {
return new JsonResponse(['status' => 'error', 'message' => 'Order not found'], 404);
}
if (!$this->validateForFacebook($order)) {
return new JsonResponse(null, 204);
}
$eventID = $request->cookies->get('eventID') ?? '';
$isPostUpsell = OrderHelper::getOrderSuffix($order->getOrderNumber());
$prefix = 'p';
if ($isPostUpsell) {
// $prefix .= '-upsell' . $isPostUpsell;
return new JsonResponse(['status' => 'error', 'message' => 'postUpsell'], 200);
}
$data = [
'eventID' => $prefix . '-' . $eventID,
'data' => [
'content_type' => 'product',
'currency' => strtoupper($order->getCurrency()),
'value' => round($order->getTotalPrice(), 2),
]
];
$contents = $content_ids = [];
foreach ($order->getProducts() as $orderItem) {
$product = $orderItem->getProduct();
$content_ids[] = $product->getProductDetail()->getSku();
$contents[] = [
'id' => $product->getProductDetail()->getSku(),
'quantity' => $orderItem->getQuantity(),
'item_price' => $orderItem->getPrice(),
'title' => $product->getProductDetail()->getTitle(),
'category' => $product->isMainProduct() ? 'main' : 'upsell',
];
}
$data['data']['contents'] = $contents;
$data['data']['content_ids'] = $content_ids;
return new JsonResponse(['status' => 'success', 'data' => $data]);
} catch (\Exception $e) {
return new JsonResponse(['status' => 'error', 'message' => $e->getMessage()], 400);
}
}
public function validateForFacebook(?Order $order = null): bool
{
$domain = $this->domainManager->getCurrentDomain();
$tracker = $this->eventProviderManager->detectTrackerFromRequest();
$trackersEventProviders = $domain->getDefaultEventProviders() ?? [];
$trackersEventProviders = $tracker ? $tracker->getEventProviders() : $trackersEventProviders;
if ($order) {
$trackersEventProviders = $order->getTracker() ? $order->getTracker()->getEventProviders() : $trackersEventProviders;
}
return !empty($trackersEventProviders)
&& in_array(FacebookProvider::PROVIDER_NAME, $trackersEventProviders);
}
}