vendor/elements/demi-bundle/src/Elements/Demi/Deskline/DataObject/Adapter/AccommodationProduct.php line 121

Open in your IDE?
  1. <?php
  2. /**
  3.  * Elements DeMI
  4.  *
  5.  * This source file is available under the elements DeMI license version 1
  6.  *
  7.  *  @copyright  Copyright (c) elements.at New Media Solutions GmbH (https://www.elements.at/)
  8.  *  @license    elements DeMI Lizenz Version 1 (https://www.elements.at/de/demi-lizenz)
  9.  */
  10. namespace Elements\Demi\Deskline\DataObject\Adapter;
  11. use Carbon\Carbon;
  12. use Doctrine\DBAL\Connection;
  13. use Doctrine\DBAL\ParameterType;
  14. use Elements\Demi\DataObject\Adapter\AbstractAccommodationProduct;
  15. use Elements\Demi\Deskline\Config;
  16. use Elements\Demi\Deskline\Constant\DescriptionInterface;
  17. use Elements\Demi\Deskline\Constant\DocumentInterface;
  18. use Elements\Demi\Helper;
  19. use Elements\Demi\Vacancies\Dependency\VacancyDependencyContainer;
  20. use Exception;
  21. use Pimcore;
  22. use Pimcore\Bundle\EcommerceFrameworkBundle\CartManager\CartCheckoutData;
  23. use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
  24. use Pimcore\Db;
  25. use Pimcore\Model\DataObject\Fieldcollection\Data\DemiPeriod;
  26. class AccommodationProduct extends AbstractAccommodationProduct implements DocumentInterfaceDescriptionInterface
  27. {
  28.     protected int|float|null $cheapestStdPrice null;
  29.     protected array $defaultDescriptionType = [self::DESCRIPTION_PRODUCT_DESCRIPTION];
  30.     protected array $defaultDocumentTypes = [self::DOCUMENT_TYPE_SERVICE_PROVIDERself::DOCUMENT_TYPE_PRODUCTself::DOCUMENT_TYPE_PRODUCT_GROUPself::DOCUMENT_TYPE_SERVICE];
  31.     public function getImageDocuments(mixed $types null, ?Carbon $filterDate nullbool $withChilds false): array
  32.     {
  33.         if ($types === null) {
  34.             $types $this->defaultDocumentTypes;
  35.         }
  36.         if ($this->object->getProductType() === 'Package') {
  37.             return [];
  38.         }
  39.         return parent::getImageDocuments($types$filterDate);
  40.     }
  41.     public function getDefaultMeals(?Carbon $filterDate null): array
  42.     {
  43.         $defaults = [];
  44.         $priceTemplates $this->object->getPriceTemplatesForMeals($filterDate);
  45.         if ($priceTemplates) {
  46.             foreach ($priceTemplates as $priceTemplate) {
  47.                 if (!empty($priceTemplate->getDefaultMealType())) {
  48.                     $defaults[] = $priceTemplate->getDefaultMealType();
  49.                 }
  50.             }
  51.         }
  52.         return $defaults;
  53.     }
  54.     /**
  55.      * getall valid Mealcodes
  56.      */
  57.     public function getValidMeals(int $nights 0, ?Carbon $filterDate null): array
  58.     {
  59.         $mealCodes = [];
  60.         $priceTemplates $this->object->getPriceTemplates();
  61.         $dummy = new \Elements\Demi\Model\PriceTemplate();
  62.         $classid $dummy->getClassId();
  63.         $priceTemplatesIds = [];
  64.         foreach ($priceTemplates as $templates) {
  65.             $priceTemplatesIds[] = $templates->getId();
  66.         }
  67.         $dummy = new DemiPeriod();
  68.         $fieldcollname $dummy->getType();
  69.         $result = [];
  70.         $builder Db::get()->createQueryBuilder();
  71.         $priceTemplateAdd '';
  72.         if (!empty($priceTemplatesIds)) {
  73.             $priceTemplateAdd $builder->expr()->in('o_id'':templateIds');
  74.         }
  75.         if ($filterDate) {
  76.             $result $builder
  77.                 ->select('objectCollection.o_id')
  78.                 ->from('object_collection_' $fieldcollname '_' $classid'objectCollection')
  79.                 ->where(
  80.                     $builder->expr()->and(
  81.                         $builder->createNamedParameter($filterDate->getTimestamp(), ParameterType::INTEGER) . ' BETWEEN objectCollection.dateFrom AND objectCollection.dateTo',
  82.                         $priceTemplateAdd
  83.                     )
  84.                 )
  85.                 ->setParameter(':templateIds'$priceTemplatesIdsConnection::PARAM_INT_ARRAY)
  86.                 ->execute()->fetchAll();
  87.         }
  88.         if (count($result) <= 0) {
  89.             $builder Db::get()->createQueryBuilder();
  90.             $result $builder
  91.                 ->select('objectClass.o_id')
  92.                 ->from('object_' $classid'objectClass')
  93.                 ->where(
  94.                     $builder->expr()->and(
  95.                         $priceTemplateAdd,
  96.                         'objectClass.name = ' $builder->createNamedParameter('Standard')
  97.                     )
  98.                 )
  99.                 ->setParameter(':templateIds'$priceTemplatesIdsConnection::PARAM_INT_ARRAY)
  100.                 ->execute()->fetchAll();
  101.         }
  102.         $template \Elements\Demi\Model\PriceTemplate::getById((int) $result[0]['o_id']);
  103.         if ($template !== null) {
  104.             $mTypes $template->getMealTypes();
  105.             if ($mTypes !== null) {
  106.                 foreach ($template->getMealTypes() as $mealType) {
  107.                     if ($mealType->getNights() <= $nights) {
  108.                         $dummyCode $mealType->getMealType();
  109.                         $mealCodes[$dummyCode->getFid()] = $dummyCode;
  110.                     }
  111.                 }
  112.             }
  113.         }
  114.         return $mealCodes;
  115.     }
  116.     /**
  117.      * Wrapper function to get an array of mealCodes instead of the mealType object
  118.      * will be removed in future and replaced with _getMeals()
  119.      * kept until the mealCode array is unwrestled in the view-code
  120.      *
  121.      *@deprecated
  122.      */
  123.     public function getMeals(int $nights 0, ?Carbon $filterDate null): array
  124.     {
  125.         $mealCodes = [];
  126.         $meals $this->object->_getMeals($nights$filterDate);
  127.         foreach ($meals as $meal) {
  128.             $mealCodes[] = $meal->getFid();
  129.         }
  130.         return $mealCodes;
  131.     }
  132.     public function _getMeals(int $nights, ?Carbon $filterDate null): array
  133.     {
  134.         $meals = [];
  135.         $priceTemplates $this->object->getPriceTemplatesForMeals($filterDate);
  136.         if ($priceTemplates) {
  137.             foreach ($priceTemplates as $priceTemplate) {
  138.                 if (!empty($priceTemplate->getMealTypes())) {
  139.                     foreach ($priceTemplate->getMealTypes() as $mealType) {
  140.                         if ($mealType->getNights() >= $nights) {
  141.                             $meals[] = $mealType->getMealType();
  142.                         }
  143.                     }
  144.                 }
  145.             }
  146.         }
  147.         return $meals;
  148.     }
  149.     public function getPriceTemplatesForMeals(bool $noFilter false, ?Carbon $filterDate null): \Elements\Demi\Model\PriceTemplate
  150.     {
  151.         $priceTemplates $this->object->getPriceTemplates();
  152.         if (!$noFilter && is_array($priceTemplates) && !Pimcore::inAdmin() && !Config::getInstance()->isImporting()) {
  153.             if (!$filterDate) {
  154.                 $nowTst time();
  155.             } else {
  156.                 $nowTst $filterDate->getTimestamp();
  157.             }
  158.             $priceTemplates array_filter($priceTemplates, static function ($object) use ($nowTst) {
  159.                 return $nowTst >= $object->getValidFrom()->getTimestamp();
  160.             });
  161.         }
  162.         return $priceTemplates;
  163.     }
  164.     public function getPriceForParams(array $params): float
  165.     {
  166.         // dateFrom Carbon
  167.         $mandatory = ['dateFrom''occupancy'];
  168.         foreach ($mandatory as $key) {
  169.             if (!isset($params[$key])) {
  170.                 return 0;
  171.             }
  172.         }
  173.         $price 0;
  174.         $priceTemplates $this->object->getPriceTemplates();
  175.         $useTemplate null;
  176.         $stdTemplate null;
  177.         $today = new Carbon();
  178.         foreach ($priceTemplates as $template) {
  179.             if ($template->getValidFrom()->getTimestamp() > $today->getTimestamp()) {
  180.                 continue;
  181.             }
  182.             $periods $template->getPeriods();
  183.             if ($template->getIsStandard()) {
  184.                 $stdTemplate $template;
  185.                 continue;
  186.             }
  187.             if (!empty($periods)) {
  188.                 foreach ($periods as $period) {
  189.                     if ($period->getDateFrom()->getTimestamp() <= $params['dateFrom']->getTimestamp() && $period->getDateTo()->getTimestamp() >= $params['dateFrom']->getTimestamp()) {
  190.                         $useTemplate $template;
  191.                         break 2;
  192.                     }
  193.                 }
  194.             }
  195.         }
  196.         if (!$useTemplate) {
  197.             $useTemplate $stdTemplate;
  198.         }
  199.         if (!$useTemplate) {
  200.             return 0;
  201.         }
  202.         $prices $useTemplate->getPrices();
  203.         if (!empty($prices)) {
  204.             foreach ($useTemplate->getPrices() as $priceColl) {
  205.                 if ($priceColl->getOccupancyFrom() <= $params['occupancy'] && $priceColl->getOccupancyTo() >= $params['occupancy']) {
  206.                     $price $priceColl->getPrice();
  207.                     break;
  208.                 }
  209.             }
  210.         }
  211.         return $price;
  212.     }
  213.     public function getService(): ?\Elements\Demi\Model\AccommodationService
  214.     {
  215.         $service $this->object->getParent();
  216.         if($service instanceof \Elements\Demi\Model\AccommodationService){
  217.             return $service;
  218.         } else {
  219.             //this is performance killing legacy code and should only be used as last resort in case the object tree is messed up
  220.             $list \Elements\Demi\Model\AccommodationService::getList(['condition' => 'products LIKE ' Db::get()->quote('%,' $this->object->getId() . ',%')]);
  221.             return Helper::first($list->getObjects());
  222.         }
  223.     }
  224.     /**
  225.      * called by default CommitOrderProcessor to get the product name to store it in the order item
  226.      * should be overwritten in mapped sub classes of product classes
  227.      */
  228.     public function getOSName(): string
  229.     {
  230.         return $this->object->getName();
  231.     }
  232.     /**
  233.      * called by default CommitOrderProcessor to get the product number to store it in the order item
  234.      * should be overwritten in mapped sub classes of product classes
  235.      */
  236.     public function getOSProductNumber(): string
  237.     {
  238.         return $this->object->getFid();
  239.     }
  240.     /**
  241.      * defines the name of the price system for this product.
  242.      * there should either be a attribute in pro product object or
  243.      * it should be overwritten in mapped sub classes of product classes
  244.      */
  245.     public function getPriceSystemName(): string
  246.     {
  247.         return 'deskline';
  248.     }
  249.     /**
  250.      * defines if product is included into the product index. If false, product doesn't appear in product index.
  251.      */
  252.     public function getOSDoIndexProduct(): bool
  253.     {
  254.         return false;
  255.     }
  256.     /**
  257.      * returns if product is active.
  258.      * there should either be a attribute in pro product object or
  259.      * it should be overwritten in mapped sub classes of product classes in case of multiple criteria for product active state
  260.      */
  261.     public function isActive(): bool
  262.     {
  263.         return $this->object->getActive();
  264.     }
  265.     /**
  266.      * returns array of categories.
  267.      * has to be overwritten either in pimcore object or mapped sub class.
  268.      */
  269.     public function getCategories(): array
  270.     {
  271.         return [];
  272.     }
  273.     public function setDesklinePrice($price): void
  274.     {
  275.         $env Factory::getInstance()->getEnvironment();
  276.         $prices $env->getDesklineProductPrices();
  277.         //TODO CHECK IF EXISTS....
  278.         $prices[$this->object->getId()] = $price;
  279.         $env->setDesklineProductPrices($prices);
  280.         $env->save();
  281.     }
  282.     //TODO use trait for additional and accommodation Product
  283.     public function getDesklinePrice()
  284.     {
  285.         $env Factory::getInstance()->getEnvironment();
  286.         $data CartCheckoutData::getByKeyCartId('p_' $this->object->getId(), $env->getCartId());
  287.         $stdObj unserialize($data->getData());
  288.         if (! is_object($stdObj) || empty($stdObj->price)) {
  289.             throw new Exception('No Price Set for Product ' $this->object->getId());
  290.         }
  291.         return $stdObj->price;
  292.     }
  293.     //TODO obsolete
  294.     public function getDesklineQuantity()
  295.     {
  296.         $env Factory::getInstance()->getEnvironment();
  297.         $quantities $env->getDesklineProductQuantities();
  298.         return $quantities[$this->object->getId()] ?? 1;
  299.     }
  300.     public function getCheapestStandardPrice(VacancyDependencyContainer $dc): float|int|null
  301.     {
  302.         if ($this->cheapestStdPrice <= || $this->cheapestStdPrice === null) {
  303.             $query '
  304.                 SELECT bp.price as minPrice, pt.rule type, pt.nights nights
  305.                   FROM    ' $dc->getDBTableName('price_template') . ' pt
  306.                        INNER JOIN
  307.                           ' $dc->getDBTableName('price_template_base_prices') . ' bp
  308.                        ON bp.price_template_id = pt.id
  309.                  WHERE     pt.product_id = ' $this->object->getId() . '
  310.                        AND pt.stdOccupancy BETWEEN bp.occupancyFrom AND bp.occupancyTo
  311.                        AND price > 0
  312.                        order by minPrice
  313.                        limit 1
  314.             ';
  315.             $result $dc->getDb()->fetchAllAssociative($query);
  316.             $this->cheapestStdPrice 0;
  317.             if (!empty($result)) {
  318.                 $this->cheapestStdPrice $result[0];
  319.             }
  320.         }
  321.         return $this->cheapestStdPrice;
  322.     }
  323.     /**
  324.      * @depricated
  325.      */
  326.     public function getMinPriceFromStandardTemplate()
  327.     {
  328.         $templates $this->object->getPriceTemplates();
  329.         $price null;
  330.         if (!empty($templates)) {
  331.             $stdAdults $this->object->getAdultsStd();
  332.             foreach ($templates as $template) {
  333.                 if (strtolower($template->getName()) === 'standard') {
  334.                     $prices $template->getPrices();
  335.                     if (!empty($prices)) {
  336.                         foreach ($prices as $price) {
  337.                             if ($stdAdults >= $price->getOccupancyFrom() && $stdAdults <= $price->getOccupancyTo()) {
  338.                                 $price $price->getPrice();
  339.                                 break;
  340.                             }
  341.                         }
  342.                     }
  343.                     break;
  344.                 }
  345.             }
  346.         }
  347.         return $price;
  348.     }
  349.     public function getPackageMaster(): Pimcore\Model\DataObject\AbstractObject|\Elements\Demi\Model\HousePackageMaster|Pimcore\Model\DataObject\Concrete|null
  350.     {
  351.         $dummy = new \Elements\Demi\Model\HousePackageMaster();
  352.         $classId $dummy->getClassId();
  353.         $builder Db::get()->createQueryBuilder();
  354.         $result $builder
  355.             ->select('objectRelations.src_id')
  356.             ->from('object_relations_' $classId'objectRelations')
  357.             ->where('objectRelations.dest_id = ' $builder->createNamedParameter($this->object->getId(), ParameterType::INTEGER))
  358.             ->execute()->fetchAll();
  359.         $hpm null;
  360.         if (is_array($result) && count($result) === 1) {
  361.             $hpm \Elements\Demi\Model\HousePackageMaster::getById($result[0]['src_id']);
  362.         } elseif (is_array($result)) {
  363.             foreach ($result as $data) {
  364.                 $hpm \Elements\Demi\Model\HousePackageMaster::getById($data['src_id']);
  365.                 if ($hpm && $hpm->isPublished()) {
  366.                     break;
  367.                 }
  368.             }
  369.         }
  370.         return $hpm;
  371.     }
  372. }