<?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 Carbon\Carbon;
use Elements\Bundle\DemiFrontendBundle\Service\BrochureSearchFrontend;
use Elements\Bundle\DemiFrontendBundle\Service\CartItemInfo;
use Elements\Demi\Frontend\Service\Configuration;
use Elements\Bundle\DemiFrontendBundle\Service\DemiUrl;
use Elements\Bundle\DemiFrontendBundle\Service\DesklineCart;
use Elements\Bundle\DemiFrontendBundle\Service\EcommerceHelper;
use Elements\Bundle\DemiFrontendBundle\Service\Newsletter;
use Elements\Bundle\DemiFrontendBundle\Service\Redirect;
use Elements\Bundle\DemiFrontendBundle\Service\Validation;
use Elements\Demi\DataObject\AbstractCustomer;
use Elements\Demi\Deskline\Config;
use Elements\Demi\Deskline\Constant\PaymentMethodInterface;
use Elements\Demi\Info\CartItemInfoHolder;
use Elements\Demi\Model\Language;
use Elements\Demi\Model\ShopItem;
use Exception;
use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
use Pimcore\Db;
use Pimcore\Localization\LocaleService;
use Pimcore\Model\DataObject\DemiShopItem;
use Pimcore\Model\DataObject\DemiShopItemGroup\Listing;
use Pimcore\Tool\DeviceDetector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\User\UserInterface;
class BrochureController extends BookingController
{
public const BROCHURE_CART_NAME = 'demi_brochures';
protected array $owners = [];
protected array $dbCodes = [];
protected array $langauges = [];
protected array $groupIds = [];
public function __construct(EcommerceHelper $ecommerceHelper, Validation $validationService, Redirect $redirectService, CartItemInfo $cartItemInfoService,
Configuration $configuration, protected DemiUrl $demiUrl, protected LocaleService $locale, protected DesklineCart $desklineCartHelper,
protected BrochureSearchFrontend $brochureSearchFrontend, protected ?Newsletter $newsletterHandler = null, protected ?string $fallbackBrochureOwner = null)
{
parent::__construct($ecommerceHelper, $validationService, $redirectService, $cartItemInfoService, $configuration);
$this->initFilters();
}
public function overviewAction(Request $request, bool $listOnly = false): array|Response
{
if($listOnly){
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
}
$selectedLanguages = $request->get('languages-filter');
$selectedGroups = $request->get('type');
$allowedOwners = $this->owners;
$editableSelectedOwner =$this->getDocumentEditable('select', 'owner')->getData();
if ($editableSelectedOwner !== null && $editableSelectedOwner !== 'undefined') {
$allowedOwners = [$editableSelectedOwner];
}
$selectedOwner = $editableSelectedOwner !== null && $editableSelectedOwner !== 'undefined' ?
[$editableSelectedOwner] : $this->owners;
if ($request->get('owner') && in_array($request->get('owner'), $allowedOwners, true)) {
//only allow filtering of owners which are included/allowed by document
$selectedOwner = [$request->get('owner')];
}
$predefinedHolidaythemes = $this->getDocumentEditable('relations', 'included-themes')->getData();
$themeIds = $request->get('holidayThemeIds');
if (!empty($predefinedHolidaythemes) && empty($themeIds)) {
foreach ($predefinedHolidaythemes as $predefinedHolidaytheme) {
$themeIds[] = $predefinedHolidaytheme->getId();
}
}
$selectedLanguage = $this->locale->getLocale();
$selectedLanguage = (is_array($selectedLanguages) && !in_array($this->locale->getLocale(), $selectedLanguages, true)) ? $selectedLanguages[0] : $selectedLanguage;
$this->brochureSearchFrontend->setLanguages($selectedLanguages ?? [$selectedLanguage]);
$selectedGroup = !empty($selectedGroups) ? $selectedGroups[0] : null;
$this->brochureSearchFrontend->setShopItemGroupIds($selectedGroups ?? []);
$error = $this->ecommerceHelper->getError();
$this->ecommerceHelper->setError('');
$this->brochureSearchFrontend->setObjects(null);
$this->brochureSearchFrontend->applyCustomFiltering();
$this->brochureSearchFrontend->applyCustomSorting();
$brochures = $this->brochureSearchFrontend->getObjectListing($selectedOwner, true);
$brochures = $brochures->getObjects();
$variantLanguages = [];
if (is_array($brochures)) {
foreach ($brochures as $b) {
foreach ($b->getVariants() as $v) {
$variantLanguages[] = $v->getVariationLanguage();
}
}
}
$variantLanguages = array_unique($variantLanguages);
$availableLanguageObjects = [];
foreach ($this->langauges as $language) {
$availableLanguages[] = $language;
$o = Language::getByFid($language);
//only use languages available in the overall result set
if ($o instanceof Language and in_array($o->getFid(), $variantLanguages)) {
$availableLanguageObjects[] = $o;
}
}
uasort($brochures, static function (ShopItem $brochureA, ShopItem $brochureB) {
if (($brochureA->getGroup() && $brochureB->getGroup()) && ($brochureA->getGroup()->getOrder() - $brochureB->getGroup()->getOrder() !== 0)) {
return $brochureA->getGroup()->getOrder() - $brochureB->getGroup()->getOrder();
}
return $brochureA->getOrder() - $brochureB->getOrder();
});
$viewParams['selectedOwner'] = $request->get('owner') ?? [];
$ownerSelect[] = ['undefined', '--------'];
foreach ($this->owners as $owner) {
$ownerSelect[] = [$owner, $owner];
}
$brochureIds = array_map(static function ($brochure) {
if (!$brochure->getParent() instanceof DemiShopItem) {
return $brochure->getId();
}
}, $brochures);
$groups = new Listing();
$groups->addConditionParam('o_id in (' . implode(',', $this->groupIds) . ") and o_id in (select dest_id from
object_relations_{$this->brochureSearchFrontend->getClassId()} where src_id in (" . implode(',', $brochureIds) . '))');
$groups->setOrder('order ASC');
$viewParams['ownersForSelect'] = $ownerSelect;
$viewParams['owners'] = $this->owners;
$viewParams['brochureList'] = $brochures;
$viewParams['availableLanguages'] = array_unique($availableLanguages); //compatibility (unused in standard)
$viewParams['availableLanguageObjects'] = array_unique($availableLanguageObjects);
$viewParams['selectedLanguages'] = $selectedLanguages ?: [];
$viewParams['selectedLanguage'] = $selectedLanguage;
$viewParams['availableGroups'] = $groups->getObjects();
$viewParams['selectedGroups'] = $selectedGroups ?: [];
$viewParams['selectedGroup'] = $selectedGroup;
$viewParams['currentLanguage'] = $this->locale->getLocale();
$viewParams['error'] = $error ? 'demi.booking.error.' . $error : null;
$deviceDetector = DeviceDetector::getInstance();
$device = $deviceDetector?->isPhone() ? 'mobile' : 'desktop';
if (!$listOnly) {
return $this->renderTemplate('@ElementsDemiFrontend/Brochure/overview.'.$device.'.html.twig', $viewParams);
}
return $viewParams;
}
public function listAction(Request $request): Response
{
return $this->renderTemplate('@ElementsDemiFrontend/Brochure/list.html.twig', $this->overviewAction($request, true));
}
public function prepareCheckoutAction(Request $request): void
{
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
$brochures = $request->get('prospekte');
$languages = $request->get('language');
$count = $request->get('count');
$now = new Carbon();
$cart = $this->ecommerceHelper->clear();
foreach ($brochures as $brochure) {
$product = DemiShopItem::getById($brochure);
$brocount = (int)$count[$brochure];
$language = $languages[$brochure];
$cartItemInfo = new CartItemInfoHolder();
$cartItemInfo->setCurrency(Factory::getInstance()->getEnvironment()->getDefaultCurrency()->getShortName());
$cartItemInfo->setDateFrom($now);
$cartItemInfo->setDateTo($cartItemInfo->getDateFrom());
$cartItemInfo->setDbCode($product->getDataBaseCode());
$cartItemInfo->setType($language);
$cartItemInfo->setSettlerCode($product->getOwner());
$this->ecommerceHelper->addProductToCart($brocount, $product, $cartItemInfo, $cart);
}
}
public function step1Action(Request $request, UserInterface $user = null) : Response
{
Factory::getInstance()->getEnvironment()->setCustomItem('demi_cartName', self::BROCHURE_CART_NAME);
if ($request->get('clear')) {
$this->prepareCheckoutAction($request);
}
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
$cart = $this->ecommerceHelper->getCart();
$error = $this->ecommerceHelper->getError();
$this->ecommerceHelper->setError('');
$manager = Factory::getInstance()->getCheckoutManager($cart);
$env = Factory::getInstance()->getEnvironment();
$language = $request->get('_locale');
$cartItems = $cart->getItems();
if(!empty($cartItems)){
Config::setClientKeyOverrideFromObject(reset($cartItems)->getProduct());
}
$desklineCartService = $this->desklineCartHelper->getDesklineCartService($cart);
if ($this->getDocumentEditable('select','owner') === null || $this->getDocumentEditable('select','owner')->getData() === null) {
$this->ecommerceHelper->setError('no-owner-given');
return $this->redirect($this->configuration->getBrochurePath()?->getFullPath());
}
try {
$selectedOwner = $this->getDocumentEditable('select','owner')->getData() !== 'undefined' ? $this->getDocumentEditable('select','owner')->getData() : $this->fallbackBrochureOwner;
// we need to check in brochures with a different originator according to their settlerCode in order to mark
// them for the right salesPoint at deskline.
$desklineCart = $desklineCartService->createCart($language, $selectedOwner);
} catch (Exception $exception) {
$this->ecommerceHelper->setError('create-deskline-cart');
return $this->redirect($this->configuration->getBrochurePath()?->getFullPath());
}
/** @var ShopItem $firstProduct */
$firstProduct = $this->ecommerceHelper->getFirstProductFromCart($cart);
$organisationInformation = $desklineCartService->getOrganisationForSettler($firstProduct->getOwner(), $this->locale->getLocale());
$desklineCart->setOrganisationInformation($organisationInformation);
$paymentInfoStep = $manager->getCheckoutStep('paymentInfo');
$choosableMethods = ['free-brochure' => PaymentMethodInterface::NO_PAYMENT];
$selectedPaymentMethod = PaymentMethodInterface::NO_PAYMENT;
$manager->commitStep($paymentInfoStep, ['paymentMethod' => $selectedPaymentMethod]);
$env->setCustomItem('desklineCart', $desklineCart);
$env->save();
$shopItems = [];
$languages = [];
foreach ($cart->getShopItems() as $shopItem) {
$shopItems[] = $shopItem->getProduct();
$languages[$shopItem->getProduct()->getId()] = $shopItem->getCartItemInfo()->getType();
}
$viewParams['languages'] = $languages;
$viewParams['shopItems'] = $shopItems;
$viewParams['choosablePaymentMethods'] = $choosableMethods;
$viewParams['selectedPaymentMethod'] = $selectedPaymentMethod;
$viewParams['organisationInfo'] = $organisationInformation;
$viewParams['customer'] = $manager->getCheckoutStep('customer')->getData() ? $manager->getCheckoutStep('customer')->getData()['deliveryCustomer'] : null;
$viewParams['optionalData'] = $manager->getCheckoutStep('optionalData')->getData();
$viewParams['isNoPayment'] = true;
$viewParams['error'] = $error ? 'demi.booking.error.' . $error : null;
$viewParams['cart'] = $cart;
$viewParams['cartName'] = self::BROCHURE_CART_NAME;
$viewParams['user'] = $user instanceof AbstractCustomer ? $user : null;
$viewParams['isBrochure'] = true;
$deviceDetector = DeviceDetector::getInstance();
$device = $deviceDetector->isPhone() ? 'mobile' : 'desktop';
return $this->renderTemplate('@ElementsDemiFrontend/Brochure/step1.'.$device.'.html.twig', $viewParams);
}
public function cardAction(Request $request)
{
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
$brochures = $request->get('prospekte');
$languages = $request->get('language');
$selectedBrochures = [];
foreach ($brochures as $brochure) {
$shopItem = DemiShopItem::getById($brochure);
if ($shopItem instanceof DemiShopItem) {
$selectedBrochures[] = $shopItem;
}
}
$viewParams['selectedBrochures'] = $selectedBrochures;
$viewParams['selectedLanguages'] = $languages;
return $this->renderTemplate('@ElementsDemiFrontend/Brochure/card.html.twig', $viewParams);
}
public function finishedAction(Request $request) : Response
{
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
$viewParams['order'] = $request->get('order');
$deviceDetector = DeviceDetector::getInstance();
$device = $deviceDetector->isPhone() ? 'mobile' : 'desktop';
return $this->renderTemplate('@ElementsDemiFrontend/Brochure/finished.'.$device.'.html.twig', $viewParams);
}
protected function initFilters(): void
{
$query = Db::get()->createQueryBuilder();
$query->select('owner')
->distinct()
->from('object_' . DemiShopItem::classId())
->where('o_published = 1 and active = 1')
->orderBy('owner');
$res = $query->execute()->fetchAllNumeric();
if (!empty($res)) {
$res = array_merge(...$res);
$this->owners = $res;
}
$query->select('distinct dataBaseCode')
->from('object_' . DemiShopItem::classId())
->where('o_published = 1 and active = 1')
->orderBy('dataBaseCode');
$res = $query->execute()->fetchAllNumeric();
if (!empty($res)) {
$res = array_merge(...$res);
$this->dbCodes = $res;
}
$query->select('distinct variationLanguage')
->from('object_' . DemiShopItem::classId())
->where('o_published = 1 and active = 1 and variationLanguage is not null')
->orderBy('variationLanguage');
$res = $query->execute()->fetchAllNumeric();
if (!empty($res)) {
$res = array_merge(...$res);
$this->langauges = $res;
}
$query->select('distinct group__id')
->from('object_' . DemiShopItem::classId())
->where('o_published = 1 and active = 1 and group__id is not null')
->orderBy('group__id');
$res = $query->execute()->fetchAllNumeric();
if (!empty($res)) {
$res = array_merge(...$res);
$this->groupIds = $res;
}
}
}