<?php
/**
* Elements DeMI
*
* This source file is available under the elements DeMI license version 1
*
* @copyright Copyright (c) elements.at New Media Solutions GmbH (https://www.elements.at/)
* @license elements DeMI Lizenz Version 1 (https://www.elements.at/de/demi-lizenz)
*/
namespace Elements\Bundle\DemiFrontendBundle\Controller;
use Elements\Bundle\CmsToolsBundle\Tool\Helper\ElementsCustomDateFormat;
use Elements\Bundle\DemiFrontendBundle\Service\AccommodationResultSet;
use Elements\Bundle\DemiFrontendBundle\Service\AdditionalService;
use Elements\Bundle\DemiFrontendBundle\Service\CartItemInfo;
use Elements\Bundle\DemiFrontendBundle\Service\Checkout\PrePaymentHandler;
use Elements\Demi\Frontend\Service\Configuration;
use Elements\Bundle\DemiFrontendBundle\Service\DemiUrl;
use Elements\Bundle\DemiFrontendBundle\Service\EcommerceHelper;
use Elements\Bundle\DemiFrontendBundle\Service\Redirect;
use Elements\Bundle\DemiFrontendBundle\Service\SearchFrontend;
use Elements\Bundle\DemiFrontendBundle\Service\Ticketing;
use Elements\Bundle\DemiFrontendBundle\Service\Validation;
use Elements\Bundle\TicketingBundle\Model\OrderItem;
use Elements\Bundle\TicketingBundle\OrderManager;
use Elements\Demi\AbstractObject;
use Elements\Demi\Accommodation\Search\Parameter;
use Elements\Demi\AdditionalService\Search\Listing;
use Elements\Demi\AdditionalService\Search\Parameter\Line;
use Elements\Demi\Deskline\Config;
use Elements\Demi\Deskline\Constant\DescriptionInterface;
use Elements\Demi\Deskline\Constant\ShoppingCart\DurationTypeInterface;
use Elements\Demi\Deskline\Constant\ShoppingCart\ItemTypeInterface;
use Elements\Demi\Deskline\DSI\Service\DynamicService;
use Elements\Demi\Deskline\Package\Search\Listing\Live;
use Elements\Demi\Deskline\Service\Search\CancellationInformation;
use Elements\Demi\EcommerceFramework\Checkout\SessionCart;
use Elements\Demi\Info\CartItemInfoHolder;
use Elements\Demi\Info\DestinationPackageCartItemInfoHolder;
use Elements\Demi\Info\DestinationPackageTicketSubCartItemInfoHolder;
use Elements\Demi\Info\TicketCartItemInfoHolder;
use Elements\Demi\Model\AccommodationProduct;
use Elements\Demi\Model\AdditionalProduct;
use Elements\Demi\Model\HousePackageMaster;
use Elements\Demi\Model\PackageSection;
use Elements\Demi\Model\ShopItem;
use Elements\Demi\Package\Search\Detail\ResultSet\Package;
use Exception;
use HttpEncodingException;
use JetBrains\PhpStorm\Pure;
use Pimcore\Bundle\AdminBundle\HttpFoundation\JsonResponse;
use Pimcore\Bundle\EcommerceFrameworkBundle\CartManager\CartInterface;
use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
use Pimcore\Bundle\EcommerceFrameworkBundle\Tracking\TrackingManager;
use Pimcore\Log\ApplicationLogger;
use Pimcore\Model\DataObject\DemiAccommodationProduct;
use Pimcore\Model\DataObject\DemiAdditionalProduct;
use Pimcore\Model\DataObject\DemiPackageSection;
use Pimcore\Tool\DeviceDetector;
use Pimcore\Translation\Translator;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class CartController extends BookingController
{
/**
* @var SearchFrontend|null
*/
protected $searchFrontend = null;
/**
* @var Listing|null
*/
protected $additionalServiceListingLive = null;
/**
* @var Listing|null
*/
protected $additionalServiceListingLocal = null;
/**
* @var AccommodationResultSet|null
*/
protected $accommodationResultSet = null;
/**
* @var DemiUrl|null
*/
protected $demiUrl = null;
/**
* @var null|Translator
*/
protected $translator = null;
/**
* @var null|TrackingManager
*/
protected $trackingManager = null;
/**
* @var Ticketing|null
*/
protected $ticketing = null;
/**
* @var OrderManager|null
*/
protected $orderManager = null;
/**
* @var AdditionalService
*/
protected $additionalServiceCartHandler = null;
/**
* @var PrePaymentHandler
*/
protected $prePaymentHandler = null;
public function __construct(
EcommerceHelper $ecommerceHelper,
Validation $validationService,
Redirect $redirectService,
CartItemInfo $cartItemInfoService,
Configuration $configuration,
SearchFrontend $searchFrontend,
Listing $additionalServiceListingLive,
Listing $additionalServiceListingLocal,
AccommodationResultSet $accommodationResultSet,
DemiUrl $demiUrl,
Translator $translator,
TrackingManager $trackingManager,
AdditionalService $additionalServiceCartHandler,
Ticketing $ticketing,
OrderManager $orderManager = null,
PrePaymentHandler $prePaymentHandler,
protected ContainerBagInterface $parameterBag,
protected \Elements\Demi\Deskline\Accommodation\Search\Service\Vacancies\Live $vacanciesLive,
protected \Elements\Demi\Deskline\Package\Search\Service\Live $searchServiceLive,
)
{
parent::__construct($ecommerceHelper, $validationService, $redirectService, $cartItemInfoService,
$configuration);
$this->searchFrontend = $searchFrontend;
$this->additionalServiceListingLive = $additionalServiceListingLive;
$this->additionalServiceListingLocal = $additionalServiceListingLocal;
$this->accommodationResultSet = $accommodationResultSet;
$this->demiUrl = $demiUrl;
$this->translator = $translator;
$this->trackingManager = $trackingManager;
$this->additionalServiceCartHandler = $additionalServiceCartHandler;
$this->ticketing = $ticketing;
$this->orderManager = $orderManager;
$this->prePaymentHandler = $prePaymentHandler;
}
public function step1Action(Request $request): RedirectResponse|Response
{
$cart = $this->ecommerceHelper->getCart();
// if items in cart, but destination package - redirect to packagestep1
if (count($cart->getItems()) > 0 && count($cart->getDestinationPackageItems()) > 0) {
return $this->redirect($this->demiUrl->getCheckoutUrl('cart', 'packagestep1',
['_locale' => $request->getLocale()]));
}
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
Factory::getInstance()->getEnvironment()->removeCustomItem('demi_cartName');
$env = Factory::getInstance()->getEnvironment();
$error = $this->ecommerceHelper->getError();
$this->ecommerceHelper->setError('');
if (is_array($cart->getAccommodationItems()) && count($cart->getAccommodationItems()) > 0) {
$accommodationItems = $cart->getAccommodationItems();
$isOrgOffer = reset($accommodationItems)->getCartItemInfo()->getIsOrganisationOffer();
if ($isOrgOffer) {
$env = Factory::getInstance()->getEnvironment();
$env->clearEnvironment();
$this->ecommerceHelper->clear();
if ($error) {
$this->ecommerceHelper->setError($error);
}
}
}
$originator = $this->document->getProperty('demi_customOriginator');
$this->handleRecommendedServices($cart, $originator);
if ($request->get('clear') || $request->get('add')) {
$error = null;
$env->removeCustomItem('deskline_bookableOnRequest');
$env->save();
$tvbId = $request->get('tvbPackage');
if ($request->get('clear')) {
$cart = $this->ecommerceHelper->clear();
}
if (!$this->validationService->checkRequestForCartParameters($request)) {
throw new Exception('some parameters are missing. cannot add product to cart');
}
$bookableOnRequest = false;
foreach ($request->get('roomRow') as $key => $roomRow) {
$accommodationLiveAdapter = $tvbId ? $this->searchServiceLive : $this->vacanciesLive;
$id = $request->get('productId')[$key];
$mealCode = $request->get('mealCode')[$key];
$units = $request->get('count')[$key];
$searchParam = $tvbId ? $this->searchFrontend->getPackageSearchParam() : $this->searchFrontend->getSearchParam($roomRow,
true);
$searchParam->setOmitExtraFeesInMinPrice(false);
$searchParam->setOmitVisitorTaxMinPrice(false);
if ($searchParam instanceof Parameter) {
$searchParam->setIsCorridor(false);
}
$tmproomrows = $searchParam->getRoomrows();
$tmproomrows[0]->setUnits($units);
$searchParam->setRoomrows($tmproomrows);
$searchParam->setMealTypeId($mealCode);
$tvbId ? $accommodationLiveAdapter->setParams($searchParam) : $accommodationLiveAdapter->setSearchParameter($searchParam);
$resultSetProduct = $this->accommodationResultSet->getProductByProductIdAndMealType($accommodationLiveAdapter,
$id, $mealCode, true);
if ($resultSetProduct === null) {
throw new Exception("Serviceprovider not actually available. Return");
}
$cartItemInfo = $this->cartItemInfoService->fillPriceInfoFromResultSetProduct(new CartItemInfoHolder(),
$resultSetProduct);
$cartItemInfo = $this->cartItemInfoService->fillOtherFromRequest($cartItemInfo, $request, $roomRow,
$key);
$bookableOnRequest = $resultSetProduct->getBookableOnRequest();
$product = AccommodationProduct::getById($id);
$cart = $this->ecommerceHelper->addProductToCart($units, $product, $cartItemInfo, $cart);
$this->trackingManager->trackCartProductActionAdd($cart, $product, $units);
}
$env->setCustomItem('demi_hpmId', $request->get('hpmId'));
$env->setCustomItem('deskline_bookableOnRequest', $bookableOnRequest);
$env->save();
}
if ($cart->getLastAddedId()) {
$viewParams['lastAddedId'] = $cart->getLastAddedId();
$cart->setLastAddedId(0);
$cart->save();
}
if ($cart->getLastRemovedId()) {
$viewParams['lastRemovedId'] = $cart->getLastRemovedId();
$cart->setLastRemovedId(0);
$cart->save();
}
$acco = $this->ecommerceHelper->getAccoFromCart($cart);
$additionalProvider = $this->ecommerceHelper->getAddProviderFromCart($cart);
if (!$this->validationService->validateBookableOnRequestCart($cart)) {
throw new Exception('a cart with a product that is bookable on request cannot contain non bookable on request products');
}
$hpmId = $env->getCustomItem('demi_hpmId');
if ($acco !== null) {
$additionalServiceParams = $this->searchFrontend->getAdditionalServiceParam($acco, $cart);
$this->additionalServiceListingLocal->setParameter($additionalServiceParams);
$this->additionalServiceListingLocal->load();
$this->additionalServiceListingLocal = $this->additionalServiceCartHandler->modifyListingForCart($this->additionalServiceListingLocal, $cart);
$viewParams['additionalServiceItems'] = $this->additionalServiceListingLocal;
}
$arrivalDate = $acco === null && $additionalProvider === null ? null : $cart->getArrivalDate();
$departureDate = $acco === null && $additionalProvider === null ? null : $cart->getDepartureDate();
$bookOnRequest = $env->getCustomItem('deskline_bookableOnRequest');
$viewParams['isBookOnRequest'] = $bookOnRequest;
//viewpoint is only important for mobile
$viewpoint = ($acco !== null && !$bookOnRequest && $this->additionalServiceListingLocal && $this->additionalServiceListingLocal->count() > 0 && $request->get('viewpoint') != 2) ? 1 : 2;
$viewParams['viewpoint'] = $viewpoint;
if ($error) {
//in case of error skip display of any additional offers
$viewParams['viewpoint'] = 2;
}
$viewParams['acco'] = $acco;
$viewParams['additionalProvider'] = $additionalProvider;
$viewParams['cart'] = $cart;
$viewParams['isPackage'] = !empty($hpmId);
$viewParams['pId'] = !empty($hpmId) ? $hpmId : null;
$viewParams['pName'] = !empty($hpmId) ? HousePackageMaster::getById($hpmId)->getName() : null;
$viewParams['searchParam'] = $this->searchFrontend->getSearchParam(null, true);
$viewParams['error'] = $error ? 'demi.booking.error.' . $error : null;
$viewParams['emptyCart'] = $acco === null && $additionalProvider === null;
$hasTickets = !empty($this->ticketing->getDummyTickets($arrivalDate, $departureDate,
$acco, $cart)) && empty($cart->getDestinationPackageItems());
$viewParams['hasTickets'] = $hasTickets;
$viewParams['isMerchandise'] = $env->getCustomItem('demi_isMerchandiseCart');
$viewParams['hasAdditionalPrePaymentStep'] = $this->prePaymentHandler->hasAdditionalPrePaymentStep();
if ($this->parameterBag->get('elements_demi.checkout') === 'long') {
$viewParams['checkoutSteps'] = 'long';
} else {
$viewParams['checkoutSteps'] = 'short';
}
if (!$request->get('viewpoint') && !empty($cart->getItems()) && $hasTickets && DeviceDetector::getInstance()->isPhone() && $this->additionalServiceListingLocal->getParameter() && $this->additionalServiceListingLocal->count() <= 0) {
//don't skip the tickets just because viewport is set to 2 already
return $this->redirect($this->demiUrl->getCheckoutUrl('ticket', 'overview',
['_locale' => $request->getLocale()]));
}
if (!$this->configuration->getNeverSkipCart() && (!$request->get('viewpoint') || $request->get('viewpoint') != 2) && !empty($cart->getItems()) && $this->additionalServiceListingLocal->getParameter() &&
$this->additionalServiceListingLocal->count() <= 0 && $request->get('clear')) {
return $this->redirect($this->demiUrl->getCheckoutUrl($hasTickets ? 'ticket' : 'checkout', $hasTickets ? 'overview' : 'step2',
['_locale' => $request->getLocale()], 'customer'));
}
$deviceDetector = DeviceDetector::getInstance();
$device = $deviceDetector->isPhone() ? 'mobile' : 'desktop';
return $this->renderTemplate('@ElementsDemiFrontend/Cart/step1.' . $device . '.html.twig', $viewParams);
}
public function packagestep1Action(Request $request): Response
{
$cart = $this->ecommerceHelper->getCart();
// if items in cart, but no destination packages - redirect to step1
if (count($cart->getItems()) > 0 && count($cart->getDestinationPackageItems()) == 0) {
return $this->redirect($this->demiUrl->getCheckoutUrl('cart', 'step1',
['_locale' => $request->getLocale()]));
}
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
Factory::getInstance()->getEnvironment()->removeCustomItem('demi_cartName');
$env = Factory::getInstance()->getEnvironment();
$error = $this->ecommerceHelper->getError();
$this->ecommerceHelper->setError('');
if (is_array($cart->getAccommodationItems()) && count($cart->getAccommodationItems()) > 0) {
$accommodationItems = $cart->getAccommodationItems();
$isOrgOffer = reset($accommodationItems)->getCartItemInfo()->getIsOrganisationOffer();
if ($isOrgOffer) {
$env = Factory::getInstance()->getEnvironment();
$env->clearEnvironment();
$this->ecommerceHelper->clear();
if ($error) {
$this->ecommerceHelper->setError($error);
}
}
}
$tvbId = $request->get('tvbPackage');
if (!$tvbId) {
$cartItems = $cart->getItems();
$cartItem = reset($cartItems);
$destinationPackageItems = $cart->getDestinationPackageItems();
$tvbId = $cart->getDestinationPackageItems() && count($cart->getDestinationPackageItems()) > 0 ? reset($destinationPackageItems)->getProduct()->getId() : null;
$tvbPackage = $cart->getDestinationPackageItems() && count($cart->getDestinationPackageItems()) > 0 ? reset($destinationPackageItems)->getProduct() : null;
} else {
$tvbPackage = AbstractObject::getById($tvbId) ?: null;
}
$error = null;
$env->removeCustomItem('deskline_bookableOnRequest');
$env->save();
if ($request->get('clear') || $request->get('add')) {
if ($request->get('clear')) {
$cart = $this->ecommerceHelper->clear();
}
if (!$this->validationService->checkRequestForCartParameters($request) && $tvbPackage->hasAccommodationSection()) {
throw new Exception('some parameters are missing. cannot add product to cart');
}
}
Config::setClientKeyOverrideFromObject($tvbPackage);
$roomRows = $request->get('roomRow');
if (!$roomRows) {
$roomRows[0] = 0;
}
$accommodationLiveAdapter = $tvbId ? $this->searchServiceLive : $this->vacanciesLive;
foreach ($roomRows as $key => $roomRow) {
if ($request->get('clear') || $request->get('add')) {
$searchParam = $this->searchFrontend->getPackageSearchParam();
$searchParam->setOmitExtraFeesInMinPrice(false);
$searchParam->setOmitVisitorTaxMinPrice(false);
} else {
if (!$tvbId) {
//empty package cart
break;
}
$searchParam = $this->searchFrontend->getPackageSearchParam(null, false, $tvbId);
$searchParam->setPackageId($tvbId);
$searchParam = $this->cartItemInfoService->fillPackageSearchParamsFromCartItemInfo($cartItem->getCartItemInfo(),
$searchParam);
}
$tvbId ? $accommodationLiveAdapter->setParams($searchParam) : $accommodationLiveAdapter->setSearchParameter($searchParam);
$id = $request->get('productId')[$key];
$mealCode = $request->get('mealCode')[$key];
$units = $request->get('count')[$key];
$packageResultSet = Package::getById($tvbId, $accommodationLiveAdapter);
if ($id && $mealCode) {
$packageCategory = $packageResultSet->getCategoryForProductAndMealCode($id, $mealCode);
$searchParam->setMealTypeId($mealCode);
} elseif ($cartItem) {
$packageCategory = $cartItem->getCartItemInfo()->getPackageCategory();
} else {
//fallback for packages without acco, just take the first category
$resultsetCategory = $packageResultSet->getCategory()[0];
$packageCategory = $resultsetCategory->getObject();
}
if ($request->get('clear') || $request->get('add')) {
$listing = new Live($packageResultSet, $searchParam);
$test = $listing->getItems(0, 1000);
foreach ($test as $resultSetAcco) {
$acco = AccommodationProduct::getById($id)->getParent()->getParent();
if ($resultSetAcco->getAccommodationId() == $acco->getId()) {
break;
}
}
if ($resultSetAcco) {
foreach ($resultSetAcco->getProducts() as $resultSetProduct) {
if ($resultSetProduct->getProductId() == $id) {
break;
}
}
}
if ($resultSetProduct) {
$cartItemInfo = $this->cartItemInfoService->fillPriceInfoFromResultSetProduct(new DestinationPackageCartItemInfoHolder(),
$resultSetProduct);
} else {
//tvb package without acco
$cartItemInfo = new DestinationPackageCartItemInfoHolder();
$cartItemInfo->setCurrency(Factory::getInstance()->getEnvironment()->getDefaultCurrency()->getShortName());
}
$cartItemInfo = $this->cartItemInfoService->fillOtherFromRequest($cartItemInfo, $request, $roomRow,
$key);
$env->save();
} else {
foreach ($cartItem->getSubItems() as $subItem) {
if ($subItem->getProduct() instanceof AccommodationProduct) {
$acco = $subItem->getProduct()->getParent()->getParent();
}
}
}
$product = \Elements\Demi\Model\Package::getById($tvbId);
if ($request->get('clear') || $request->get('add')) {
//add package to cart
$cart = $this->ecommerceHelper->addProductToCart($units, $product, $cartItemInfo, $cart, true,
[]);
$cartItemInfo = $this->ecommerceHelper->handlePackageCategoryPrices($product, $cartItemInfo, $packageCategory, $packageResultSet);
$this->trackingManager->trackCartProductActionAdd($cart, $product, $units);
}
//add subproducts to cart
$accommodationProduct = AccommodationProduct::getById($id);
if ($accommodationProduct && ($request->get('clear') || $request->get('add'))) {
if (!$packageCategory) {
throw new NotFoundHttpException('Category for meal code id ' . $mealCode . ' not found');
}
$subProducts[] = $this->ecommerceHelper->addSubProductToCart(1, $packageResultSet->getObject(),
$accommodationProduct, $packageResultSet->getAccommodationSection($packageCategory),
$packageResultSet, $cart, $packageCategory);
//reset the price to that of acco product, prices of additionals will be added later.
if($product->getPackagePrice() === 'Dynamic'){
$cartItemInfo->setPrice($subProducts[0]->getPrice());
$cartItemInfo->setTotalPrice($subProducts[0]->getPrice());
}
}
$mandatoryProductsAlreadyInCart = [];
foreach ($packageResultSet->getSectionData() as $section) {
if ($section->getProductType() == ItemTypeInterface::ADDITIONAL_SERVICE && $section->getIsMandatory() && $section->getObject()->getProducts() && count($section->getObject()->getProducts()->getItems()) == 1) {
//exactly one product in mandatory section and preselected -> add to cart automatically if preselect activated
$amount = 1;
if ($section->getUnitType() === 'PerPerson') {
$amount = (int)$request->get('a' . $roomRow) + (int)$request->get('c' . $roomRow);
}
$additionalProducts = $section->getObject()->getProducts();
foreach ($additionalProducts->getItems() as $additionalProduct) {
if ($prod = $additionalProduct->getProduct()) {
//check ist preselected or not relevant for totalprice and mandatory - in both cases we add it to shopping cart
if ($additionalProduct->getPreselected() || (!$section->getObject()->getSelectionRulesAddPrice() && $section->getIsMandatory())) {
if ($request->get('clear') || $request->get('add')) {
$service = $prod->getParent();
$hasMandatoryCheckoutQuestions = false;
if ($service instanceof \Elements\Demi\Model\AdditionalService && $service->getCheckoutQuestions()) {
foreach ($service->getCheckoutQuestions()->getItems() as $checkoutQuestion) {
if ($checkoutQuestion->getAnswerMandatory()) {
//skip automatic adding to cart - mandatory questions have to be answered
$hasMandatoryCheckoutQuestions = true;
break;
}
}
}
if ($hasMandatoryCheckoutQuestions) {
continue;
}
$newSubProduct = $this->ecommerceHelper->addSubProductToCart($amount, $packageResultSet->getObject(), $prod, $section->getObject(), $packageResultSet, $cart, $packageCategory, $cartItemInfo->getChildrenAges());
//add price to overall price
$cartItemInfo->setPrice($cartItemInfo->getPrice() + $newSubProduct->getPrice());
$cartItemInfo->setTotalPrice($cartItemInfo->getPrice() + $newSubProduct->getPrice());
$subProducts[] = $newSubProduct;
if (!$resultSetProduct) {
//hack for package without acco - cartitemInfo was newly created in line 420, set price to that instance
$cartItemInfo->setTotalPrice($cartItemInfo->getTotalPrice() + $newSubProduct->getPrice());
}
if (!$cartItemInfo->getDbCode()) {
$cartItemInfo->setDbCode($prod->getParent()->getParent()->getDbcode());
}
if (!$cartItemInfo->getPackageCategory()) {
$cartItemInfo->setPackageCategory($packageCategory);
}
}
}
}
}
}
}
if ($request->get('clear') || $request->get('add')) {
$cartItemInfo = $this->cartItemInfoService->fillDestinationPackageInfosFromCart($cartItemInfo, $cart,
$packageResultSet);
$destinationPackageItems = $cart->getDestinationPackageItems();
$existingItem = reset($destinationPackageItems);
$existingItem->setCartItemInfo($cartItemInfo);
if ($this->orderManager && $this->orderManager->getType() === 'Dta') {
foreach ($existingItem->getSubItems() as $subItem) {
$isSkiticket = $subItem->getProduct()->getDemiExtension()
&& $subItem->getProduct()->getDemiExtension()->getDesklineDummyProduct()
&& $subItem->getProduct()->getDemiExtension()->getDesklineDummyProduct()->getIsSkiticket();
if ($isSkiticket
&& $subItem->getCartItemInfo() instanceof DestinationPackageTicketSubCartItemInfoHolder
&& !$subItem->getCartItemInfo()->getInterfaceTicketId()) {
//autodetect skiticket because it was added as mandatory item
$dummyExtension = $subItem->getProduct()->getDemiExtension()->getDesklineDummyProduct();
//use first possible duration value from service - the user did not get the option to select it
$possibleDurationValues = $subItem->getProduct()->getParent()->getDurationValues();
$subItem->getCartItemInfo()->setDurationValue(is_array($possibleDurationValues) && $possibleDurationValues[0] ? $possibleDurationValues[0][0] : null);
if (!$subItem->getCartItemInfo()->getDurationValue()) {
throw new Exception('can not auto detect ticket duration value');
}
$subItem->getCartItemInfo()->setDurationValue(DurationTypeInterface::DAY);
if (count($dummyExtension->getDtaConsumerCategory()) > 1) {
throw new Exception('Can not detect consumer category for skiticket mandatory product - multiple consumer categories assigned');
}
$consumerCategory = !empty($dummyExtension->getDtaConsumerCategory()) ? $dummyExtension->getDtaConsumerCategory()[0]->getUuid() : null;
$detectedTickets = [];
foreach ($dummyExtension->getTickets() as $ticket) {
if ($ticket->getValidityCategory()->getValidityValue() == $subItem->getCartItemInfo()->getDurationValue()) {
$detectedTickets[$ticket->getUuid()] = $ticket;
}
}
if (count($detectedTickets) > 1 || count($detectedTickets) == 0) {
throw new Exception('Can not autodetect ticket for mandatory product - zero or multiple options found');
}
$ticketArray = array_keys($detectedTickets);
$subItem->getCartItemInfo()->setInterfaceTicketId(reset($ticketArray));
$subItem->getCartItemInfo()->setInterfaceTicketTypeId($consumerCategory);
}
}
}
}
}
$additionalProvider = $this->ecommerceHelper->getAddProviderFromCart($cart);
if (!$this->validationService->validateBookableOnRequestCart($cart)) {
throw new Exception('a cart with a product that is bookable on request cannot contain non bookable on request products');
}
$productIds = [];
if ($packageResultSet) {
foreach ($packageResultSet->getSectionData() as $section) {
if ($section->getProductType() == ItemTypeInterface::ADDITIONAL_SERVICE) {
$additionalProducts = $section->getObject()->getProducts();
if ($additionalProducts) {
foreach ($additionalProducts->getItems() as $additionalProduct) {
if ($additionalProduct->getProduct()) {
$sectionObject = DemiPackageSection::getById($section->getSectionId());
if ($sectionObject && $sectionObject->getAssignedProducts() === 'perCategory') {
if (!$additionalProduct->getCategory() || ($packageCategory && $additionalProduct->getCategory()
&& $additionalProduct->getCategory()->getFid() == $packageCategory->getFid())) {
$productIds[] = $additionalProduct->getProduct()->getId();
}
} else {
$productIds[] = $additionalProduct->getProduct()->getId();
}
}
}
}
}
}
}
if (count($productIds) > 0) {
$additionalServiceParams = $this->searchFrontend->getAdditionalServiceParam($acco, $cart);
$additionalServiceParams->setExcludeServicesOfAdditionalServiceProviders(false);
$additionalServiceParams->setIgnorePackageOnly(true);
$additionalServiceParams->setIgnoreAvailabilities(true);
$additionalServiceParams->setProductIds($productIds);
$this->additionalServiceListingLocal->setParameter($additionalServiceParams);
$this->additionalServiceListingLocal->load();
$viewParams['additionalServiceItems'] = $this->additionalServiceListingLocal;
}
$viewParams['packageResultSet'] = $packageResultSet;
if (!$accommodationProduct && $cartItem) {
foreach ($cartItem->getSubItems() as $subItem) {
if ($subItem->getProduct() instanceof AccommodationProduct) {
$accommodationProduct = $subItem->getProduct();
}
}
}
if ($packageResultSet && $accommodationProduct) {
$addNightPrice = $packageResultSet->getPriceForAdditionalNight($accommodationProduct,
$packageCategory, $packageResultSet->getAccommodationSection($packageCategory));
$viewParams['addNightPrice'] = (float)$addNightPrice > 0 ? $addNightPrice : 0;
$viewParams['accommodationProduct'] = $accommodationProduct;
}
$viewParams['packageCategory'] = $packageCategory;
$viewParams['isBookOnRequest'] = $env->getCustomItem('deskline_bookableOnRequest');
//viewpoint is only relevant for mobile view
$viewParams['viewpoint'] = count($productIds) > 0 && $packageResultSet && $this->additionalServiceListingLocal && $this->additionalServiceListingLocal->count() > 0 && $request->get('viewpoint') != 2 ? 1 : 2;
if ($error) {
//in case of error skip display of any additional offers
$viewParams['viewpoint'] = 2;
}
$destinationPackageItems = $cart->getDestinationPackageItems();
$existingItem = reset($destinationPackageItems);
if ($packageResultSet && $existingItem) {
$allSectionsSelected = true;
foreach ($packageResultSet->getSectionData() as $section) {
$sectionSelected = false;
foreach ($existingItem->getSubItems() as $subItem) {
if ($subItem->getCartItemInfo()->getSection()->getId() == $section->getSectionId()) {
$sectionSelected = true;
}
}
if (!$sectionSelected) {
$allSectionsSelected = false;
break;
}
}
$viewParams['allSectionsSelected'] = $allSectionsSelected;
if ($allSectionsSelected) {
$viewParams['viewpoint'] = 2;
}
}
$viewParams['acco'] = $acco;
$viewParams['additionalProvider'] = $additionalProvider;
$viewParams['cart'] = $cart;
$viewParams['isPackage'] = !empty($hpmId) || !empty($tvbId);
$pid = !empty($hpmId) ? $hpmId : null;
$viewParams['pId'] = $pid ?: (!empty($tvbId) ? $tvbId : null);
$pname = !empty($hpmId) ? HousePackageMaster::getById($hpmId)->getName() : null;
$viewParams['pName'] = $pname ?: ($tvbPackage ? $tvbPackage->getName() : null);
$viewParams['searchParam'] = $this->searchFrontend->getSearchParam(null, true);
$viewParams['error'] = $error ? 'demi.booking.error.' . $error : null;
$viewParams['emptyCart'] = $acco === null && $additionalProvider === null && $tvbPackage === null;
$viewParams['tvbPackage'] = $tvbPackage;
$arrivalDate = $acco === null && $additionalProvider === null ? null : $cart->getArrivalDate();
$departureDate = $acco === null && $additionalProvider === null ? null : $cart->getDepartureDate();
$hasTickets = !empty($this->ticketing->getDummyTickets($arrivalDate, $departureDate, $acco, $cart))
&& empty($cart->getDestinationPackageItems());
$viewParams['hasTickets'] = $hasTickets;
$viewParams['lastAddedAdditionalNights'] = $request->get('added') === 'addNights';
$viewParams['lastRemovedAdditionalNights'] = $request->get('removed') === 'addNights';
$viewParams['hasAdditionalPrePaymentStep'] = $this->prePaymentHandler->hasAdditionalPrePaymentStep();
if ($cart->getLastAddedId()) {
$viewParams['lastAddedId'] = $cart->getLastAddedId();
$cart->setLastAddedId(0);
$cart->save();
}
if ($cart->getLastRemovedId()) {
$viewParams['lastRemovedId'] = $cart->getLastRemovedId();
$cart->setLastRemovedId(0);
$cart->save();
}
if (!$this->configuration->getNeverSkipCart()
&& !empty($cart->getItems())
&& count($productIds) > 0
&& $this->additionalServiceListingLocal->getParameter()
&& $this->additionalServiceListingLocal->count() <= 0
&& $request->get('clear')) {
return $this->redirect($this->demiUrl->getCheckoutUrl($hasTickets ? 'ticket' : 'checkout', $hasTickets ? 'overview' : 'step2',
['_locale' => $request->getLocale()], 'customer'));
}
$deviceDetector = DeviceDetector::getInstance();
$device = $deviceDetector->isPhone() ? 'mobile' : 'desktop';
return $this->renderTemplate('@ElementsDemiFrontend/Cart/packagestep1.' . $device . '.html.twig', $viewParams);
}
/**
* @param Request $request
*
* @return RedirectResponse
*
* @throws Exception
* removes a product from the cart and forwards to the overview action
*/
public function removeAdditionalNightsFromCartAction(Request $request): RedirectResponse
{
$cart = $this->ecommerceHelper->getCart();
if (count($cart->getItems()) === 0) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
$itemKey = $request->query->get('itemKey');
if (empty($itemKey)) {
throw new Exception('cannot remove product since there is no itemKey given');
}
$env = Factory::getInstance()->getEnvironment();
$env->setCustomItem('useExistingDesklineCart', false);
$env->save();
$destinationPackageItems = $cart->getDestinationPackageItems();
$destinationPackageCartItem = reset($destinationPackageItems);
if ($destinationPackageCartItem && $destinationPackageCartItem->getItemKey() != $itemKey) {
$subItems = $destinationPackageCartItem->getSubItems();
foreach ($subItems as $subitem) {
if ($subitem->getProduct() instanceof AccommodationProduct) {
$nightPrice = $subitem->getCartItemInfo()->getAdditionalNightsPrice();
$oldAddPrice = $subitem->getCartItemInfo()->getAdditionalNights() * $nightPrice;
if ($oldAddPrice) {
$destinationPackageCartItem->getCartItemInfo()->setTotalPrice($destinationPackageCartItem->getCartItemInfo()->getTotalPrice() - $oldAddPrice);
}
$subitem->getCartItemInfo()->setAdditionalNights(0);
$subitem->getCartItemInfo()->setAdditionalNightsPrice($nightPrice);
$cart->save();
break;
}
}
}
$urlParams = ['_locale' => $request->getLocale()];
if (DeviceDetector::getInstance()->isPhone()) {
$urlParams['viewpoint'] = 2;
$urlParams['removed'] = 'addNights';
}
return $this->redirect($this->demiUrl->getCheckoutUrl('cart', 'packagestep1', $urlParams));
}
/**
* @param Request $request
*
* @return RedirectResponse
*
* @throws Exception
* removes a product from the cart and forwards to the overview action
*/
public function removeFromCartAction(Request $request): RedirectResponse
{
$cart = $this->ecommerceHelper->getCart();
$controller = 'cart';
if (count($cart->getItems()) === 0) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
$itemKey = $request->query->get('itemKey');
if (empty($itemKey)) {
throw new Exception('cannot remove product since there is no itemKey given');
}
$destinationPackageItems = $cart->getDestinationPackageItems();
$destinationPackageCartItem = reset($destinationPackageItems);
if ($destinationPackageCartItem && $destinationPackageCartItem->getItemKey() != $itemKey) {
//TODO: trackingmanager track remove subitem?
$this->ecommerceHelper->removeSubProductFromCart($destinationPackageCartItem->getProductId(), $itemKey);
// TODO fix price of package!
$action = 'packagestep1';
$viewpoint = $destinationPackageCartItem->getCartItemInfo()->getMandatoryMissing() ? 1 : 2;
} else {
$this->trackingManager->trackCartProductActionRemove($cart, $cart->getItem($itemKey)->getProduct(),
$cart->getItem($itemKey)->getCount());
$this->ecommerceHelper->removeProductFromCart($itemKey);
if (!empty($cart->getItems())) {
foreach ($cart->getItems() as $remainingItem) {
if (isset($remainingItem->getCartItemInfo()->getAdditionalInfo()['relatedProduct']) && $remainingItem->getCartItemInfo()->getAdditionalInfo()['relatedProduct'] === $itemKey) {
$keyToRemove = $remainingItem->getItemKey();
$this->trackingManager->trackCartProductActionRemove($cart, $cart->getItem($keyToRemove)->getProduct(),
$cart->getItem($keyToRemove)->getCount());
$this->ecommerceHelper->removeProductFromCart($keyToRemove);
}
}
}
$action = 'step1';
$viewpoint = 2;
}
if ($request->get('ticket')) {
$controller = 'ticket';
$action = 'overview';
}
$urlParams = ['_locale' => $request->getLocale()];
if (DeviceDetector::getInstance()->isPhone()) {
$urlParams['viewpoint'] = $viewpoint;
}
return $this->redirect($this->demiUrl->getCheckoutUrl($controller, $action, $urlParams));
}
/**
* @param Request $request
*
* @return RedirectResponse
*
* @throws Exception
* adds an product to the cart and forwards to the overview (step1)
* it also sets the cancellationInfo of the additionalProduct with the cancellationInfo of the referring acco
*/
public function addAdditionalNightsToCartAction(Request $request): RedirectResponse
{
$count = $request->get('count');
$cart = $this->ecommerceHelper->getCart();
$destinationPackageItems = $cart->getDestinationPackageItems();
$firstDestinationPackageProduct = reset($destinationPackageItems);
if (!$firstDestinationPackageProduct) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
$env = Factory::getInstance()->getEnvironment();
$env->setCustomItem('useExistingDesklineCart', false);
$env->save();
$subItems = $firstDestinationPackageProduct->getSubItems();
foreach ($subItems as $subitem) {
if ($subitem->getProduct() instanceof AccommodationProduct) {
$nightPrice = $subitem->getCartItemInfo()->getAdditionalNightsPrice();
$oldAddPrice = $subitem->getCartItemInfo()->getAdditionalNights() * $nightPrice;
if ($oldAddPrice) {
$firstDestinationPackageProduct->getCartItemInfo()->setTotalPrice($firstDestinationPackageProduct->getCartItemInfo()->getTotalPrice() - $oldAddPrice);
}
$addPrice = $nightPrice * $count;
$subitem->getCartItemInfo()->setAdditionalNights($count);
$subitem->getCartItemInfo()->setAdditionalNightsPrice($nightPrice);
$firstDestinationPackageProduct->getCartItemInfo()->setTotalPrice($firstDestinationPackageProduct->getCartItemInfo()->getTotalPrice() + $addPrice);
$cart->save();
break;
}
}
$url = $this->demiUrl->getCheckoutUrl('cart', 'packagestep1',
['_locale' => $request->getLocale(), 'added' => 'addNights']);
return $this->redirect($url);
}
protected function getTicketsByPrice(TicketCartItemInfoHolder $cartItemInfo, $count, SessionCart $cart, AbstractObject $product): array
{
$alreadyAdded = 0;
foreach ($cart->getItems() as $item) {
if ($item->getProductId() == $product->getId()
&& $item->getCartItemInfo()->getDateFrom()->getTimestamp() == $cartItemInfo->getDateFrom()->getTimestamp()
&& $item->getCartItemInfo()->getDurationValue() == $cartItemInfo->getDurationValue()
&& $item->getCartItemInfo()->getDurationType() == $cartItemInfo->getDurationType()) {
$alreadyAdded += $item->getCount();
}
}
$ticketOrder = $this->orderManager->create([
'product_id' => $cartItemInfo->getInterfaceTicketId(),
'purchaser_first_name' => 'Max',
'purchaser_last_name' => 'Mustermann',
'currency' => Factory::getInstance()->getEnvironment()->getDefaultCurrency()->getShortName(),
'email' => 'max.mustermann@test.at',
'date' => $cartItemInfo->getDateFrom(),
'ticket_types' => [
[
'id' => $cartItemInfo->getInterfaceTicketTypeId(),
'count' => $alreadyAdded + $count
]
]
]);
$ticketsByPrice = [];
/** @var OrderItem $item */
$items = array_slice($ticketOrder->getItems(), $count * -1, null, true);
foreach ($items as $item) {
if (!isset($ticketsByPrice[$item->getSubTotal()])) {
$ticketsByPrice[$item->getSubTotal()] = [];
}
$ticketsByPrice[$item->getSubTotal()][] = $item;
}
return $ticketsByPrice;
}
/**
* @param Request $request
*
* @return RedirectResponse
*
* @throws Exception
* adds an product to the cart and forwards to the overview (step1)
* it also sets the cancellationInfo of the additionalProduct with the cancellationInfo of the referring acco
*/
public function addToCartAction(Request $request): RedirectResponse
{
if ($request->get('tid')) {
if (!$request->get('date') || !$request->get('offerId') || !$request->get('count')) {
throw new Exception('some parameters are missing. cannot add product to cart');
}
} elseif (!$this->validationService->checkRequestForAddToCartParameters($request)) {
throw new Exception('some parameters are missing. cannot add product to cart');
}
$productId = $request->get('offerId');
/** @var AdditionalProduct|ShopItem $product */
$product = AbstractObject::getById($productId);
$count = $request->get('count');
$cart = $this->ecommerceHelper->getCart();
$controller = 'cart';
if ($destinationPackageId = $request->get('tid')) {
$section = PackageSection::getById($request->get('sectionId'));
if (!$section) {
throw new NotFoundHttpException('Could not determine package section');
}
$destinationPackageItems = $cart->getDestinationPackageItems();
$firstDestinationPackageProduct = reset($destinationPackageItems);
if (!$firstDestinationPackageProduct) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
$childrenAges = [];
foreach ($firstDestinationPackageProduct->getCartItemInfo()->getChildrenAges() as $item) {
$c = (int)$request->get('c' . $item);
for ($i = 0; $i < $c; $i++) {
$childrenAges[] = (string)$item;
}
}
$count += count($childrenAges);
$searchParam = $this->searchFrontend->getPackageSearchParam(null, false, $destinationPackageId);
$searchParam->setPackageId($destinationPackageId);
$searchParam = $this->cartItemInfoService->fillPackageSearchParamsFromCartItemInfo($firstDestinationPackageProduct->getCartItemInfo(),
$searchParam);
$this->searchServiceLive->setParams($searchParam);
$packageResultSet = Package::getById($destinationPackageId, $this->searchServiceLive);
$this->ecommerceHelper->addSubProductToCart($count, $packageResultSet->getObject(), $product, $section,
$packageResultSet, $cart, null, $childrenAges);
$cartSubItem = $firstDestinationPackageProduct->getSubItems()[$product->getid() . '_' . $section->getId()];
if ($product instanceof AdditionalProduct && $cartSubItem) {
$this->cartItemInfoService->fillDestinationPackageSubItemInfosFromRequest($cartSubItem->getCartItemInfo(), $request);
}
$this->cartItemInfoService->fillDestinationPackageInfosFromCart($firstDestinationPackageProduct->getCartItemInfo(),
$cart,
$packageResultSet);
if (!$firstDestinationPackageProduct->getCartItemInfo()->getPackageCategory() && is_array($packageResultSet->getCategory())) {
!$firstDestinationPackageProduct->getCartItemInfo()->setPackageCategory($packageResultSet->getCategory()[0]->getObject());
}
$cart->save();
$action = 'packagestep1';
} else {
$accommodationItems = $cart->getAccommodationItems();
$firstAccoProduct = reset($accommodationItems);
if (!$firstAccoProduct) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
$infoHolder = $request->get('ticket') ? new TicketCartItemInfoHolder() : new CartItemInfoHolder();
$cartItemInfo = $this->cartItemInfoService->fillAdditionalServiceProductFromRequest($infoHolder, $request);
$cancelationService = new CancellationInformation();
$cancelationInfo = $cancelationService->getCancellationInformation($product->getParent()->getParent(),
$product,
$product->getParent()->getParent()->getDbCode(),
Config::getInstance()->getSalesChannel(),
$cartItemInfo->getDateFrom(),
$cartItemInfo->getDateTo(),
$cartItemInfo->getAdultAmount(),
$cartItemInfo->getChildrenAges(),
$cartItemInfo->getDurationValue());
$cartItemInfo->setCancellationInformation($cancelationInfo);
if ($this->orderManager && $this->orderManager->getType() === 'Liftopia' && $cartItemInfo instanceof TicketCartItemInfoHolder) {
$ticketsByPrice = $this->getTicketsByPrice($cartItemInfo, $count, $cart, $product);
foreach ($ticketsByPrice as $price => $ticketByPrice) {
$tmpCartItemInfo = clone $cartItemInfo;
$tmpCartItemInfo->setPrice($price);
$tmpCartItemInfo->setTotalPrice($price);
$this->ecommerceHelper->addProductToCart(count($ticketByPrice), $product, $tmpCartItemInfo, $cart);
$this->trackingManager->trackCartProductActionAdd($cart, $product, count($ticketByPrice));
}
} else {
$this->ecommerceHelper->addProductToCart($count, $product, $cartItemInfo, $cart);
$this->trackingManager->trackCartProductActionAdd($cart, $product, $count);
}
$action = 'step1';
}
if ($request->get('ticket') || $request->get('ticketOverview')) {
$controller = 'ticket';
$action = 'overview';
}
$url = $this->demiUrl->getCheckoutUrl($controller, $action, ['_locale' => $request->getLocale()]);
return $this->redirect($url);
}
/**
* @param Request $request
*
* @return Response
*
* @throws Exception
* ajax action for additional offers in step1
*/
public function destinationpackageOfferDetailContentAction(Request $request): Response
{
if (!$this->validationService->checkRequestForOfferDetailContent($request) || !$request->get('tid')) {
throw new Exception('some parameters are missing. cannot add product to cart');
}
$productId = $request->get('id');
$destinationPackageId = $request->get('tid');
$sectionId = $request->get('sectionId');
$cart = $this->ecommerceHelper->getCart();
$packageItems = $cart->getDestinationPackageItems();
$cartItem = reset($packageItems);
$destinationPackage = \Elements\Demi\Model\Package::getById($destinationPackageId);
foreach ($destinationPackage->getSections() as $section) {
if ($section->getId() == $sectionId) {
foreach ($section->getProducts()->getItems() as $item) {
if ($item->getProduct() && $item->getProduct()->getId() == $productId) {
//found section for product
$viewParams['showPrice'] = $section->getSelectionRulesShowPrice();
$viewParams['sectionId'] = $section->getId();
break 2;
}
}
}
}
$product = AdditionalProduct::getById($productId);
$acco = $this->ecommerceHelper->getAccoFromCart($cart);
if (($acco === null) && $destinationPackage->hasAccommodationSection()) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
Config::setClientKeyOverrideFromObject($destinationPackage);
$searchParam = $this->searchFrontend->getPackageSearchParam(null, false, $destinationPackageId);
$searchParam->setPackageId($destinationPackageId);
$searchParam = $this->cartItemInfoService->fillPackageSearchParamsFromCartItemInfo($cartItem->getCartItemInfo(),
$searchParam);
$this->searchServiceLive->setParams($searchParam);
$packageResultSet = Package::getById($destinationPackageId, $this->searchServiceLive);
//does product have own availabilities?
$destinationPackageItems = $cart->getDestinationPackageItems();
$packageItem = reset($destinationPackageItems);
$category = $packageItem->getCartItemInfo()->getPackageCategory();
foreach ($packageResultSet->getCategory() as $resultSetCategory) {
if (!$category || $resultSetCategory->getCategoryFid() == $category->getFid()) {
foreach ($resultSetCategory->getSections() as $resultsetSection) {
if ($resultsetSection->getSectionObject()->getSectionId() == $section->getId()) {
foreach ($resultsetSection->getAssignmentItems() as $assignmentItem) {
if ($assignmentItem->getProductId() == $productId) {
$additionalOfferItem = $assignmentItem;
$viewParams['bookablePer'] = $section->getBookingBookablePer();
if ($section->getBookingBookablePer() === 'perPerson') {
$maxSelect = $cartItem->getCartItemInfo()->getAdultAmount() < $assignmentItem->getAvailability() ? $cartItem->getCartItemInfo()->getAdultAmount() : $assignmentItem->getAvailability();
} elseif ($section->getBookingBookablePer() === 'perPackage') {
$maxSelect = 1;
} else {
$maxSelect = $assignmentItem->getAvailability();
}
$viewParams['maxSelect'] = $maxSelect;
$viewParams['pricePerAdult'] = $assignmentItem->getPriceTotalAdults() / $cartItem->getCartItemInfo()->getAdultAmount();
$viewParams['childrenPrices'] = $assignmentItem->getPriceChildren();
//TODO: use info preselected?
break 3;
}
}
}
}
}
}
foreach ($product->getAdditionalService()->getDescriptions() as $description) {
$descriptionTypes[] = $description->getDescriptionType();
if ($description->getDescriptionType() != DescriptionInterface::DESCRIPTION_SERVICE_DESCRIPTION) {
$tosc5texts[$description->getDescriptionType()] = $description;
}
}
$viewParams['destinationPackageId'] = $destinationPackageId;
$viewParams['id'] = $productId;
$viewParams['price'] = $additionalOfferItem ? $additionalOfferItem->getPriceTotalPrice() : '';
$viewParams['cart'] = $cart;
$viewParams['arrivalDate'] = $cart->getArrivalDate();
$viewParams['departureDate'] = $cart->getDepartureDate();
$viewParams['text'] = $product->getAdditionalService()->getDescription();
$viewParams['tosc5texts'] = $tosc5texts;
$viewParams['title'] = $product->getName();
$viewParams['sectionId'] = $sectionId;
$viewParams['categoryId'] = $category?->getId();
$viewParams['searchParam'] = $this->searchFrontend->getSearchParam();
$viewParams['additionalOfferItem'] = $additionalOfferItem;
$deviceDetector = DeviceDetector::getInstance();
$device = $deviceDetector->isPhone() ? 'mobile' : 'desktop';
return $this->renderTemplate('@ElementsDemiFrontend/Cart/destinationpackageOfferDetailContent.' . $device . '.html.twig', $viewParams);
}
/**
* ajax action for additional offers in step1
*/
public function offerDetailContentAction(Request $request): Response
{
if (!$this->validationService->checkRequestForOfferDetailContent($request)) {
throw new Exception('some parameters are missing. cannot add product to cart');
}
$productId = $request->get('id');
$price = $request->get('price');
$cart = $this->ecommerceHelper->getCart();
$viewParams['showPrice'] = true;
$product = AdditionalProduct::getById($productId);
$acco = $this->ecommerceHelper->getAccoFromCart($cart);
if ($acco === null) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
Config::setClientKeyOverrideFromObject($acco);
$additionalServiceParams = $this->searchFrontend->getAdditionalServiceParam($acco, $cart);
$this->additionalServiceListingLocal->setParameter($additionalServiceParams);
$this->additionalServiceListingLocal->load();
$additionalServiceParams->setSearchLines([
$this->searchFrontend->getAdditionalServiceParamLineLive($cart, $productId)
]);
$tosc5texts = [];
foreach ($product->getAdditionalService()->getDescriptions() as $description) {
$descriptionTypes[] = $description->getDescriptionType();
if ($description->getDescriptionType() != DescriptionInterface::DESCRIPTION_SERVICE_DESCRIPTION) {
$tosc5texts[$description->getDescriptionType()] = $description;
}
}
$additionalServiceParams->setPage(1);
$additionalServiceParams->setPerPage(10);
$env = Factory::getInstance()->getEnvironment();
$bookOnRequest = $env->getCustomItem('deskline_bookableOnRequest');
$additionalServiceParams->setBookOnRequestAsBookable($bookOnRequest);
$this->additionalServiceListingLive->setParameter($additionalServiceParams);
$this->additionalServiceListingLive->load();
$viewParams['id'] = $productId;
$viewParams['price'] = $price;
$viewParams['arrivalDate'] = $cart->getArrivalDate();
$viewParams['departureDate'] = $cart->getDepartureDate();
$viewParams['productText'] = $product->getDescription();
$viewParams['tosc5texts'] = $tosc5texts;
$viewParams['text'] = $product->getAdditionalService()->getDescription();
$viewParams['title'] = $product->getName();
$viewParams['additionalServiceItem'] = $this->additionalServiceListingLive;
$viewParams['additionalServiceItems'] = $this->additionalServiceListingLocal;
$viewParams['isPackage'] = !empty($request->get('packages'));
$viewParams['cart'] = $cart;
$viewParams['searchParam'] = $this->searchFrontend->getSearchParam();
$viewParams['ticket'] = (bool)$request->get('ticket');
//TODO where do we get that value from?
$viewParams['maxSelect'] = $viewParams['ticket'] ? ($cart->getAdultCount() + $cart->getChildrenCount()) : 20;
$deviceDetector = DeviceDetector::getInstance();
$device = $deviceDetector->isPhone() ? 'mobile' : 'desktop';
return $this->renderTemplate('@ElementsDemiFrontend/Cart/offerDetailContent.' . $device . '.html.twig', $viewParams);
}
/**
* ajax action for additional offers in step1
*/
public function additionalNightsDetailContentAction(Request $request): Response
{
if (!$this->validationService->checkRequestForOfferDetailContent($request)) {
throw new Exception('some parameters are missing. cannot add product to cart');
}
$productId = $request->get('id');
$price = $request->get('price');
$destinationPackageId = $request->get('tid');
$sectionId = $request->get('sectionId');
$cart = $this->ecommerceHelper->getCart();
$destionationPackage = \Elements\Demi\Model\Package::getById($destinationPackageId);
if (!$destionationPackage) {
throw new HttpEncodingException('Destination package missing in additionalNightsDetailContentAction');
}
$acco = $this->ecommerceHelper->getAccoFromCart($cart);
if ($acco === null) {
// session ran out
return $this->redirect($this->redirectService->redirectToList($request->request->all(),
'demi.booking.error.session'));
}
$accommodationProduct = AccommodationProduct::getById($request->get('id'));
$currentlySelected = 1;
$destinationPackageItems = $cart->getDestinationPackageItems();
$cartItem = reset($destinationPackageItems);
foreach ($cartItem->getSubItems() as $subitem) {
if ($subitem->getProduct() instanceof AccommodationProduct) {
$currentlySelected = $subitem->getCartItemInfo()->getAdditionalNights();
break;
}
}
$viewParams['currentlySelected'] = $currentlySelected;
$viewParams['accommodationProduct'] = $accommodationProduct;
$viewParams['showPrice'] = true;
$viewParams['maxSelect'] = 7;
$viewParams['sectionId'] = $sectionId;
$viewParams['title'] = $accommodationProduct->getName();
$viewParams['destinationPackageId'] = $destinationPackageId;
$viewParams['id'] = $productId;
$viewParams['tid'] = $destinationPackageId;
$viewParams['price'] = $price;
$viewParams['arrivalDate'] = $cart->getArrivalDate();
$viewParams['departureDate'] = $cart->getDepartureDate();
return $this->renderTemplate('@ElementsDemiFrontend/Cart/additionalNightsDetailContent.twig', $viewParams);
}
public function hasAccoInCartAction(Request $request): JsonResponse
{
/** @var SessionCart $cart */
$cart = $this->ecommerceHelper->getCart();
$hasAcco = $canBeAdded = $hasAdditional = false;
$cartUrl = $this->demiUrl->getCheckoutUrl('cart', 'step1');
if ($request->get('productId')) {
$product = DemiAccommodationProduct::getById($request->get('productId'));
$acco = $product->getParent()->getParent();
}
foreach ($cart->getItems() as $item) {
$prod = $item->getProduct();
if ($prod instanceof AccommodationProduct) {
if ($acco && $prod->getParent()->getParent()->getId() === $acco->getId() && $product->getProductType() === $prod->getProductType()
&& ($request->get('dateFrom') && $request->get('dateTo') && $cart->getArrivalDate()->getTimestamp() === (ElementsCustomDateFormat::parseDateString($request->get('dateFrom')))->getTimestamp() &&
$cart->getDepartureDate()->getTimestamp() === (ElementsCustomDateFormat::parseDateString($request->get('dateTo')))->getTimestamp())) {
$canBeAdded = true;
}
$hasAcco = true;
$urlParams = [];
if (DeviceDetector::getInstance()->isPhone()) {
$urlParams['viewpoint'] = 2;
}
$cartUrl = $this->demiUrl->getCheckoutUrl('cart', 'step1', $urlParams);
} elseif ($prod instanceof DemiAdditionalProduct) {
$hasAdditional = true;
}
}
foreach ($cart->getDestinationPackageItems() as $item) {
$prod = $item->getProduct();
if ($prod instanceof \Elements\Demi\Model\Package) {
$hasAcco = true;
$cartUrl = $this->demiUrl->getCheckoutUrl('cart', 'packagestep1');
}
}
return new JsonResponse([
'hasAcco' => $hasAcco,
'cartUrl' => $cartUrl,
'canBeAdded' => $hasAcco === false ? true : $canBeAdded,
'hasAdditional' => $hasAdditional,
'totalItemAmount' => (count($cart->getItems()) + count($cart->getGiftItems()))
]);
}
public function amountInCartAction(Request $request): JsonResponse
{
/** @var SessionCart $cart */
$cart = $this->ecommerceHelper->getCart();
$subtractShipping = !empty($this->ecommerceHelper->getShippingProductFromCart($cart));
if ($request->get('detailed')) {
$giftAdditionals = $giftAccoProducts = $additionals = $accoProducts = 0;
foreach ($cart->getItems() as $item) {
$item->getProduct() instanceof DemiAccommodationProduct ? $accoProducts++ : $additionals++;
}
foreach ($cart->getGiftItems() as $item) {
$item->getProduct() instanceof DemiAccommodationProduct ? $giftAccoProducts++ : $giftAdditionals++;
}
if ($subtractShipping) {
$additionals--;
}
return new JsonResponse([
'items' => [
'additionalProducts' => $additionals,
'accommodationProducts' => $accoProducts
],
'gifts' => [
'additionalProducts' => $giftAdditionals,
'accommodationProducts' => $giftAccoProducts
],
'total' => $additionals + $accoProducts + $giftAdditionals + $giftAccoProducts
]);
}
$items = count($cart->getItems());
$gifts = count($cart->getGiftItems());
if ($subtractShipping) {
$items--;
}
return new JsonResponse([
'items' => $items,
'gifts' => $gifts,
'total' => $items + $gifts
]);
}
public function clearAction(Request $request): RedirectResponse
{
$this->ecommerceHelper->clear();
return $this->redirect($this->demiUrl->getCheckoutUrl('cart', 'step1'));
}
protected function handleRecommendedServices(CartInterface $cart, ?string $originator = null)
{
foreach ($cart->getItems() as $item) {
$cartItemInfo = $item->getCartItemInfo();
if ($cartItemInfo->getIsMerchandise()) {
continue;
}
if (empty($originator)) {
$originator = $cartItemInfo->getSettlerCode();
}
$addAdditionalServiceService = new DynamicService();
$dateFrom = $cartItemInfo->getDateFrom();
$dateTo = $cartItemInfo->getDateTo();
$units = $cartItemInfo->getAvailableUnits();
$adults = $cartItemInfo->getAdultAmount();
$children = count($cartItemInfo->getChildrenAges());
$productId = $item->getProduct()->getFId();
//$recommendedServices = $addAdditionalServiceService->getUpsellingAdditionalServices($originator, null, $dateFrom, $dateTo, $units, $adults, $children, $productId);
if (empty($recommendedServices)) {
continue;
}
foreach ($recommendedServices as $recommendedService) {
$recommendedProductId = $recommendedService["ProductId"];
$recommendedProduct = AdditionalProduct::getByFid($recommendedProductId);
if ($recommendedProduct === null) {
throw new \Elements\Demi\Deskline\Checkout\ShoppingCart\Exception("Required Product not Found. Aborting!");
}
$price = $recommendedProduct->getPriceTemplates()[0]?->getPrices()?->getItems()[0]?->getPrice();
if ($price === null) {
continue;
}
if (empty($recommendedService["AutoAddRule"])) {
continue;
}
//defaultvalue = AutoAddRule === "perPerson"
$count = $adults;
if ($recommendedService["AutoAddRule"] === "perBooking") {
if (count(array_filter($cart->getItems(), static function ($a) use ($recommendedProduct) {
return $a->getProductId() === $recommendedProduct->getId();
})) > 0) {
return;
}
$count = 1;
}
$addToCartParams['offerId'] = $recommendedProduct->getId();
$addToCartParams['price'] = $price;
$addToCartParams['count'] = $count;
$addToCartParams['date'] = $dateFrom->toIso8601String();
$addToCartParams['settlerCode'] = $originator;
$addToCartParams['removable'] = !$recommendedService["AutoAddItemNotRemovable"];
$addToCartParams['relatedProduct'] = $item->getItemKey();
$this->forward(AdditionalServiceController::class . "::addAdditionalItemAction", [], $addToCartParams);
}
}
}
}