<?php 
 
namespace Slivki\Controller\Admin; 
 
use DateTimeImmutable; 
use Doctrine\ORM\EntityManager; 
use GeoIO\Dimension; 
use GeoIO\Geometry\Factory; 
use Imagine\Gd\Imagine; 
use Imagine\Image\Box; 
use Imagine\Image\Point; 
use Slivki\Command\SavePurchaseCountCommand; 
use Slivki\Dao\InteriorGallery\InteriorGalleryDaoInterface; 
use Slivki\Dao\Offer\FoodOfferExtension\FoodOfferExtensionDaoInterface; 
use Slivki\Dao\Offer\MobApiOfferDaoInterface; 
use Slivki\Dto\FoodCourt\DeliveryOneDayWorkingTimeDto; 
use Slivki\Entity\AntiTag; 
use Slivki\Entity\BankCurrency; 
use Slivki\Entity\Category; 
use Slivki\Entity\City; 
use Slivki\Entity\CityArea; 
use Slivki\Entity\Comment; 
use Slivki\Entity\Director; 
use Slivki\Entity\EntityDescription; 
use Slivki\Entity\EntityDescriptionSliderImage; 
use Slivki\Entity\EntityOption; 
use Slivki\Entity\FoodOfferExtension; 
use Slivki\Entity\FoodOfferOptionExtension; 
use Slivki\Entity\GeoLocation; 
use Slivki\Entity\GiftCertificate; 
use Slivki\Entity\GiftCertificateCategory; 
use Slivki\Entity\GiftCertificateGiftCategory; 
use Slivki\Entity\GiftCertificateTag; 
use Slivki\Entity\HotFeed; 
use Slivki\Entity\ItemOfferExtension; 
use Slivki\Entity\MallGeoLocation; 
use Slivki\Entity\Media; 
use Slivki\Entity\Media\OfferDeliveryZoneMedia; 
use Slivki\Entity\Media\OfferMapLogoMedia; 
use Slivki\Entity\Media\OnlineOrderPopupLogoMedia; 
use Slivki\Entity\MediaType; 
use Slivki\Entity\Offer; 
use Slivki\Entity\OfferCategoryPosition; 
use Slivki\Entity\OfferCodePool; 
use Slivki\Entity\OfferExtension; 
use Slivki\Entity\OfferExtensionCategory; 
use Slivki\Entity\OfferExtensionOnlineCategory; 
use Slivki\Entity\OfferOrder; 
use Slivki\Entity\OfferOrderDetails; 
use Slivki\Entity\OfferPayedCategory; 
use Slivki\Entity\OfferPayedCategoryMobile; 
use Slivki\Entity\OfferProposal; 
use Slivki\Entity\OnlineOrderSettings; 
use Slivki\Entity\OperatorActionLog; 
use Slivki\Entity\PhoneNumber; 
use Slivki\Entity\ProductFastDelivery; 
use Slivki\Entity\RenewedOffer; 
use Slivki\Entity\Seo; 
use Slivki\Entity\SiteSettings; 
use Slivki\Entity\User; 
use Slivki\Entity\UserGroup; 
use Slivki\Message\Command\Admin\Category\OfferExtensionOnlineCategory\SaveOfferExtensionOnlineCategoryOfferRelationsCommand; 
use Slivki\Message\Command\Admin\Offer\EditOfferNoteCommand; 
use Slivki\Message\Command\OfferStatusLog\CreateOfferStatusLogCommand; 
use Slivki\Message\Query\Admin\Offer\OfferExtension\OfferExtensionVisibility\GetOfferExtensionVisibilitiesQuery; 
use Slivki\Messenger\Query\QueryBusInterface; 
use Slivki\Repository\Category\Admin\CategoryRepositoryInterface; 
use Slivki\Repository\Category\OfferExtensionOnlineCategory\Admin\OfferExtensionOnlineCategoryRepositoryInterface; 
use Slivki\Repository\City\Admin\CityRepositoryInterface; 
use Slivki\Repository\DeliverySchedule\Admin\DeliveryScheduleRepositoryInterface; 
use Slivki\Repository\GiftCertificate\GiftCertificateGroup\Admin\GiftCertificateGroupRepositoryInterface; 
use Slivki\Repository\GiftCertificateCategory\Admin\GiftCertificateCategoryRepositoryInterface; 
use Slivki\Repository\GiftCertificateGiftCategory\Admin\GiftCertificateGiftCategoryRepositoryInterface; 
use Slivki\Repository\Offer\Admin\FoodDeliveryZoneRepositoryInterface; 
use Slivki\Repository\OfferRepository; 
use Slivki\Repository\ProductFastDeliveryRepository; 
use Slivki\Repository\SaleRepository; 
use Slivki\Repository\SeoRepository; 
use Slivki\Serializer\Config\SerializerConfig; 
use Slivki\Services\CacheService; 
use Slivki\Services\CategoryBoxCacheService; 
use Slivki\Services\FoodCourt\DeliveryWorkingTimeService; 
use Slivki\Services\ImageService; 
use Slivki\Services\Mailer; 
use Slivki\Services\Offer\CodePoolService; 
use Slivki\Services\Offer\GalleryVideo\VideoPackageDtoGetter; 
use Slivki\Services\Offer\GalleryVideo\VideoPackageSaver; 
use Slivki\Services\Offer\OfferCacheService; 
use Slivki\Services\Offer\OfferFoodDeliveryZoneSaver; 
use Slivki\Services\Offer\OfferNoteGetter; 
use Slivki\Services\Offer\OfferResponseCacheService; 
use Slivki\Services\OnlineOrderSettings\ReceivingOrdersScheduleService; 
use Slivki\Services\Seo\SeoResourceService; 
use Slivki\Util\CommonUtil; 
use Slivki\Util\Iiko\AbstractDelivery; 
use Slivki\Util\Logger; 
use Symfony\Component\Filesystem\Filesystem; 
use Symfony\Component\HttpFoundation\JsonResponse; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpFoundation\StreamedResponse; 
use Symfony\Component\HttpKernel\KernelInterface; 
use Symfony\Component\Messenger\MessageBusInterface; 
use Symfony\Component\Routing\Annotation\Route; 
use Symfony\Component\Security\Core\Role\Role; 
use Symfony\Component\Serializer\SerializerInterface; 
use Symfony\Component\Validator\Validator\ValidatorInterface; 
 
use function array_map; 
use function explode; 
use function in_array; 
use function random_int; 
 
class OfferController extends AdminController 
{ 
    public const BELARUS_PHONE_CODE = ''; 
 
    private GiftCertificateCategoryRepositoryInterface $giftCertificateCategoryRepository; 
    private FoodOfferExtensionDaoInterface $foodOfferExtensionDao; 
    private MessageBusInterface $messageBus; 
    private DeliveryWorkingTimeService $deliveryWorkingTimeService; 
    private SerializerInterface $serializer; 
    private MobApiOfferDaoInterface $mobApiOfferDao; 
    private GiftCertificateGroupRepositoryInterface $giftCertificateGroupRepository; 
    private VideoPackageDtoGetter $videoPackageDtoGetter; 
    private VideoPackageSaver $videoPackageSaver; 
    private GiftCertificateGiftCategoryRepositoryInterface $giftCertificateGiftCategoryRepository; 
    private OfferFoodDeliveryZoneSaver $offerFoodDeliveryZoneSaver; 
    private CategoryRepositoryInterface $categoryRepository; 
    private CityRepositoryInterface $cityRepository; 
    private InteriorGalleryDaoInterface $interiorGalleryDao; 
    private OfferResponseCacheService $offerResponseCacheService; 
 
    public function __construct( 
        KernelInterface $kernel, 
        GiftCertificateCategoryRepositoryInterface $giftCertificateCategoryRepository, 
        GiftCertificateGiftCategoryRepositoryInterface $giftCertificateGiftCategoryRepository, 
        FoodOfferExtensionDaoInterface $foodOfferExtensionDao, 
        MessageBusInterface $messageBus, 
        DeliveryWorkingTimeService $deliveryWorkingTimeService, 
        SerializerInterface $serializer, 
        MobApiOfferDaoInterface $mobApiOfferDao, 
        GiftCertificateGroupRepositoryInterface $giftCertificateGroupRepository, 
        VideoPackageDtoGetter $videoPackageDtoGetter, 
        VideoPackageSaver $videoPackageSaver, 
        OfferFoodDeliveryZoneSaver $offerFoodDeliveryZoneSaver, 
        CategoryRepositoryInterface $categoryRepository, 
        CityRepositoryInterface $cityRepository, 
        InteriorGalleryDaoInterface $interiorGalleryDao, 
        OfferResponseCacheService $offerResponseCacheService 
    ) { 
        parent::__construct($kernel); 
        $this->giftCertificateCategoryRepository = $giftCertificateCategoryRepository; 
        $this->giftCertificateGiftCategoryRepository = $giftCertificateGiftCategoryRepository; 
        $this->foodOfferExtensionDao = $foodOfferExtensionDao; 
        $this->messageBus = $messageBus; 
        $this->deliveryWorkingTimeService = $deliveryWorkingTimeService; 
        $this->serializer = $serializer; 
        $this->mobApiOfferDao = $mobApiOfferDao; 
        $this->giftCertificateGroupRepository = $giftCertificateGroupRepository; 
        $this->videoPackageDtoGetter = $videoPackageDtoGetter; 
        $this->videoPackageSaver = $videoPackageSaver; 
        $this->offerFoodDeliveryZoneSaver = $offerFoodDeliveryZoneSaver; 
        $this->categoryRepository = $categoryRepository; 
        $this->cityRepository = $cityRepository; 
        $this->interiorGalleryDao = $interiorGalleryDao; 
        $this->offerResponseCacheService = $offerResponseCacheService; 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_by_category") 
     */ 
    public function ajaxGetByCategory(Request $request) { 
        ini_set('memory_limit', '512m'); 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $data = array(); 
        $categoryID = (int)$request->request->get('categoryID'); 
 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $offerRepository = $entityManager->getRepository(Offer::class); 
        $data['offers'] = $offerRepository->getOffersByCategoryWithPositions($categoryID); 
        $categoryRepository = $entityManager->getRepository(Category::class); 
        $data['category'] = $categoryRepository->find($categoryID); 
        $payedOffersList = $categoryRepository->getPayedOffersByCategoryID($categoryID); 
 
        $data['mobApiPaidOffersPositions'] = []; 
        foreach ($this->mobApiOfferDao->getPaidOffersPositionsByCategoryId($categoryID) as $mobApiPaidOffersPosition) { 
            $data['mobApiPaidOffersPositions'][$mobApiPaidOffersPosition->getId()] = $mobApiPaidOffersPosition->getPosition(); 
        } 
 
        $data['payedOffersList'] = $payedOffersList; 
        $result = $this->get('twig')->render('Slivki/admin/offers/index.html.twig', $data); 
 
        return new Response($result); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_by_category_without_tags") 
     */ 
    public function ajaxGetByCategoryWithoutTags(Request $request) { 
        $data = []; 
        $domainObjectID = (int)$request->request->get('domainObjectID'); 
        $cityID = (int)$request->request->get('cityID'); 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $offerRepository = $entityManager->getRepository(Offer::class); 
        $data['offers'] = $offerRepository->getActiveOffersByCategoryWithoutTags($domainObjectID, $cityID); 
        return $this->render('Slivki/admin/offers/index_without_tags.html.twig', $data); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_by_category_without_tags_all_city") 
     */ 
    public function ajaxGetByCategoryWithoutTagsAllCity(Request $request) { 
        $data = []; 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $offerRepository = $entityManager->getRepository(Offer::class); 
        $data['offers'] = $offerRepository->getActiveOffersByCategoryWithoutTagsAllCity(); 
        return $this->render('Slivki/admin/offers/index_without_tags.html.twig', $data); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_offers_on_review") 
     */ 
    public function ajaxGetByCategoryOnReview(Request $request) { 
        $data = []; 
        $domainObjectID = (int)$request->request->get('domainObjectID'); 
        $cityID = (int)$request->request->get('cityID'); 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $offerRepository = $entityManager->getRepository(Offer::class); 
        $offers = $offerRepository->getOffersOnReview($domainObjectID, $cityID); 
        if ($offers) { 
            foreach ($offers as $offer) { 
                $data['offers'][] = $offerRepository->find($offer['id']); 
            } 
        } else { 
            $data['offers'] = []; 
        } 
        return $this->render('Slivki/admin/offers/index_on_review.html.twig', $data); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_offer/{ID}") 
     */ 
    public function ajaxGetOffer( 
        Request $request, 
        DeliveryScheduleRepositoryInterface $deliveryScheduleRepository, 
        ImageService $imageService, 
        OfferNoteGetter $offerNoteGetter, 
        ReceivingOrdersScheduleService $receivingOrdersScheduleService, 
        FoodDeliveryZoneRepositoryInterface $foodDeliveryZoneRepository, 
        SeoResourceService $seoResourceService, 
        $ID 
    ): Response { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        ini_set('memory_limit', '256m'); 
        $session = $request->getSession(); 
        $session->set('geoLocationList', []); 
 
        $result = array(); 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $offerRepository = $entityManager->getRepository(Offer::class); 
        $entityOptionRepository = $entityManager->getRepository(EntityOption::class); 
        /** @var Offer $offer */ 
        $offer = $offerRepository->find($ID); 
        $result['offer'] = $offer; 
        $user = $this->getUserRepository()->findOneBy(["ID" => $this->getUser()->getID()]); 
        if (!$offer->isNeedReview() || $user->hasRole(UserGroup::ROLE_REVIEWER) || $user->hasRole(UserGroup::ROLE_ADMIN_ID)) { 
            $result['activeView'] = true; 
        } else { 
            $result['activeView'] = false; 
        } 
        if ($offer->isNeedReview() && !$offer->isOnReview() && $user->hasRole(UserGroup::ROLE_JUNIOR)) { 
            $result['sendOnReviewActive'] = true; 
        } else { 
            $result['sendOnReviewActive'] = false; 
        } 
        $result['activeSince'] = $offer->getActiveSince()->format('d.m.Y'); 
        $result['activeTill'] = $offer->getActiveTill()->format('d.m.Y'); 
        $result['codeActiveTill'] = $offer->getCodeActiveTill()->format('d.m.Y'); 
        $result['lastModified'] = $offer->getLastModified()->format('Y-m-d H:i:s'); 
 
        $seoRepository = $entityManager->getRepository(Seo::class); 
        $seo = $seoRepository->findBy(array('entityID' => $ID, 'resourceURL' => 'Slivki:Default:details'), array('ID' => 'DESC'), 1); 
        if ($seo) { 
            $seo = $seo[0]; 
            $result['seo']['alias'] = $seo->getMainAlias(); 
            $result['seo']['metaTitle'] = $seo->getMetaTitle(); 
            $result['seo']['metaDescription'] = $seo->getMetaDescription(); 
            $result['seo']['metaKeywords'] = $seo->getMetaKeywords(); 
        } else { 
            $result['seo']['alias'] = ''; 
            $result['seo']['metaTitle'] = ''; 
            $result['seo']['metaDescription'] = ''; 
            $result['seo']['metaKeywords'] = ''; 
        } 
        $offerPaidCategoryList = $entityManager->getRepository(OfferPayedCategory::class)->getPayedCategoriesByEntityID($ID, Category::OFFER_CATEGORY_ID); 
        $offerPaidCategoryIDList = []; 
        foreach ($offerPaidCategoryList as $offerPaidCategory) { 
            $offerPaidCategoryIDList[] = $offerPaidCategory->getCategoryID(); 
        } 
        $cityID = $offer->getDefaultCity()->getID(); 
        $offerCategoryList = $offer->getCategories()->toArray(); 
        $offerCityCategoryList = $offerCategoryList; 
        $offerPaidCategoryMobile = $entityManager->getRepository(OfferPayedCategoryMobile::class); 
        $offerPaidCategoryMobileList = []; 
        foreach ($offerCityCategoryList as $category) { 
            $categoryID = $category->getID(); 
            $mobilePosition = $offerPaidCategoryMobile->findOneBy(['categoryID' => $categoryID, 'entityID' => $ID]); 
            if ($mobilePosition) { 
                $offerPaidCategoryMobileList[$categoryID] = $mobilePosition->getPosition(); 
            } 
        } 
        $offerCategoryIDList = []; 
        $offerCityCategoryCurrentIDList = []; 
        $priceCategoryID = 0; 
        $genderCategoryIDs = []; 
        $transportTypeID = 0; 
        $tourtypeIDs = []; 
        if ($offer->getID() === Offer::BOOKING_OFFER_ID) { 
            $result['bookingTabVisible'] = true; 
        } 
        foreach ($offerCategoryList as $key => $offerCategory) { 
            if ($offerCategory->getID() === Category::FOOD_CATEGORY_ID || trim($offerCategory->getName()) == 'Еда') { 
                $result['foodTabVisible'] = true; 
            } 
            if ($offerCategory->getDomainObjectID() <= Category::SUPPLIER_CATEGORY_TYPE) { 
                $offerCategoryIDList[] = $offerCategory->getID(); 
                if ($offerCategory->getCity()->getID() == $cityID) { 
                    $offerCityCategoryCurrentIDList[] = $offerCategory->getID(); 
                } else { 
                    unset($offerCityCategoryList[$key]); 
                } 
            } else { 
                unset($offerCategoryList[$key]); 
                unset($offerCityCategoryList[$key]); 
                switch ($offerCategory->getDomainObjectID()) { 
                    case Category::PRICE_CATEGORY_ID: 
                        $priceCategoryID = $offerCategory->getID(); 
                        break; 
                    case Category::GENDER_CATEGORY_ID: 
                        $genderCategoryIDs[] = $offerCategory->getID(); 
                        break; 
                    case Category::TRANSPORT_TYPE_CATEGORY_ID: 
                        $transportTypeID = $offerCategory->getID(); 
                        break; 
                    case Category::TOUR_TYPE_CATEGORY_ID: 
                        $tourtypeIDs[] = $offerCategory->getID(); 
                } 
            } 
        } 
        $result['cityID'] = $cityID; 
        $result['allCityCategoryIDList'] = $offerCategoryIDList; 
        $result['genderCategoryIDs'] = $genderCategoryIDs; 
        $result['priceCategoryID'] = $priceCategoryID; 
        $result['transportTypeID'] = $transportTypeID; 
        $result['tourTypeIDs'] = $tourtypeIDs; 
        $result['tourismOffer'] = false; 
        if (in_array(Category::TOURISM_CATEGORY_ID, $offerCategoryIDList)) { 
            $result['tourismOffer'] = true; 
        } 
 
        $result['unlimitedCodes'] = false; 
        $result['offerForSlivkiDelivery'] = false; 
        $entityOptions = $entityOptionRepository->findBy([ 
            'entityID' => $ID, 
            'entityTypeID' => EntityOption::OFFER_ENTITY_TYPE 
        ]); 
 
        /** @var EntityOption $entityOption */ 
        foreach ($entityOptions as $entityOption) { 
            switch ($entityOption->getName()) { 
                case EntityOption::OPTION_CODES_UNLIMITED: 
                    $result['unlimitedCodes'] = true; 
                    break; 
                case EntityOption::OPTION_SLIVKI_DELIVERY: 
                    $result['offerForSlivkiDelivery'] = true; 
                    break; 
            } 
        } 
 
        $result['offerCategories'] = $this->get('twig')->render('Slivki/admin/offers/edit_offer_selected_categories.html.twig', [ 
            'offerCategoryList' => $offerCityCategoryList, 
            'offerPaidCategoryIDList' => $offerPaidCategoryIDList, 
            'defaultCategoryID' => $offer->getDefaultCategoryID(), 
            'offerPaidCategoryMobile' => $offerPaidCategoryMobileList 
        ]); 
        $categoryRepository = $entityManager->getRepository(Category::class); 
        $data['categories'] = $categoryRepository->getCategoryTree(Category::OFFER_CATEGORY_ID, 0, $cityID); 
        $data['selectedCategoryIDList'] = $offerCityCategoryCurrentIDList; 
        $result['categories'] = $this->get('twig')->render('Slivki/admin/categories/recursive_category_with_checkboxes_macro.html.twig', $data); 
 
        $mediaRepository = $entityManager->getRepository(Media::class); 
        $teaserImage = $offer->getTeaserMedia(); 
        if ($teaserImage) { 
            $result['teaserImage'] = $imageService->getImageURL($teaserImage, 500, 324); 
        } 
        $appTeaserImage = $offer->getAppTeaserMedia(); 
        if ($appTeaserImage) { 
            $result['appTeaserImage'] = $imageService->getImageURL($appTeaserImage, ImageService::OFFER_APP_TEASER_WIDTH, ImageService::OFFER_APP_TEASER_HEIGHT); 
        } 
        $mobileTeaserImage = $offer->getMobileTeaserMedia(); 
        if ($mobileTeaserImage) { 
            $result['mobileTeaserImage'] = $imageService->getImageURL($mobileTeaserImage, 764, 382); 
        } 
        $additionalTeaserImage = $mediaRepository->getOfferAdditionalTeaserMedia($ID); 
        if ($additionalTeaserImage) { 
            $result['additionalTeaserImage'] = $imageService->getImageURL($additionalTeaserImage, 250, 162); 
        } 
        $hotFeedIconImage = $mediaRepository->getOfferHotFeedIconMedia($ID); 
        if ($hotFeedIconImage) { 
            $result['hotFeedIconImage'] = $imageService->getImageURL($hotFeedIconImage, 500, 324); 
        } 
        $offerTopBlockMedia = $offer->getTopBlockMedia(); 
        if ($offerTopBlockMedia) { 
            $result['offerTopBlockMedia'] = $imageService->getImageURL($offerTopBlockMedia, 0, 0); 
        } 
        $offerTopBlockMobileMedia = $offer->getTopBlockMobileMedia(); 
        if ($offerTopBlockMobileMedia) { 
            $result['offerTopBlockMobileMedia'] = $imageService->getImageURL($offerTopBlockMobileMedia, 0, 0); 
        } 
 
        $onlineOrderPopupLogoMedia = $offer->getOnlineOrderPopupLogoMedia(); 
        if (null !== $onlineOrderPopupLogoMedia) { 
            $result['onlineOrderPopupLogoMedia'] = $imageService->getImageURL($onlineOrderPopupLogoMedia, 350, 175); 
        } 
 
        $giftCertificatePdfBgMedia = $offer->getGiftCertificatePdfBgMedia(); 
        if ($giftCertificatePdfBgMedia) { 
            $result['giftCertificatePdfBgMedia'] = $imageService->getImageURL($giftCertificatePdfBgMedia, 0, 0); 
        } 
 
        $mapLogoMedia = $offer->getMapLogoMedia(); 
        if (null !== $mapLogoMedia) { 
            $result['mapLogoMedia'] = $imageService->getImageURL($mapLogoMedia, 0, 0); 
        } 
 
        $deliveryZoneMedia = $offer->getDeliveryZoneMedia(); 
        if (null !== $deliveryZoneMedia) { 
            $result['deliveryZoneMedia'] = $imageService->getImageURL($deliveryZoneMedia, 0, 0); 
        } 
 
        $offerTeaserLogo = $mediaRepository->getOfferTeaserLogo($ID); 
        if ($offerTeaserLogo) { 
            $result['offerTeaserLogo'] = $imageService->getImageURL($offerTeaserLogo, $offer->getTeaserLogoWidth(), $offer->getTeaserLogoHeight()); 
        } 
        $offerShopMedias = $mediaRepository->getOfferShopMedias($ID); 
        $result['offerShopMedias'] = $this->renderView('Slivki/admin/offers/shop_medias.html.twig', [ 
            'images' => $offerShopMedias, 
            'interiorGalleryMediaIds' => $this->interiorGalleryDao->getByOfferId($ID), 
        ]); 
 
        $offerDetailMedias = $mediaRepository->getOfferDetailMedias($ID); 
        $result['offerDetailMedias'] = $this->get('twig')->render('Slivki/admin/offers/detail_medias.html.twig', array('images' => $offerDetailMedias)); 
 
        $descriptionRepository = $entityManager->getRepository(EntityDescription::class); 
        $descriptionTypeIDList = [ 
            'Condition' => EntityDescription::TYPE_OFFER_CONDITIONS_ID, 
            'Features' => EntityDescription::TYPE_OFFER_FEATURES_ID, 
            'Location' => EntityDescription::TYPE_OFFER_LOCATION_ID, 
            'Logo' => EntityDescription::TYPE_OFFER_LOGO_ID, 
            'Legal' => EntityDescription::TYPE_OFFER_LEGAL_ID, 
            'Description' => EntityDescription::TYPE_OFFER_DESCRIPTION_ID, 
            'WorkingHours' => EntityDescription::TYPE_OFFER_WORKING_HOURS_ID, 
            'VendorCondition' => EntityDescription::TYPE_VENDOR_CONDITION, 
            'BriefDeliveryCondition' => EntityDescription::TYPE_BRIEF_DELIVERY_CONDITION, 
        ]; 
        foreach ($descriptionTypeIDList as $key => $descriptionTypeID) { 
            if ($descriptionTypeID == EntityDescription::TYPE_OFFER_DESCRIPTION_ID) { 
                $descriptions = $descriptionRepository->findBy(['entityID' => $ID, 'typeID' => $descriptionTypeID], ['ID' => 'ASC']); 
                if (!$descriptions) { 
                    $descriptions = ['new']; 
                } 
                $result['offerDescriptions'] = $this->get('twig')->render('Slivki/admin/offers/offer_description_block.html.twig', ['descriptions' => $descriptions]); 
            } else { 
                $description = $descriptionRepository->findOneBy(['entityID' => $ID, 'typeID' => $descriptionTypeID]); 
                $result["description$key"] = $description ? $description->getDescription() ? $description->getDescription() : '' : ''; 
            } 
        } 
 
        $result['geoLocations'] = $this->getGeoLocationList($offer); 
        $result['directors'] = $this->get('twig')->render('Slivki/admin/directors/list.html.twig', ['directors' => $offer->getDirectors()->toArray()]); 
        $result['antiTags'] = $this->get('twig')->render('Slivki/admin/tags/antitag_list.html.twig', ['tags' => $offer->getAntiTags()->toArray()]); 
        $result['codes'] = $offer->getLastActiveCodePool(); 
 
        $data['managerList'] = $entityManager->getRepository(UserGroup::class)->findOneByName('MANAGER')->getUsers(); 
        $data['currentManager'] = $offer->getManager(); 
        $result['managerOptions'] = $this->get('twig')->render('Slivki/admin/managers/options_list.html.twig', $data); 
        $result['phoneNumberList'] = $this->get('twig')->render('Slivki/admin/offers/phone_number_list.html.twig', ['offer' => $offer, 'belarusPhoneCode' => self::BELARUS_PHONE_CODE]); 
 
        $productFastDeliveryList = []; 
        if (null !== $offer->getProductFastDelivery()) { 
            foreach ($offer->getProductFastDelivery() as $item) { 
                $productFastDeliveryList[] = [ 
                    'productFastDeliveryId' => $item->getProductId(), 
                    'productFastDeliveryProductId' => $item->getProductId(), 
                    'productFastDeliveryDeliveryTime' => $item->getDeliveryTime(), 
                    'productFastDeliveryIsActive' => $item->isActive(), 
                ]; 
            } 
        } 
 
        $result['productFastDelivery'] = $this->get('twig')->render('Slivki/admin/offers/product_fast_delivery_list.html.twig', ['offerId' => $offer->getID(), 'productFastDeliveryList' => $productFastDeliveryList]); 
        $result['deliveryZoneList'] = $this->renderView('Slivki/admin/offers/delivery_zone_list.html.twig', ['offerId' => $offer->getID(), 'deliveryZoneList' => $foodDeliveryZoneRepository->getByOfferId($offer->getID())]); 
 
        $hotFeed = $entityManager->getRepository(HotFeed::class)->findBy(['entityTypeID' => Category::OFFER_CATEGORY_ID, 'entityID' => $offer->getID(), 'type' => HotFeed::TYPE_MAIN_PAGE]); 
        if ($hotFeed) { 
            $result['hotFeed'] = true; 
        } 
        $tourismHotFeed = $entityManager->getRepository(HotFeed::class)->findBy(['entityTypeID' => Category::OFFER_CATEGORY_ID, 'entityID' => $offer->getID(), 'type' => HotFeed::TYPE_OFFER_TOURISM_PAGE]); 
        if ($tourismHotFeed) { 
            $result['tourismHotFeed'] = true; 
        } 
        $description = $descriptionRepository->findOneBy(['entityID' => $ID, 'typeID' => EntityDescription::TYPE_FOOD_ORDER_DESCRIPTION_ID]); 
        if ($description) { 
            $result['foodOptionDescription'] = $description->getDescription(); 
        } 
        if ($offer->getDeliveryPrice()) { 
            $result['foodOptionDeliveryPrice'] = $offer->getDeliveryPrice(); 
        } 
        if ($offer->getSumForFreeDelivery()) { 
            $result['foodOptionLowerPrice'] = $offer->getSumForFreeDelivery(); 
        } 
 
        $result['foodList'] = $this->renderView( 
            'Slivki/admin/offers/offer_food_list_table.html.twig', 
            ['offer' => $this->foodOfferExtensionDao->findAllFoodOfferExtensionsByOfferId($ID)], 
        ); 
 
        $items = $entityManager->getRepository(ItemOfferExtension::class)->findBy(['offer' => $ID]); 
        if ($items) { 
            $result['items'] = $this->renderView('Slivki/admin/offers/offer_items_table.html.twig', ['items' => $items]); 
        } 
        $entityOption = $entityOptionRepository->findOneBy(['entityID' => $ID, 'entityTypeID' => EntityOption::OFFER_ENTITY_TYPE, 'name' => EntityOption::OPTION_ENDLESS_CODES]); 
        if ($entityOption) { 
            $result['isEndless'] = $entityOption->getValue(); 
        } 
        $createdOn = $offer->getCreatedOn()->setTime(0, 0)->modify('+30 days'); 
        $nowDate = new \DateTime(); 
        if ($nowDate > $createdOn && $user->hasRole(UserGroup::ROLE_MANAGER_ID)) { 
            $result['bannedAlias'] = true; 
        } 
        $bookedOption = $entityOptionRepository->findOneBy(['entityID' => $ID, 'entityTypeID' => EntityOption::BOOKING_RESERVED_DATES, 'name' => EntityOption::OPTION_BOOKING_DATES]); 
        if ($bookedOption) { 
            $dateToFormat = []; 
            foreach (explode(",", $bookedOption->getValue()) as $date) { 
                $dateToFormat[] = date('d.m.Y', strtotime($date)); 
            } 
            $result['bookedDates'] = implode(',', $dateToFormat); 
        } 
 
        $onlineOrderSettings = $offer->getOnlineOrderSettings(); 
        if (!$onlineOrderSettings) { 
            $onlineOrderSettings = new OnlineOrderSettings(); 
            $onlineOrderSettings->setOffer($offer); 
        } 
        $iikoUtil = AbstractDelivery::instance($offer); 
 
        $result['onlineOrderSettingsBox'] = $this->renderView('Slivki/admin/offers/online_order_settings.html.twig', [ 
            'onlineOrderSettings' => $onlineOrderSettings, 
            'allowedPaymentMethods' => $onlineOrderSettings->getAllowedPaymentMethods(), 
            'pickupLeadTime' => $onlineOrderSettings->getPickupLeadTime(), 
            'priceCodeDependsOnOrder' => $onlineOrderSettings->getPriceCodeDependsOnOrder(), 
            'pickupIntervalBetweenOrdersTime' => $iikoUtil::PICKUP_INTERVAL_BETWEEN_ORDERS_TIME, 
            'pickupNearlyEnabled' => $iikoUtil::PICKUP_NEARLY_ENABLED, 
            'pickupDisableTime' => $iikoUtil::PICKUP_DISABLE_TIME, 
            'deliverySchedules' => $deliveryScheduleRepository->findByOfferId($offer->getID()), 
            'deliveryWorkingTime' => $this->deliveryWorkingTimeService->getDeliveryWorkingTimeByOffer($offer), 
            'receivingOrdersSchedule' => $receivingOrdersScheduleService->getReceivingOrdersScheduleByOffer($offer), 
        ]); 
 
        $result['videoPackage'] = $this->videoPackageDtoGetter->getByOfferId($ID); 
        $result['offerNote'] = $offerNoteGetter->getOfferNote($ID); 
        $result['previewUrl'] = sprintf('%s?preview=true', $seoResourceService->getOfferUrlWithDomain($ID)); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_edit_comments") 
     */ 
    public function ajaxGetComments(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $ID = $request->request->get('id'); 
        $offer = $this->getOfferRepository()->find($ID); 
        if (!$offer) { 
            return new Response('false'); 
        } 
        $comments = $this->getCommentRepository()->findBy(['entityID' => $ID, 'typeID' => Comment::TYPE_OFFER_COMMENT], ['createdOn' => 'DESC'], 50); 
        $loadedCommentsCount = count($comments); 
        return new Response(json_encode(['html' => $this->get('twig')->render('Slivki/admin/offers/comments_list.html.twig', ['comments' => $comments, 'offer' => $offer]), 'loadedCommentsCount' => $loadedCommentsCount])); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_load_more_comments") 
     */ 
    public function ajaxLoadMoreComments(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $ID = $request->request->get('id'); 
        $offer = $this->getOfferRepository()->find($ID); 
        if (!$offer) { 
            return new Response('false'); 
        } 
        $lastCommentID = $request->request->get('lastCommentID'); 
        if (!$lastCommentID) { 
            $lastCommentID = PHP_INT_MAX; 
        } 
        $dql = "select comment from Slivki:Comment comment 
            where comment.entityID = :offerID 
              and comment.ID < :lastCommentID 
            order by comment.createdOn desc"; 
        $query = $this->getDoctrine()->getManager('admin')->createQuery($dql) 
            ->setParameter('offerID', $ID) 
            ->setParameter('lastCommentID', $lastCommentID); 
        $query->setMaxResults(50); 
        $comments = $query->getResult(); 
        $loadedCommentsCount = count($comments); 
 
        return new Response(json_encode(['html' => $this->get('twig')->render('Slivki/admin/offers/comments_list.html.twig', ['comments' => $comments, 'offer' => $offer]), 'loadedCommentsCount' => $loadedCommentsCount])); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_category_tree_by_city") 
     */ 
    public function ajaxGetCateoryTreeByCity(Request $request) { 
        $entityManager = $this->getEntityManager(); 
        $cityID = $request->request->get('cityID'); 
        $categoryRepository = $entityManager->getRepository(Category::class); 
        $data['categories'] = $categoryRepository->getCategoryTree(Category::OFFER_CATEGORY_ID, 0, $cityID); 
        $offerID = $request->request->get('offerID'); 
        $result['offerCategories'] = ''; 
        if ($offerID) { 
            $offerCategoryIDList = []; 
            $offer = $entityManager->getRepository(Offer::class)->find($offerID); 
            $offerCategoryList = $offer->getCategoriesByCity($cityID)->toArray(); 
            foreach ($offerCategoryList as $key => $offerCategory) { 
                if ($offerCategory->getDomainObjectID() <= Category::SUPPLIER_CATEGORY_TYPE) { 
                    $offerCategoryIDList[] = $offerCategory->getID(); 
                } else { 
                    unset($offerCategoryList[$key]); 
                } 
            } 
            $offerPaidCategoryList = $entityManager->getRepository(OfferPayedCategory::class)->getPayedCategoriesByEntityID($offerID, Category::OFFER_CATEGORY_ID); 
            $offerPaidCategoryIDList = []; 
            foreach ($offerPaidCategoryList as $offerPaidCategory) { 
                $offerPaidCategoryIDList[] = $offerPaidCategory->getCategoryID(); 
            } 
            $result['offerCategories'] = $this->get('twig')->render('Slivki/admin/offers/edit_offer_selected_categories.html.twig', [ 
                'offerCategoryList' => $offerCategoryList, 
                'offerPaidCategoryIDList' => $offerPaidCategoryIDList, 
                'defaultCategoryID' => $offer->getDefaultCategoryID(), 
                'offerPaidCategoryMobile' => [], 
            ]); 
            $data['selectedCategoryIDList'] = $offerCategoryIDList; 
        } 
        $result['categories'] = $this->get('twig')->render('Slivki/admin/categories/recursive_category_with_checkboxes_macro.html.twig', $data); 
        return new JsonResponse($result); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_edit_offer") 
     */ 
    public function ajaxEditOffer( 
        Request $request, 
        OfferCacheService $offerCacheService, 
        CacheService $cacheService, 
        ImageService $imageService, 
        KernelInterface $kernel, 
        CodePoolService $codePoolService, 
        Mailer $mailer, 
        CategoryBoxCacheService $categoryBoxCacheService 
    ) { 
        ini_set('memory_limit', '4G'); 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result['message'] = $this->validateOfferForm($request); 
        if ($result['message'] !== true) { 
            return new Response(json_encode($result)); 
        } 
 
        $result = $this->saveOffer($request, $offerCacheService, $cacheService, $imageService, $kernel, $codePoolService, $mailer, $categoryBoxCacheService); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_category_tree", name="/admin/offer/ajax_get_category_tree") 
     */ 
    public function ajaxGetCategoryTree(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $categoryRepository = $this->getDoctrine()->getRepository(Category::class); 
        $category = $categoryRepository->find($request->request->get('categoryID')); 
        $data['categories'] = $categoryRepository->getCategoryTree(Category::OFFER_CATEGORY_ID, 0, $category->getCity()->getID()); 
        $result['categories'] = $this->get('twig')->render('Slivki/admin/categories/recursive_category_with_checkboxes_macro.html.twig', $data); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_add_offer", name="/admin/offer/ajax_add_offer") 
     */ 
    public function ajaxAddOffer(Request $request, OfferCacheService $offerCacheService, CacheService $cacheService, ImageService $imageService, KernelInterface $kernel, CodePoolService $codePoolService, Mailer $mailer, CategoryBoxCacheService $categoryBoxCacheService) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result['message'] = $this->validateOfferForm($request); 
        if ($result['message'] !== true) { 
            return new Response(json_encode($result)); 
        } 
 
        $result = $this->saveOffer($request, $offerCacheService, $cacheService, $imageService, $kernel, $codePoolService, $mailer, $categoryBoxCacheService, true); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_upload_detail_images") 
     */ 
    public function ajaxUploadDetailImages(Request $request, KernelInterface $kernel) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result = array(); 
        $uploadedFile = $request->files->get('editOfferDetailsImagesUpload'); 
        $fs = new Filesystem(); 
        $logoPath = $kernel->getProjectDir() . Offer::DETAIL_MEDIA_PATH; 
        $fileName = $uploadedFile->getClientOriginalName(); 
        $result['originalFileName'] = $fileName; 
        while ($fs->exists($logoPath . $fileName)) { 
            $fileName = time() . '_' . $fileName; 
        } 
        $uploadedFile->move($logoPath, $fileName); 
 
        $result['imageURL'] = str_replace('/public', '', Offer::DETAIL_MEDIA_PATH) . $fileName; 
        $result['imageName'] = $fileName; 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_add_detail_medias") 
     */ 
    public function ajaxAddDetailMedias(Request $request) 
    { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result = []; 
        $imageID = $request->request->get('imageID'); 
        $imageURL = $request->request->get('imageURL'); 
        $isVideo = $request->request->getBoolean('video'); 
 
        $result['offerDetailMedias'] = $this->get('twig')->render( 
            'Slivki/admin/offers/add_detail_medias.html.twig', 
            [ 
                'imageID' => $imageID, 
                'imageURL' => $imageURL, 
                'isVideo' => $isVideo, 
            ] 
        ); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_upload_shop_images", name="/admin/offer/ajax_upload_shop_images") 
     */ 
    public function ajaxUploadShopImages(Request $request, KernelInterface $kernel) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result = array(); 
        $uploadedFile = $request->files->get('edit-offer-upload-shop-images'); 
        $fs = new Filesystem(); 
        $logoPath = $kernel->getProjectDir() . Offer::SHOP_MEDIA_PATH; 
        $fileName = $uploadedFile->getClientOriginalName(); 
        $result['originalFileName'] = $fileName; 
        while ($fs->exists($logoPath . $fileName)) { 
            $fileName = time() . '_' . $fileName; 
        } 
        $uploadedFile->move($logoPath, $fileName); 
 
        $result['imageURL'] = str_replace('/public', '', Offer::SHOP_MEDIA_PATH) . $fileName; 
        $result['imageName'] = $fileName; 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_add_shop_medias", name="/admin/offer/ajax_add_shop_medias") 
     */ 
    public function ajaxAddShopMedias(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = array(); 
        $imageID = $request->request->get('imageID'); 
        $imageURL = $request->request->get('imageURL'); 
        $imageName = $request->request->get('imageName'); 
 
        $result['offerShopMedias'] = $this->get('twig')->render('Slivki/admin/offers/add_shop_medias.html.twig', array('imageID' => $imageID, 'imageURL' => $imageURL, 'imageName' => $imageName)); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_add_teaser_medias", name="/admin/offer/ajax_add_teaser_medias") 
     */ 
    public function ajaxAddTeaserMedias(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = array(); 
        $imageURL = $request->request->get('imageURL'); 
        $imageName = $request->request->get('imageName'); 
 
        $result['offerTeaserMedias'] = $this->get('twig')->render('Slivki/admin/offers/add_teaser_medias.html.twig', array('imageURL' => $imageURL, 'imageName' => $imageName)); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_remove_media", name="/admin/offer/ajax_remove_media") 
     */ 
    public function ajaxRemoveMedia(Request $request, CacheService $cacheService) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $mediaID = $request->request->get('mediaID'); 
        $this->getEntityManager()->getConnection()->executeQuery('delete from media where id = ' . $mediaID); 
        $cacheService->deleteMedia($mediaID); 
        return new Response(''); 
    } 
 
    private function validateOfferForm(Request $request) { 
        $errorMessage = ''; 
 
        if ($request->request->get('edit-offer-title') == '') { 
            $errorMessage .= 'Введите имя акции!<br>'; 
        } 
        if (!$request->request->get('editOfferAllCityCategoryIDList')) { 
            $this->log('error'); 
            $errorMessage .= 'Выберите хотя бы одну категорию!<br>'; 
        } 
 
        if ($errorMessage != '') { 
            $result = array( 
                'title' => 'Ошибка!', 
                'message' => $errorMessage, 
                'type' => 'modal-danger' 
            ); 
            return $result; 
        } 
 
        return true; 
    } 
 
    private function saveOffer( 
        Request $request, 
        OfferCacheService $offerCacheService, 
        CacheService $cacheService, 
        ImageService $imageService, 
        KernelInterface $kernel, 
        CodePoolService $codePoolService, 
        Mailer $mailer, 
        CategoryBoxCacheService $categoryBoxCacheService, 
        $new = false 
    ) { 
        ini_set('max_execution_time', 600); 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $offerRepository = $entityManager->getRepository(Offer::class); 
        $requestOfferID = (int)$request->request->get('edit-offer-id'); 
 
        $session = $request->getSession(); 
        $offerPreviousActiveTill = null; 
        $offerIsVisible = false; 
        $debugLogger = null; 
        /** @var $offer \Slivki\Entity\Offer */ 
        if ($new) { 
            $offer = new Offer(); 
            $debugLogger = Logger::instance('saveOfferDebug-new-'); 
            $defaultCity = $this->cityRepository->getById($request->request->getInt('editOfferDefaultCityID')); 
            $offer->setDefaultCity($defaultCity); 
        } else { 
            $offer = $offerRepository->find($requestOfferID); 
            $offerPreviousActiveTill = $offer->getActiveTill(); 
            $offerIsVisible = $offer->isVisible(); 
 
            $debugLogger = Logger::instance('saveOfferDebug-' . $offer->getID()); 
        } 
 
        $debugLogger->info('start'); 
 
        $offer->setVersion($offer->getVersion() + 1); 
        $meOnMapName = trim($request->request->get('editOfferMeOnMapName')); 
        $offer->setMeOnMapName('' === $meOnMapName ? null : $meOnMapName); 
        $offerTitle = $request->request->get('edit-offer-title'); 
        $requestActiveSearchPosition = $request->request->get('edit-offer-active-search-position') ? true : false; 
        $requestSearchPosition = $request->request->get('edit-offer-search-position'); 
 
        $categoryIDList = explode(',', $request->request->get('editOfferAllCityCategoryIDList')); 
        $priceCategoryID = $request->request->get('priceCategoryDefault'); 
        $tourismPriceCategoryID = $request->request->get('priceCategoryTourism'); 
        $transportType = $request->request->get('transportType'); 
        if ($priceCategoryID) { 
            $categoryIDList[] = $priceCategoryID; 
        } 
        if ($tourismPriceCategoryID) { 
            $categoryIDList[] = $tourismPriceCategoryID; 
        } 
        if ($transportType) { 
            $categoryIDList[] = $transportType; 
        } 
        $categoryIDList = array_merge($categoryIDList, $request->request->get('genderCategory', [])); 
        $categoryIDList = array_merge($categoryIDList, $request->request->get('tourType', [])); 
        $currentCityID = $request->request->get('offerCategoryCitySelect'); 
        $currentCategories = $offer->getCategoriesByCity($currentCityID)->toArray(); 
        foreach ($currentCategories as $currentCategory) { 
            if (in_array($currentCategory->getID(), $categoryIDList) === false) { 
                $this->logOperatorAction($request, $requestOfferID, 'remove category ' . $currentCategory->getID(), OperatorActionLog::ADD_AND_REMOVE_FROM_CATEGORY_SALE_AND_OFFERS); 
                $offer->removeCategory($currentCategory); 
                $payedCategoryRepository = $entityManager->getRepository(OfferPayedCategoryMobile::class); 
                $payedCategory = $payedCategoryRepository->findOneBy(['categoryID' => $currentCategory->getID(), 'entityID' => $offer->getID()]); 
                if ($payedCategory) { 
                    $entityManager->remove($payedCategory); 
                } 
            } 
        } 
 
        $categories = $this->categoryRepository->findByIds(array_values($categoryIDList)); 
        foreach ($categories as $currentCategory) { 
            if ($offer->addCategory($currentCategory)) { 
                $this->logOperatorAction( 
                    $request, 
                    $requestOfferID, 
                    sprintf('add category %s',  $currentCategory->getID()), 
                    OperatorActionLog::ADD_AND_REMOVE_FROM_CATEGORY_SALE_AND_OFFERS, 
                ); 
            } 
        } 
 
        $price = $request->request->get('edit-offer-price', ''); 
        if ($price != '') { 
            $price = (float)str_replace(',', '.', $price); 
        } else { 
            $price = null; 
        } 
        $offer->setPrice($price); 
 
        $oldPrice = $request->request->get('editOfferOldPrice', ''); 
        if ($oldPrice != '') { 
            $oldPrice = (float)str_replace(',', '.', $oldPrice); 
        } else { 
            $oldPrice = null; 
        } 
        $offer->setOldPrice($oldPrice); 
 
        $offer->setHint($request->request->get('edit-offer-hint')); 
        if ($this->getUser()->hasRole(UserGroup::ROLE_ADMIN_ID)) { 
            $offer->setFree($request->request->get('edit-offer-free')); 
        } 
        $offer->setWithoutCodes($request->request->getBoolean('edit-offer-without-codes')); 
        $offer->setTitle($offerTitle); 
        $offer->setExplanationText($request->request->get('edit-offer-explanation-text')); 
        $offer->setOfferPrice($request->request->get('edit-offer-offer-price')); 
        $offer->setRegularPrice($request->request->get('edit-offer-regular-price')); 
        $offer->setDiscount($request->request->get('edit-offer-discount')); 
        $offer->setAdditionalPercents((int)$request->request->get('edit-offer-additional-percents')); 
        $offer->setAddress($request->request->get('edit-offer-address')); 
        $offer->setShowPriceInConditions($request->request->get('show-price-in-conditions')); 
        $offer->setHideFeatures($request->request->getBoolean('editOfferHideFeatures')); 
        $offer->setShowAltOffers($request->request->get('show-alt-offers')); 
        $offer->setCaptionName($request->request->get('edit-offer-caption-name')); 
        $offer->setCaptionColor($request->request->get('edit-offer-caption-color')); 
        $offer->setRegionalCaptionName($request->request->get('offerRegionalCaptionName')); 
        $offer->setRegionalCaptionColor($request->request->get('offerRegionalCaptionColor')); 
 
        $defaultCategoryId = $request->request->getInt('defaultCategoryID'); 
        if (0 !== $defaultCategoryId) { 
            $defaultCategory = $this->categoryRepository->getById($defaultCategoryId); 
            $offer->setDefaultCategoryID($defaultCategoryId); 
            $offer->setDefaultCity($defaultCategory->getCity()); 
        } 
 
        $offer->setLastModified(new \DateTime()); 
        $offer->setActiveSearchPosition($requestActiveSearchPosition); 
        $offer->setSearchPosition(mb_strtolower($requestSearchPosition)); 
        $offer->setCompanyName($request->request->get('companyName')); 
        $offer->setActiveCurrencyCalculator($request->request->get('edit-offer-active-currency-calculator')); 
        $offer->setTeaserLogoWidth($request->request->getInt('editOfferTeaserLogoWidth', 0)); 
        $offer->setTeaserLogoHeight($request->request->getInt('editOfferTeaserLogoHeight', 0)); 
        $offer->setBuyCodeButtonText($request->request->get('buyCodeButtonText', '')); 
        $offer->setBuyItemsButtonText($request->request->get('buyItemsButtonText', '')); 
        $offer->setAllowedBuyOnlyCode($request->request->getBoolean('allowedBuyOnlyCode')); 
        $offer->setTelegramBotShow($request->request->getBoolean('editOfferTelegramBotShow')); 
        $offer->setBuyCodeDisable($request->request->getBoolean('offerBuyCodeDisable')); 
        $offer->setHideInApp($request->request->getBoolean('offerHideInApp')); 
        $offer->setBrandboxEnabled($request->request->getBoolean('offerBrandboxEnabled')); 
        $offer->setDiscountDeliveryPopup(trim($request->request->get('discount-delivery-popup')) === '' ? null : trim($request->request->get('discount-delivery-popup'))); 
        $offer->setDiscountPickupPopup(trim($request->request->get('discount-pickup-popup')) === '' ? null : trim($request->request->get('discount-pickup-popup'))); 
        $offer->setExternalOfferLink(trim($request->request->get('external-offer-link')) === '' ? null : trim($request->request->get('external-offer-link'))); 
        $offer->setIsShowExternalOfferLink($request->request->getBoolean('is_show_external_offer_link')); 
 
        $offer->setDeliveryTimeTeaser($request->request->get('deliveryTimeTeaser')); 
        $offer->setFoodcourtInfoTeaser($request->request->get('foodcourtInfoTeaser')); 
        $offer->setFoodcourtInfoColorTeaser($request->request->get('foodcourtInfoColorTeaser')); 
        $offer->setTitleFontColor($request->request->get('titleFontColor')); 
        $offer->setIsIncludedInBeauty($request->request->getBoolean('isIncludedInBeauty')); 
        $offer->setQrCodes($request->request->getBoolean('isQrCodes')); 
        $offer->setRecurrentDisabled($request->request->getBoolean('recurrentDisabled')); 
        $offer->setAvailableOnFood($request->request->getBoolean('availableOnFood')); 
        $offer->setOnlineAutoOpened($request->request->getBoolean('onlineAutoOpened')); 
        $offer->setFoodcourtLogoEnabled($request->request->getBoolean('foodcourtLogoEnabled')); 
        $offer->setOnlineOrderGiftEnabled($request->request->getBoolean('onlineOrderGiftEnabled')); 
        $offer->setBuyCodeInAppOnly($request->request->getBoolean('buyCodeInAppOnly')); 
        $offer->setShowProductsInOfferDescription($request->request->getBoolean('showProductsInOfferDescription')); 
        $offer->setCheckAddressInOfferMenu($request->request->getBoolean('checkAddressInOfferMenu')); 
        $offer->setShowMapIconInApp($request->request->getBoolean('showMapIconInApp')); 
        $offer->setFestOffer($request->request->getBoolean('festOffer')); 
        $offer->setSeparateTabForCertificatesInApp($request->request->getBoolean('separateTabForCertificatesInApp')); 
        $offer->setUseUnusedCodes($request->request->getBoolean('useUnusedCodes')); 
 
        $offer->setYclientCompanyId($request->request->get('yclientCompanyId') ?: null); 
        $offer->setYclientAppKey($request->request->get('yclientAppKey') ?: null); 
 
        $allowedOnlineOrderTypes = \json_decode($request->request->get('allowedOnlineOrderTypes'), true); 
        $offer->setAllowedOnlineOrderTypes( 
            (null === $allowedOnlineOrderTypes || (0 === \count($allowedOnlineOrderTypes['site']) && 0 === \count($allowedOnlineOrderTypes['app']))) 
                ? null 
                : $allowedOnlineOrderTypes 
        ); 
        $offer->setOnlineOrderAllowedRemovedAt(null === $offer->getAllowedOnlineOrderTypes() ? new DateTimeImmutable() : null); 
 
        $allowedPaymentMethodsForCertificate = json_decode($request->request->get('allowedPaymentMethodsForCertificate'), true); 
        $offer->setAllowedPaymentMethodsForCertificate($allowedPaymentMethodsForCertificate); 
 
        $offer->setPartnerOnlineRegistrationAllowed($request->request->getBoolean('partnerOnlineRegistrationAllowed')); 
        $partnerOnlineRegistrationLink = trim($request->request->get('partnerOnlineRegistrationLink')); 
        $offer->setPartnerOnlineRegistrationLink(empty($partnerOnlineRegistrationLink) ? null : $partnerOnlineRegistrationLink); 
 
        $purchaseKoeff = $request->request->get('purchaseKoeff', ''); 
        if ($purchaseKoeff != '') { 
            $purchaseKoeff = (float)str_replace(',', '.', $purchaseKoeff); 
        } else { 
            $purchaseKoeff = null; 
        } 
        $offer->setPurchaseKoeff($purchaseKoeff); 
        if ($request->request->get('edit-offer-active-currency-calculator')) { 
            $bankCurrency = $entityManager->getRepository(BankCurrency::class)->find($request->request->get('edit-offer-bank-currency-id')); 
            if ($bankCurrency) { 
                $offer->setBankCurrency($bankCurrency); 
            } 
        } 
        $activeTill = date_create_from_format('d.m.Y H:i:s', $request->request->get('edit-offer-active-till') . '00:00:00'); 
        $currentTill = $offer->getActiveTill(); 
        $active = $request->request->getBoolean('edit-offer-active'); 
        $isActive = $offer->isActive(); 
        $showInHotFeed = $request->request->get('hotFeed') == 'on'; 
        $cityID = City::DEFAULT_CITY_ID; 
        foreach ($offer->getCategories() as $categoryItem) { 
            if ($categoryItem->getCity() && $categoryItem->getCity()->getID() != City::DEFAULT_CITY_ID) { 
                $cityID = $categoryItem->getCity()->getID(); 
                break; 
            } 
        } 
        $hotFeed = $entityManager->getRepository(HotFeed::class)->findBy(['entityTypeID' => Category::OFFER_CATEGORY_ID, 'entityID' => $offer->getID(), 'type' => HotFeed::TYPE_MAIN_PAGE]); 
        if (!$hotFeed && ($showInHotFeed || ($active && !$isActive) || ($active && date_format($activeTill, 'd') !== date_format($currentTill, 'd')))) { 
            $hotFeed = new HotFeed(); 
            $hotFeed->setCreatedOn(new \DateTime()); 
            $hotFeed->setEntityTypeID(Category::OFFER_CATEGORY_ID); 
            $hotFeed->setEntityID($offer->getID()); 
            $hotFeed->setCityID($cityID); 
            $entityManager->persist($hotFeed); 
            $entityManager->flush($hotFeed); 
        } else if ($hotFeed && (!$showInHotFeed || !$active)) { 
            $entityManager->remove($hotFeed[0]); 
            $entityManager->flush($hotFeed); 
        } 
        $showInTourismHotFeed = $request->request->get('tourismHotFeed') == 'on'; 
        $hotFeed = $entityManager->getRepository(HotFeed::class)->findBy(['entityTypeID' => Category::OFFER_CATEGORY_ID, 'entityID' => $offer->getID(), 'type' => HotFeed::TYPE_OFFER_TOURISM_PAGE]); 
        if ($showInTourismHotFeed && !$hotFeed) { 
            $hotFeed = new HotFeed(); 
            $hotFeed->setCreatedOn(new \DateTime()); 
            $hotFeed->setEntityTypeID(Category::OFFER_CATEGORY_ID); 
            $hotFeed->setEntityID($offer->getID()); 
            $hotFeed->setType(HotFeed::TYPE_OFFER_TOURISM_PAGE); 
            $hotFeed->setCityID($cityID); 
            $entityManager->persist($hotFeed); 
            $entityManager->flush($hotFeed); 
        } else if (!$showInTourismHotFeed && $hotFeed) { 
            $entityManager->remove($hotFeed[0]); 
            $entityManager->flush($hotFeed); 
        } 
        $offer->setHideNoveltyLabel($request->request->has('hideNoveltyLabel')); 
        $offer->setHideBannersInComments($request->request->has('hideBannersInComments')); 
        $activeSince = date_create_from_format('d.m.Y H:i:s', $request->request->get('edit-offer-active-since') . '00:00:00'); 
        $activeTill = date_create_from_format('d.m.Y H:i:s', $request->request->get('edit-offer-active-till') . '00:00:00'); 
        $offer->setActiveSince($activeSince); 
        $offer->setActiveTill($activeTill); 
        $isHidden = $offer->isHidden(); 
        $hidden = $request->request->getBoolean('edit-offer-hidden'); 
        $offer->setHidden($hidden); 
        $codeActiveTill = date_create_from_format('d.m.Y H:i:s', $request->request->get('edit-offer-code-active-till') . '00:00:00'); 
        $offer->setCodeActiveTill($codeActiveTill); 
        $user = $entityManager->find(User::class, $this->getUser()->getID()); 
 
        $entityManager->persist($offer); 
        if ($new) { 
            if ($user) { 
                $user->addCreatedOffer($offer); 
                $entityManager->flush($user); 
                if ($user->hasRole(UserGroup::ROLE_JUNIOR)) { 
                    $offer->setNeedReview(true); 
                } 
            } 
        } 
 
        if (!$offer->isNeedReview() || $user->hasRole(UserGroup::ROLE_REVIEWER) || $user->hasRole(UserGroup::ROLE_ADMIN_ID)) { 
            if ($active) { 
                $warningMessage = []; 
                $errorMessage = []; 
                if (count($request->request->get('edit-offer-detail-medias', [])) == 0) { 
                    $errorMessage[] = "главное изображение"; 
                } 
                if (!$offer->getTeaserMedia() && $request->request->get('editOfferTeaserImage') == '') { 
                    $errorMessage[] = "тизер"; 
                } 
                if (count($errorMessage) > 0) { 
                    $result['errorMessage'] = 'Не введены следующие данные: ' . implode(',', $errorMessage); 
                    return $result; 
                } 
                if (count($warningMessage) > 0) { 
                    $result['warningMessage'] = 'Акция сохранена, проверте следующие данные: ' . implode(',', $warningMessage); 
                } 
            } 
            $offer->setActive($active); 
            if (($offer->isNeedReview() || $offer->isOnReview()) && ($user->hasRole(UserGroup::ROLE_REVIEWER) || $user->hasRole(UserGroup::ROLE_ADMIN_ID))) { 
                $offer->setNeedReview(false); 
                $offer->setOnReview(false); 
            } 
            $entityManager->flush($offer); 
            if (!$offerIsVisible && $offer->isVisible()) { 
                $offer->setRenewedOn(new \DateTime()); 
                $entityManager->flush($offer); 
            } 
        } else { 
            if ($request->request->get('sendOnReview') && $offer->isNeedReview()) { 
                $offer->setOnReview(true); 
                $entityManager->flush($offer); 
                $reviewers = $entityManager->find(UserGroup::class, UserGroup::ROLE_REVIEWER)->getUsers(); 
                if (!empty($reviewers)) { 
                    foreach ($reviewers as $reviewer) { 
                        $message = $mailer->createMessage(); 
                        $message->setSubject('Новая акция на проверке') 
                            ->setFrom("info@slivki.by", 'Slivki.by') 
                            ->setTo($reviewer->getEmail()) 
                            ->setBody("<b>Акция: </b>" . $offer->getTitle(), 'text/html'); 
                        $mailer->send($message); 
                    } 
                } 
            } 
        } 
        $offerID = $offer->getID(); 
 
        if (!$new && ($active != $isActive || $hidden != $isHidden)) { 
            if ($active && !$hidden) { 
                $this->getCommentRepository()->updateCommentEntityHidden($offerID, Comment::TYPE_OFFER_COMMENT, 'false'); 
            } else { 
                $this->getCommentRepository()->updateCommentEntityHidden($offerID, Comment::TYPE_OFFER_COMMENT, 'true'); 
            } 
        } 
 
        $fastDelivery = $request->request->get('fastDelivery'); 
 
        /** @var ProductFastDeliveryRepository $productFastDeliveryDql */ 
        $repositoryProductFastDelivery = $this->getEntityManager()->getRepository(ProductFastDelivery::class); 
        $repositoryProductFastDelivery->removeNotesByOffer($offer); 
 
        if ($fastDelivery) { 
            foreach ($fastDelivery as $itemFastDelivery) { 
                if (!$itemFastDelivery['productId']) { 
                    continue; 
                } 
 
                $productFastDelivery = new ProductFastDelivery($offer, $itemFastDelivery['productId'], $itemFastDelivery['deliveryTime'], isset($itemFastDelivery['isActive'])); 
 
                $offer->addProductFastDelivery($productFastDelivery); 
            } 
        } 
 
        $mediaRepository = $entityManager->getRepository(Media::class); 
        $mediaTypeRepository = $entityManager->getRepository(MediaType::class); 
        $shopMedias = $request->request->get('edit-offer-shop-medias', []); 
        foreach ($shopMedias as $key => $value) { 
            $explodedValue = explode('||', $value); 
            $shopMediaID = $explodedValue[0]; 
            $shopMediaFileName = $explodedValue[1]; 
            if (strpos($shopMediaID, 'new-shop-media') !== false) { 
                $media = new Media(); 
                $media->setEntityID($offerID); 
                $media->setMediaType($mediaTypeRepository->find(MediaType::TYPE_OFFER_SHOP_PHOTO_ID)); 
                $media->setPath(MediaType::TYPE_OFFER_SHOP_PHOTO_PATH); 
                $media->setName($shopMediaFileName); 
                $entityManager->persist($media); 
            } else { 
                $media = $mediaRepository->find($shopMediaID); 
            } 
            $media->setPath(MediaType::TYPE_OFFER_SHOP_PHOTO_PATH); 
            $media->setSortOrder($key); 
            $entityManager->flush($media); 
            $entityManager->detach($media); 
        } 
 
        $detailMedias = $request->request->get('edit-offer-detail-medias', []); 
        foreach ($detailMedias as $key => $value) { 
            $explodedValue = explode('||', $value); 
            $detailMediaID = $explodedValue[0]; 
            $detailMediaFileName = $explodedValue[1]; 
            $isVideoDetail = isset($explodedValue[2]) ? (bool) $explodedValue[2] : false; 
            $detailMediaFileName = explode('/', $detailMediaFileName); 
            if (strpos($detailMediaID, 'new-detail-media') !== false) { 
                $this->saveMedia( 
                    $imageService, 
                    $offerID, 
                    MediaType::TYPE_OFFER_DETAIL_PHOTO_ID, 
                    MediaType::TYPE_OFFER_DETAIL_PHOTO_PATH, 
                    array_values(array_slice($detailMediaFileName, -1))[0], 
                    $key + 1, 
                    true, 
                    $isVideoDetail 
                ); 
            } else { 
                $media = $mediaRepository->find($detailMediaID); 
                $media->setSortOrder($key + 1); 
                $entityManager->flush($media); 
                $entityManager->detach($media); 
            } 
        } 
 
        $teaserMediaFileName = $request->request->get('editOfferTeaserImage'); 
        $offerTeaserMedia = null; 
        if ($teaserMediaFileName) { 
            $editOfferDesktopTeaserImage = $request->request->get('editOfferDesktopTeaserImage', ''); 
            $editOfferMobileTeaserImage = $request->request->get('editOfferMobileTeaserImage', ''); 
            $editOfferAppTeaserImage = $request->request->get('editOfferAppTeaserImage', ''); 
 
            if ($editOfferDesktopTeaserImage != '') { 
                $offerTeaserMedia = $this->setOfferTeaserMedia($cacheService, $imageService, $entityManager, Media\OfferTeaserMedia::TYPE, $offer, $editOfferDesktopTeaserImage); 
            } 
            if ($editOfferMobileTeaserImage != '') { 
                $this->setOfferTeaserMedia($cacheService, $imageService, $entityManager, Media\OfferMobileTeaserMedia::TYPE, $offer, $editOfferMobileTeaserImage); 
            } 
            if ($editOfferAppTeaserImage != '') { 
                $this->setOfferTeaserMedia($cacheService, $imageService, $entityManager, Media\OfferAppTeaserMedia::TYPE, $offer, $editOfferAppTeaserImage); 
            } 
        } 
 
        $editOfferTopBlockImage = $request->request->get('editOfferTopBlockImage'); 
        if ($editOfferTopBlockImage) { 
            foreach ($offer->getTopBlockMedias() as $mediaToRemove) { 
                $offer->removeTopBlockMedia($mediaToRemove); 
                $entityManager->remove($mediaToRemove); 
                $cacheService->deleteMedia($mediaToRemove->getID()); 
            } 
            $offerTopBlockMedia = new Media\OfferTopBlockMedia(); 
            $offerTopBlockMedia->setName($editOfferTopBlockImage); 
            $offerTopBlockMedia->setPath(MediaType::DEFAULT_IMAGE_PATH); 
            $offer->addTopBlockMedia($offerTopBlockMedia); 
        } 
 
        $editOfferTopBlockMobileImage = $request->request->get('editOfferTopBlockMobileImage'); 
        if ($editOfferTopBlockMobileImage) { 
            foreach ($offer->getTopBlockMobileMedias() as $mediaToRemove) { 
                $offer->removeTopBlockMobileMedia($mediaToRemove); 
                $entityManager->remove($mediaToRemove); 
                $cacheService->deleteMedia($mediaToRemove->getID()); 
            } 
            $offerTopBlockMobileMedia = new Media\OfferTopBlockMobileMedia(); 
            $offerTopBlockMobileMedia->setName($editOfferTopBlockMobileImage); 
            $offerTopBlockMobileMedia->setPath(MediaType::DEFAULT_IMAGE_PATH); 
            $offer->addTopBlockMobileMedia($offerTopBlockMobileMedia); 
        } 
 
        $editOfferOnlineOrderPopupLogoImage = $request->request->get('editOfferOnlineOrderPopupLogoImage'); 
        if (null !== $editOfferOnlineOrderPopupLogoImage) { 
            foreach ($offer->getOnlineOrderPopupLogoMedias() as $mediaToRemove) { 
                $offer->removeOnlineOrderPopupLogoMedia($mediaToRemove); 
                $entityManager->remove($mediaToRemove); 
                $cacheService->deleteMedia($mediaToRemove->getID()); 
            } 
 
            $onlineOrderPopupLogoMedia = new OnlineOrderPopupLogoMedia(); 
            $onlineOrderPopupLogoMedia->setName($editOfferOnlineOrderPopupLogoImage); 
            $onlineOrderPopupLogoMedia->setPath(MediaType::DEFAULT_IMAGE_PATH); 
            $offer->addOnlineOrderPopupLogoMedia($onlineOrderPopupLogoMedia); 
        } 
 
        $editOfferCrtPdfBgImage = $request->request->get('editOfferCrtPdfBgImage'); 
        if ($editOfferCrtPdfBgImage) { 
            foreach ($offer->getGiftCertificatePdfBgMedias() as $mediaToRemove) { 
                $offer->removeGiftCertificatePdfBgMedia($mediaToRemove); 
                $entityManager->remove($mediaToRemove); 
                $cacheService->deleteMedia($mediaToRemove->getID()); 
            } 
            $giftCertificatePdfBgMedia = new Media\GiftCertificatePdfBgMedia(); 
            $giftCertificatePdfBgMedia->setName($editOfferCrtPdfBgImage); 
            $giftCertificatePdfBgMedia->setPath(MediaType::DEFAULT_IMAGE_PATH); 
            $offer->addGiftCertificatePdfBgMedia($giftCertificatePdfBgMedia); 
        } 
 
        $mapLogoImage = $request->request->get('editOfferMapLogoImage'); 
        if ($mapLogoImage) { 
            foreach ($offer->getMapLogoMedias() as $mediaToRemove) { 
                $offer->removeMapLogoMedia($mediaToRemove); 
                $cacheService->deleteMedia($mediaToRemove->getID()); 
            } 
            $offerMapLogoMedia = new OfferMapLogoMedia(); 
            $offerMapLogoMedia->setName($mapLogoImage); 
            $offerMapLogoMedia->setPath(MediaType::DEFAULT_IMAGE_PATH); 
            $offer->addMapLogoMedia($offerMapLogoMedia); 
        } 
 
        $deliveryZoneImage = $request->request->get('editOfferDeliveryZoneImage'); 
        if (null !== $deliveryZoneImage) { 
            foreach ($offer->getDeliveryZoneMedias() as $mediaToRemove) { 
                $offer->removeDeliveryZoneMedia($mediaToRemove); 
                $cacheService->deleteMedia($mediaToRemove->getID()); 
            } 
            $offerDeliveryZoneMedia = new OfferDeliveryZoneMedia(); 
            $offerDeliveryZoneMedia->setName($deliveryZoneImage); 
            $offerDeliveryZoneMedia->setPath(MediaType::DEFAULT_IMAGE_PATH); 
            $offer->addDeliveryZoneMedia($offerDeliveryZoneMedia); 
        } 
 
        $additionalTeaserMediaFileName = $request->request->get('editOfferAdditionalTeaserImage'); 
        if ($additionalTeaserMediaFileName) { 
            $this->saveMedia($imageService, $offerID, MediaType::TYPE_OFFER_ADDITIONAL_TEASER_ID, MediaType::TYPE_OFFER_ADDITIONAL_TEASER_PATH, $additionalTeaserMediaFileName); 
        } 
 
        $hotFeedfIconMediaFileName = $request->request->get('editOfferHotFeedIcon'); 
        if ($hotFeedfIconMediaFileName) { 
            $this->saveMedia($imageService, $offerID, MediaType::TYPE_HOT_FEED_OFFER_ICON_IMAGE_ID, MediaType::TYPE_HOT_FEED_ICON_IMAGE_PATH, $hotFeedfIconMediaFileName); 
        } 
 
        $offerTeaserLogoFileName = $request->request->get('editOfferTeaserLogo'); 
        if ($offerTeaserLogoFileName) { 
            $this->saveMedia($imageService, $offerID, MediaType::TYPE_OFFER_TEASER_LOGO_ID, MediaType::TYPE_OFFER_TEASER_LOGO_PATH, $offerTeaserLogoFileName); 
        } 
 
        $seoRepository = $entityManager->getRepository(Seo::class); 
        $requestAlias = $request->request->get('edit-offer-alias'); 
        $createdOn = $offer->getCreatedOn()->setTime(0, 0)->modify('+30 days'); 
        $nowDate = new \DateTime(); 
        $entitySeo = $seoRepository->getByEntity(SeoRepository::RESOURCE_URL_OFFER_DETAILS, $offerID); 
        $currentAlias = $entitySeo ? $entitySeo->getMainAlias() : ''; 
        if (($requestAlias && $requestAlias != $currentAlias) && $nowDate > $createdOn && $user->hasRole(UserGroup::ROLE_MANAGER_ID) && !$user->hasRole(UserGroup::ROLE_ADMIN_ID)) { 
            $result['message'] = array( 
                'title' => 'Ошибка!', 
                'message' => 'В этой акции недоступно изменение ссылки, обратитесь к администратору', 
                'type' => 'modal-danger' 
            ); 
            return $result; 
        } 
        $alias = new Seo(); 
        $alias->setMainAlias($requestAlias ? $requestAlias : ''); 
        $alias->setEntityID($offerID); 
        $alias->setActive(true); 
        $alias->setMetaTitle($request->request->get('edit-offer-meta-title')); 
        $alias->setMetaDescription($request->request->get('edit-offer-meta-description')); 
        $alias->setMetaKeywords($request->request->get('edit-offer-meta-keywords')); 
        $alias->setResourceURL('Slivki:Default:details'); 
 
        $offerCity = $offerRepository->getOfferCity($offerID); 
        if (null !== $offerCity) { 
            $alias->setDomain($offerCity->getDomain()); 
        } 
        if ($requestAlias && !$seoRepository->setAlias($alias)) { 
            $result['message'] = array( 
                'title' => 'Ошибка!', 
                'message' => 'Алиас ' . $requestAlias . ' уже существует!', 
                'type' => 'modal-danger' 
            ); 
            return $result; 
        } 
 
        $codeCostFromForm = $request->request->get('edit-offer-code-cost'); 
        if (!empty($codeCostFromForm) && is_numeric($codeCostFromForm)) { 
            $offer->setCodeCost($codeCostFromForm); 
        } else { 
            $siteSettings = $entityManager->getRepository(SiteSettings::class)->find(1); 
            if (null !== $offerCity && $new) { 
                if ($offerCity->getID() !== City::DEFAULT_CITY_ID) { 
                    $codeCost = $offerCity->getID() === City::TASHKENT_CITY_ID 
                        ? SiteSettings::TASHKENT_CODE_COST 
                        : $siteSettings->getRegionsCodeCost(); 
                    $offer->setCodeCost($codeCost); 
                } else { 
                    $offer->setCodeCost(null); 
                } 
            } 
        } 
 
        $descriptionRepository = $entityManager->getRepository(EntityDescription::class); 
        $descriptions = [ 
            [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_OFFER_CONDITIONS_ID]), 
                'request' => $request->request->get('description-condition'), 
                'type' => EntityDescription::TYPE_OFFER_CONDITIONS_ID 
            ], 
            [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_OFFER_FEATURES_ID]), 
                'request' => $request->request->get('description-features'), 
                'type' => EntityDescription::TYPE_OFFER_FEATURES_ID 
            ], 
            [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_OFFER_LOCATION_ID]), 
                'request' => $request->request->get('description-location'), 
                'type' => EntityDescription::TYPE_OFFER_LOCATION_ID 
            ], 
            [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_OFFER_LOGO_ID]), 
                'request' => $request->request->get('description-logo'), 
                'type' => EntityDescription::TYPE_OFFER_LOGO_ID 
            ], 
            [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_OFFER_LEGAL_ID]), 
                'request' => $request->request->get('description-legal'), 
                'type' => EntityDescription::TYPE_OFFER_LEGAL_ID 
            ], [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_OFFER_WORKING_HOURS_ID]), 
                'request' => strip_tags($request->request->get('edit-offer-common-working-hours', ''), '<strong><em><span><br>'), 
                'type' => EntityDescription::TYPE_OFFER_WORKING_HOURS_ID 
            ], 
            [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_VENDOR_CONDITION]), 
                'request' => $request->request->get('vendorCondition'), 
                'type' => EntityDescription::TYPE_VENDOR_CONDITION, 
            ], 
            [ 
                'repository' => $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_BRIEF_DELIVERY_CONDITION]), 
                'request' => $request->request->get('briefDeliveryCondition'), 
                'type' => EntityDescription::TYPE_BRIEF_DELIVERY_CONDITION, 
            ], 
        ]; 
        foreach ($descriptions as $description) { 
            if (mb_strpos($description['request'], 'WebKitFormBoundary') !== false) { 
                return ['errorMessage' => 'Произошла ошибка при сохранении описания! Данные не сохранены! Попробуйте еще раз!']; 
            } 
            if (!$description['repository']) { 
                $description['repository'] = new EntityDescription(); 
                $description['repository']->setTypeID($description['type']); 
                $description['repository']->setOffer($offer); 
                $offer->addDescription($description['repository']); 
                $entityManager->persist($description['repository']); 
            } 
            $description['repository']->setDescription($this->deleteExtraLines(trim($description['request']))); 
            $offer->setLuceneReindex(true); 
            $entityManager->flush($description['repository']); 
        } 
 
        $editDescriptionList = array_filter($request->request->all(), function ($key) { 
            return strpos($key, 'editDescription') === 0; 
        }, ARRAY_FILTER_USE_KEY); 
        $result['addedDescriptionIDList'] = []; 
        foreach ($editDescriptionList as $key => $description) { 
            if (mb_strpos($description, 'WebKitFormBoundary') !== false) { 
                return ['errorMessage' => 'Произошла ошибка при сохранении описания! Данные не сохранены! Попробуйте еще раз!']; 
            } 
            $descriptionID = str_replace('editDescription', '', $key); 
            $descriptionID = explode('_', $descriptionID); 
            $sortOrder = $descriptionID[1]; 
            $descriptionID = $descriptionID[0]; 
            if (strpos($descriptionID, 'new-') !== false) { 
                $offerDescription = new EntityDescription(); 
                $offer->addDescription($offerDescription); 
                $offerDescription->setDescription($this->setImageRatio($kernel, $description)); 
                $offerDescription->setTypeID(EntityDescription::TYPE_OFFER_DESCRIPTION_ID); 
                $offerDescription->setOffer($offer); 
                $entityManager->persist($offerDescription); 
                $result['addedDescriptionIDList'][$descriptionID] = $offerDescription->getID(); 
            } else { 
                $offerDescription = $entityManager->find(EntityDescription::class, $descriptionID); 
            } 
            if ($offerDescription) { 
                if (strip_tags($description) != "") { 
                    $offerDescription->setDescription($this->setImageRatio($kernel, $description)); 
                } 
                $offerDescription->setSortOrder($sortOrder); 
                $entityManager->flush($offerDescription); 
            } 
        } 
 
        $offerNote = strip_tags($request->request->get('offerNote', ''), '<strong><em><span><br>'); 
        $this->messageBus->dispatch(new EditOfferNoteCommand($offerID, $offerNote)); 
 
        $result['addedDescriptionSliderImageIDList'] = []; 
        $requestGalleryImageList = $request->request->get('editOfferDescriptionGalery', []); 
        foreach ($requestGalleryImageList as $key => $value) { 
            $explodedValue = explode('||', $value); 
            $offerDescriptionSliderImageID = $explodedValue[0]; 
            $offerDescriptionSliderImageUri = EntityDescriptionSliderImage::IMAGE_PATH . $explodedValue[1]; 
            if (strpos($offerDescriptionSliderImageID, 'newOfferDescriptionGaleryImage') !== false) { 
                $offerDescriptionSliderImageIDExploded = explode('_', $offerDescriptionSliderImageID); 
                $offerDescriptionID = $offerDescriptionSliderImageIDExploded[1]; 
                if (strpos($offerDescriptionID, 'new') !== false) { 
                    $offerDescriptionID = $result['addedDescriptionIDList'][$offerDescriptionID]; 
                } 
                $offerDescription = $entityManager->find(EntityDescription::class, $offerDescriptionID); 
                $offerDescriptionSliderImage = new EntityDescriptionSliderImage(); 
                $offerDescriptionSliderImage->setEntityDescription($offerDescription); 
                $offerDescriptionSliderImage->setImageUrl($offerDescriptionSliderImageUri); 
                $entityManager->persist($offerDescriptionSliderImage); 
                $result['addedDescriptionSliderImageIDList'][$offerDescriptionSliderImageID] = $offerDescriptionSliderImage->getID(); 
            } else { 
                $offerDescriptionSliderImage = $entityManager->find(EntityDescriptionSliderImage::class, $offerDescriptionSliderImageID); 
            } 
            $offerDescriptionSliderImage->setSortOrder($key); 
            $entityManager->flush($offerDescriptionSliderImage); 
            $entityManager->detach($offerDescriptionSliderImage); 
        } 
 
        $geoLocationList = $session->get('geoLocationList', []); 
        $geoLocationRepository = $entityManager->getRepository(GeoLocation::class); 
        foreach ($geoLocationList as $geoLocationItem) { 
            $geoLocation = null; 
            if (strpos($geoLocationItem['ID'], 'new-') === false) { 
                $geoLocation = $geoLocationRepository->find($geoLocationItem['ID']); 
            } 
            if (!$geoLocation) { 
                $geoLocation = new GeoLocation(); 
                $offer->addGeoLocation($geoLocation); 
                $entityManager->persist($geoLocation); 
            } 
            $geoLocation->setCity($geoLocationItem['city']); 
            $geoLocation->setStreet($geoLocationItem['street']); 
            $geoLocation->setHouse($geoLocationItem['house']); 
            $geoLocation->setLatitude($geoLocationItem['latitude']); 
            $geoLocation->setLongitude($geoLocationItem['longitude']); 
            $geoLocation->setBigMapMarker($geoLocationItem['bigMapMarker']); 
            if ($geoLocationItem['description'] == '') { 
                // parse supplier brand name 
                $descriptionLogo = $request->request->get('description-logo', ''); 
                $descriptionLogo = strip_tags($descriptionLogo); 
                preg_match('/"(.*?)"/', $descriptionLogo, $match); 
                if (isset($match[0])) { 
                    $geoLocationItem['description'] = $match[0]; 
                } 
            } 
            $geoLocation->setDescription($geoLocationItem['description']); 
            $geoLocation->setLabel($geoLocationItem['label']); 
            $geoLocation->setWorkingHours($geoLocationItem['workingHours']); 
            $geoLocation->setPickupPointPartnerID($geoLocationItem['pickupPointPartnerID']); 
            $geoLocation->setPickupPointBelTransSatDepotID(empty($geoLocationItem['pickupPointBelTransSatDepotID']) ? null : trim($geoLocationItem['pickupPointBelTransSatDepotID'])); 
            $geoLocation->setPickupPointSchedule($geoLocationItem['pickupPointSchedule']); 
            $geoLocation->setBepaidCredentials(empty($geoLocationItem['bepaidCredentials']) ? null : \trim($geoLocationItem['bepaidCredentials'])); 
            $geoLocation->setCallbackChatId($geoLocationItem['callbackChatId']); 
 
            if (!empty($geoLocationItem['latitude']) && !empty($geoLocationItem['longitude'])) { 
                $point = (new Factory()) 
                    ->createPoint( 
                        Dimension::DIMENSION_2D, 
                        [ 
                            'x' => (float) $geoLocationItem['latitude'], 
                            'y' => (float) $geoLocationItem['longitude'], 
                            'z' => null, 
                            'm' => null, 
                        ], 
                        GeoLocation::SRID 
                    ); 
 
                $geoLocation->setPoint($point); 
            } 
 
            $cityArea = $entityManager->getRepository(CityArea::class)->find($geoLocationItem['cityArea']); 
            if ($cityArea) { 
                $cityArea->addGeoLocations($geoLocation); 
                $entityManager->flush($cityArea); 
            } else { 
                $entityManager->flush($geoLocation); 
            } 
            $session->remove('geoLocationList'); 
        } 
 
        $addressPosition = $request->request->get('edit-offer-address-position'); 
        foreach (json_decode($addressPosition, true) as $address) { 
            if (strpos($address['addressID'], 'new-') === false) { 
                $geoLocation = $geoLocationRepository->find($address['addressID']); 
                $geoLocation->setSortOrder($address['position']); 
            } 
        } 
 
        $requestAntiTagIDList = $request->request->get('admin-antitag-id') ? $request->request->get('admin-antitag-id') : []; 
        foreach ($requestAntiTagIDList as $index => $tagID) { 
            $tag = $entityManager->getRepository(AntiTag::class)->find($tagID); 
            if ($tag) { 
                if ($request->request->get('admin-antitag-deleted')[$index] == "true") { 
                    $offer->deleteAntiTag($tag); 
                } else { 
                    if ($tag->getTag() != $request->request->get('admin-antitag-tag')[$index]) { 
                        $tag->setTag($request->request->get('admin-antitag-tag')[$index]); 
                        $entityManager->flush($tag); 
                    } 
                    $offer->addAntiTag($tag); 
                } 
            } 
        } 
 
        $offer->setTelegram($request->request->get('editTelegramInfo')); 
        $offer->setViber($request->request->get('editViberInfo')); 
        $offer->setMessengerCallBack( 
            null !== $request->request->get('editMessengerCallBack') 
            ? $this->serializer->serialize($request->request->get('editMessengerCallBack'), SerializerConfig::JSON) 
            : null 
        ); 
 
        $requestPhoneNumberList = array_filter($request->request->all(), static function ($key) { 
            return strpos($key, 'editOfferPhoneNumber_') === 0; 
        }, ARRAY_FILTER_USE_KEY); 
 
        foreach ($requestPhoneNumberList as $keyPhoneNumber => $phoneNumber) { 
            $requestPhoneNumberList[$keyPhoneNumber] = self::BELARUS_PHONE_CODE . $phoneNumber; 
        } 
 
        $previousPhoneNumberList = $offer->getPhoneNumbers()->toArray(); 
        $requestPhoneNumberIDList = []; 
        foreach ($requestPhoneNumberList as $key => $requestPhoneNumber) { 
            $requestPhoneNumberID = explode('_', $key); 
            if (!isset($requestPhoneNumberID[1])) { 
                continue; 
            } 
            $requestPhoneNumberID = $requestPhoneNumberID[1]; 
            $requestPhoneNumberIDList[] = $requestPhoneNumberID; 
            $requestPhoneNumber = trim($requestPhoneNumber); 
            if (!strpos($key, 'new') === false) { 
                if ($requestPhoneNumber != '') { 
                    $phoneNumber = new PhoneNumber(); 
                    $phoneNumber->setNumber($requestPhoneNumber); 
                    $phoneNumber->setLink(CommonUtil::phoneNumber2Link($requestPhoneNumber)); 
                    $phoneNumber->setLabel($request->request->get('editOfferPhoneNumberLabel_' . $requestPhoneNumberID)); 
                    $phoneNumberGeoLocationIDList = $request->request->get('editOfferPhoneNumberAddress_' . $requestPhoneNumberID, []); 
                    foreach ($phoneNumberGeoLocationIDList as $phoneNumberGeoLocationID) { 
                        $phoneNumberGeoLocation = $entityManager->getRepository(GeoLocation::class)->find($phoneNumberGeoLocationID); 
                        if ($phoneNumberGeoLocation) { 
                            $phoneNumber->addGeoLocation($phoneNumberGeoLocation); 
                        } 
                    } 
                    $offer->addPhoneNumber($phoneNumber); 
                } 
            } else { 
                $phoneNumber = $entityManager->getRepository(PhoneNumber::class)->find($requestPhoneNumberID); 
                if ($phoneNumber) { 
                    $phoneNumber->setNumber($requestPhoneNumber); 
                    $phoneNumber->setLink(CommonUtil::phoneNumber2Link($requestPhoneNumber)); 
                    $phoneNumber->setLabel($request->request->get('editOfferPhoneNumberLabel_' . $requestPhoneNumberID)); 
                    $phoneNumberGeoLocationIDList = $request->request->get('editOfferPhoneNumberAddress_' . $requestPhoneNumberID, []); 
                    foreach ($phoneNumberGeoLocationIDList as $phoneNumberGeoLocationID) { 
                        $phoneNumberGeoLocation = $entityManager->getRepository(GeoLocation::class)->find($phoneNumberGeoLocationID); 
                        if ($phoneNumberGeoLocation) { 
                            $phoneNumber->addGeoLocation($phoneNumberGeoLocation); 
                        } 
                    } 
                    foreach ($phoneNumber->getGeoLocations() as $phoneNumberCurrentGeoLocation) { 
                        if (!in_array($phoneNumberCurrentGeoLocation->getID(), $phoneNumberGeoLocationIDList)) { 
                            $phoneNumber->removeGeoLocation($phoneNumberCurrentGeoLocation); 
                        } 
                    } 
                    $entityManager->flush($phoneNumber); 
                } 
            } 
        } 
        foreach ($previousPhoneNumberList as $currentPhoneNumber) { 
            if (!in_array($currentPhoneNumber->getID(), $requestPhoneNumberIDList)) { 
                $offer->removePhoneNumberByID($currentPhoneNumber->getID()); 
                $offerCacheService->deletePhoneNumber($currentPhoneNumber->getID()); 
                $entityManager->remove($currentPhoneNumber); 
                $entityManager->flush($currentPhoneNumber); 
            } 
        } 
 
        $offer->setLuceneReindex(true); 
        $entityManager->flush($offer); 
 
        $offerMailingTeaserMedia = $offer->getMailingTeaserMedia(); 
        if ($offer->hasNotDefaultCityCategory()) { 
            if (!$offer->getCaptionName()) { 
                foreach ($offer->getMailingTeaserMedias() as $mediaToRemove) { 
                    $offer->removeMailingTeaserMedia($mediaToRemove); 
                    $entityManager->remove($mediaToRemove); 
                    $cacheService->deleteMedia($mediaToRemove->getID()); 
                } 
                $entityManager->flush(); 
            } else { 
                $imageName = $imageService->saveMailingTeaserImage($offer); 
                if ($imageName) { 
                    foreach ($offer->getMailingTeaserMedias() as $mediaToRemove) { 
                        $offer->removeMailingTeaserMedia($mediaToRemove); 
                        $entityManager->remove($mediaToRemove); 
                        $cacheService->deleteMedia($mediaToRemove->getID()); 
                    } 
 
                    if (!$offerMailingTeaserMedia) { 
                        $offerMailingTeaserMedia = new Media\OfferMailingTeaserMedia(); 
                    } 
                    $offerMailingTeaserMedia->setName($imageName); 
                    $offerMailingTeaserMedia->setPath($offer->getTeaserMedia()->getPath()); 
                    $offer->addMailingTeaserMedia($offerMailingTeaserMedia); 
                    $entityManager->flush(); 
                    foreach ($offerMailingTeaserMedia->getSizes() as $mediasSize) { 
                        $imageService->resizeImage($offerMailingTeaserMedia, $mediasSize->getWidth(), $mediasSize->getHeight()); 
                    } 
                } 
            } 
        } else if ($offerMailingTeaserMedia) { 
            foreach ($offer->getMailingTeaserMedias() as $mediaToRemove) { 
                $offer->removeMailingTeaserMedia($mediaToRemove); 
                $entityManager->remove($mediaToRemove); 
                $cacheService->deleteMedia($mediaToRemove->getID()); 
            } 
            $entityManager->flush(); 
        } 
 
        $offerShopMedias = $mediaRepository->getOfferShopMedias($offerID); 
        $result['offerShopMedias'] = $this->renderView('Slivki/admin/offers/shop_medias.html.twig', [ 
            'images' => $offerShopMedias, 
            'interiorGalleryMediaIds' => $this->interiorGalleryDao->getByOfferId($offerID), 
        ]); 
        $offerDetailMedias = $mediaRepository->getOfferDetailMedias($offerID); 
        $result['offerDetailMedias'] = $this->get('twig')->render('Slivki/admin/offers/detail_medias.html.twig', array('images' => $offerDetailMedias)); 
 
        $manager = null; 
        $requestDirectorIDList = $request->request->get('admin-director-id', []); 
        foreach ($requestDirectorIDList as $index => $directorID) { 
            $director = $entityManager->getRepository(Director::class)->find($directorID); 
            if ($director) { 
                if ($request->request->get('admin-director-deleted')[$index] == "true") { 
                    $director->removeOffer($offer); 
                } else if (!$offer->getDirectors()->contains($director)) { 
                    $director->addOffer($offer); 
                    $manager = $director->getManager(); 
                    if ($manager) { 
                        $manager->addOffer($offer); 
                    } 
                } 
                $entityManager->flush($director); 
            } 
        } 
        if (!$manager) { 
            $offerManagerID = $request->request->get('offerManager', 0); 
            if ($offerManagerID > 0) { 
                $offerManager = $entityManager->find(User::class, $offerManagerID); 
                if ($offerManager) { 
                    $offerManager->addOffer($offer); 
                } 
            } 
        } 
 
        // Set Paid Categories and refresh positions 
        $offerPayedCategoryRepository = $entityManager->getRepository(OfferPayedCategory::class); 
        $offerCategoryPositionRepository = $entityManager->getRepository(OfferCategoryPosition::class); 
        if ($offer->isActive() && $offer->isInActivePeriod()) { 
            $categoriesToRefreshIDList = []; 
            $requestOfferPayedCategoryIDList = $request->request->get('payedCategories') ? $request->request->get('payedCategories') : []; 
            $offerPayedCategories = $offerPayedCategoryRepository->getPayedCategoriesByEntityID($offerID, Category::OFFER_CATEGORY_ID); 
 
            /** * @var OfferPayedCategory $offerPayedCategory */ 
            foreach ($offerPayedCategories as $offerPayedCategory) { 
                $requestOfferPayedCategoryIDListKey = array_search($offerPayedCategory->getCategoryID(), $requestOfferPayedCategoryIDList); 
                if ($requestOfferPayedCategoryIDListKey === false) { 
                    $entityManager->remove($offerPayedCategory); 
                    $categoriesToRefreshIDList[] = $offerPayedCategory->getCategoryID(); 
                    $this->logOperatorAction($request, $requestOfferID, "remove paid category " . $offerPayedCategory->getCategoryID(), OperatorActionLog::SET_PAID_OFFER_CATEGORY); 
                } else { 
                    unset($requestOfferPayedCategoryIDList[$requestOfferPayedCategoryIDListKey]); 
                } 
            } 
            $entityManager->flush(); 
 
            foreach ($requestOfferPayedCategoryIDList as $categoryID) { 
                $offerPayedCategory = new OfferPayedCategory(); 
                $offerPayedCategory->setEntityID($offerID); 
                $offerPayedCategory->setCategoryID($categoryID); 
                $offerPayedCategory->setPosition($offerPayedCategoryRepository->getNextOfferPayedCategoryPosition($categoryID)); 
                $entityManager->persist($offerPayedCategory); 
                $entityManager->flush(); 
                $categoriesToRefreshIDList[] = $categoryID; 
                $this->logOperatorAction($request, $requestOfferID, "add paid category " . $offerPayedCategory->getCategoryID(), OperatorActionLog::SET_PAID_OFFER_CATEGORY); 
            } 
 
            $offerCategoryPositionList = $offerCategoryPositionRepository->getOfferCategoryPositionByEntityID($offerID, Category::OFFER_CATEGORY_ID); 
            foreach ($offerCategoryPositionList as $offerCategoryPosition) { 
                if (!in_array($offerCategoryPosition->getCategoryID(), $categoryIDList)) { 
                    $entityManager->remove($offerCategoryPosition); 
                } 
            } 
            $entityManager->flush(); 
            $unlimitedCodes = $request->request->get('edit-offer-unlimited-codes') == 'on'; 
            $entityOption = $entityManager->getRepository(EntityOption::class)->findOneBy([ 
                'entityID' => $offerID, 
                'entityTypeID' => EntityOption::OFFER_ENTITY_TYPE, 
                'name' => EntityOption::OPTION_CODES_UNLIMITED, 
            ]); 
            if ($unlimitedCodes) { 
                if (!$entityOption) { 
                    $entityOption = new EntityOption(); 
                    $entityManager->persist($entityOption); 
                    $entityOption->setEntityID($offerID); 
                    $entityOption->setEntityTypeID(EntityOption::OFFER_ENTITY_TYPE); 
                    $entityOption->setName(EntityOption::OPTION_CODES_UNLIMITED); 
                    $entityManager->flush(); 
                } 
            } else { 
                if ($entityOption) { 
                    $entityManager->remove($entityOption); 
                    $entityManager->flush(); 
                } 
            } 
            foreach ($categoryIDList as $categoryID) { 
                $offerCategoryPosition = $offerCategoryPositionRepository->findOneBy(['entityID' => $offerID, 'categoryID' => $categoryID]); 
                if (!$offerCategoryPosition) { 
                    $position = 99999; 
                    if ($categoryID == Category::NEW_OFFER_CATEGORY_ID) { 
                        $position = 25; 
                    } 
                    $offerCategoryPosition = new OfferCategoryPosition(); 
                    $offerCategoryPosition->setEntityID($offerID); 
                    $offerCategoryPosition->setCategoryID($categoryID); 
                    $offerCategoryPosition->setPosition($position); 
                    $entityManager->persist($offerCategoryPosition); 
                    $entityManager->flush(); 
                    if ($categoryID == Category::NEW_OFFER_CATEGORY_ID) { 
                        $sql = 'update offer_category_position set position = position + 1  
                          where category_id = ' . Category::NEW_OFFER_CATEGORY_ID . ' and position >= ' . $position . ' and entity_id <> ' . $offerID; 
                        $entityManager->getConnection()->executeQuery($sql); 
                    } 
                } 
            } 
 
            foreach (array_unique($categoriesToRefreshIDList) as $categoryID) { 
                $this->refreshOfferCategoriesPosition($kernel, $categoryID, false); 
            } 
        } else { 
            $offerCategoryPositionList = $offerCategoryPositionRepository->getOfferCategoryPositionByEntityID($offerID, Category::OFFER_CATEGORY_ID); 
            foreach ($offerCategoryPositionList as $offerCategoryPosition) { 
                $entityManager->remove($offerCategoryPosition); 
            } 
            $offerPayedCategoryList = $offerPayedCategoryRepository->getPayedCategoriesByEntityID($offerID, Category::OFFER_CATEGORY_ID); 
            foreach ($offerPayedCategoryList as $offerPayedCategory) { 
                $entityManager->remove($offerPayedCategory); 
            } 
            $entityManager->flush(); 
        } 
 
        if ($offerPreviousActiveTill && $offerPreviousActiveTill < $offer->getActiveTill()) { 
            $renewedOffer = $entityManager->getRepository(RenewedOffer::class)->findBy([ 
                'offer' => $offer, 
                'sentUserNotification' => false 
            ]); 
            if (!$renewedOffer) { 
                $renewedOffer = new RenewedOffer(); 
                $renewedOffer->setOffer($offer); 
                $renewedOffer->setOfferPreviousActiveTill($offerPreviousActiveTill); 
                $entityManager->persist($renewedOffer); 
                $entityManager->flush(); 
            } 
        } 
 
        $descriptionRepository = $entityManager->getRepository(EntityDescription::class); 
        $description = $descriptionRepository->findOneBy(['entityID' => $offerID, 'typeID' => EntityDescription::TYPE_FOOD_ORDER_DESCRIPTION_ID]); 
        $requestDescription = trim($request->request->get('edit-offer-food-delivery-description', '')); 
        if (!$description) { 
            $description = new EntityDescription(); 
            $description->setOffer($offer); 
            $description->setTypeID(EntityDescription::TYPE_FOOD_ORDER_DESCRIPTION_ID); 
            $entityManager->persist($description); 
        } 
        $description->setDescription($requestDescription); 
        $offer->setDeliveryPrice((double)str_replace(',', '.', $request->request->get('edit-offer-food-delivery-price'))); 
        $offer->setSumForFreeDelivery((double)str_replace(",", ".", $request->request->get('edit-offer-food-lower-delivery-price'))); 
 
        $requestOfferItems = json_decode($request->request->get('offerItems'), true); 
        $offerItems = $offer->getItems(); 
        if (is_array($requestOfferItems)) { 
            foreach ($offerItems as $offerItem) { 
                $deleteItem = true; 
                foreach ($requestOfferItems as $requestOfferItem) { 
                    if ($requestOfferItem['id'] == $offerItem->getID()) { 
                        $deleteItem = false; 
                        break; 
                    } 
                } 
                if ($deleteItem) { 
                    $offerCacheService->deleteExtension($offerItem->getID()); 
                    $entityManager->remove($offerItem); 
                } 
            } 
            foreach ($requestOfferItems as $requestOfferItem) { 
                $requestOfferItemID = $requestOfferItem['id']; 
                if (strpos($requestOfferItemID, 'new') !== false) { 
                    $offerItem = new ItemOfferExtension(); 
                    $offerItem->setOffer($offer); 
                    $entityManager->persist($offerItem); 
                } else { 
                    $offerItem = $entityManager->find(ItemOfferExtension::class, $requestOfferItemID); 
                } 
                $offerItem->setName($requestOfferItem['name']); 
                $offerItem->setPrice((float)str_replace(',', '.', $requestOfferItem['price'])); 
                $offerItem->setOfferPrice((float)str_replace(',', '.', $requestOfferItem['offerPrice'])); 
                if (trim($requestOfferItem['codePrice']) == '') { 
                    $offerItem->setCodePrice(null); 
                } else { 
                    $offerItem->setCodePrice((float)str_replace(',', '.', $requestOfferItem['codePrice'])); 
                } 
                $offerItem->setDescription($requestOfferItem['description']); 
                $offerItem->setCodePrefix($requestOfferItem['prefix']); 
            } 
        } 
        $bookedDates = $request->request->get('edit-offer-booked-dates'); 
        if ($bookedDates != '') { 
            $bookedDates = explode(',', trim($bookedDates)); 
            usort($bookedDates, function ($a, $b) { 
                return strtotime($a) - strtotime($b); 
            }); 
            $bookedDates = implode(",", $bookedDates); 
            $entityOption = $entityManager->getRepository(EntityOption::class)->findOneBy([ 
                "entityID" => $offerID, 
                "entityTypeID" => EntityOption::BOOKING_RESERVED_DATES, 
                "name" => EntityOption::OPTION_BOOKING_DATES 
            ]); 
            if (!$entityOption) { 
                $entityOption = new EntityOption(); 
                $entityOption->setEntityID($offer->getID()); 
                $entityOption->setCreatedOn(new \DateTime()); 
                $entityManager->persist($entityOption); 
            } 
            $entityOption->setEntityTypeID(EntityOption::BOOKING_RESERVED_DATES); 
            $entityOption->setLastModified(new \DateTime()); 
            $entityOption->setName(EntityOption::OPTION_BOOKING_DATES); 
            $entityOption->setValue($bookedDates); 
        } 
 
        $entityManager->flush(); 
 
        $offerForSlivkiDelivery = $request->request->getBoolean('offerForSlivkiDelivery'); 
        $slivkiDeliveryOption = $entityManager->getRepository(EntityOption::class)->findBy([ 
            'entityID' => $offerID, 
            'name' => EntityOption::OPTION_SLIVKI_DELIVERY 
        ]); 
        $slivkiDeliveryOptionCount = count($slivkiDeliveryOption); 
 
        if ($offerForSlivkiDelivery && $slivkiDeliveryOptionCount == 0) { 
            $slivkiDeliveryOption = new EntityOption(); 
            $slivkiDeliveryOption->setName(EntityOption::OPTION_SLIVKI_DELIVERY); 
            $slivkiDeliveryOption->setEntityID($offerID); 
            $slivkiDeliveryOption->setEntityTypeID(EntityOption::OFFER_ENTITY_TYPE); 
            $entityManager->persist($slivkiDeliveryOption); 
        } elseif (!$offerForSlivkiDelivery and $slivkiDeliveryOptionCount > 0) { 
            foreach ($slivkiDeliveryOption as $option) { 
                $entityManager->remove($option); 
            } 
        } 
 
        $this->videoPackageSaver->save( 
            $offerID, 
            $request->request->get('videoPackageTitle'), 
            $request->request->get('videoPackagePicturePath') 
        ); 
 
        $this->offerFoodDeliveryZoneSaver->save($offer, $request->request->get('foodDeliveryZone', [])); 
        $entityManager->flush(); 
 
        $offerItems = $entityManager->getRepository(ItemOfferExtension::class)->findBy(['offer' => $offerID]); 
        if ($offerItems) { 
            $result['items'] = $this->renderView('Slivki/admin/offers/offer_items_table.html.twig', ['items' => $offerItems]); 
        } 
        $result['lastModified'] = $offer->getLastModified()->format('Y-m-d H:i:s'); 
        $result['message'] = array( 
            'title' => 'Успех!', 
            'message' => 'Акция успешно сохранена!', 
            'type' => 'modal-success' 
        ); 
 
        $sql = 'select id from offer_extension where offer_id = ' . $offerID; 
        $extensionIDList = $entityManager->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_COLUMN); 
        foreach ($offerCacheService->getExtensions($offerID) as $extensionCached) { 
            if (!in_array($extensionCached->getID(), $extensionIDList)) { 
                $offerCacheService->deleteExtension($extensionCached->getID()); 
            } 
        } 
        $debugLogger->info('1000'); 
        $this->messageBus->dispatch(new CreateOfferStatusLogCommand($offerID, $offer->getStatus()->getValue(), $this->getUser()->getID())); 
        $this->logOperatorAction($request, $offerID, "save offer", OperatorActionLog::SAVE_SALE_OR_OFFER); 
        $debugLogger->info('1500'); 
        $offerCacheService->reloadOfferCache($offerID); 
        $debugLogger->info('2000'); 
        $categoryBoxCacheService->setTeaser($offer); 
        $debugLogger->info('3000'); 
        $this->offerResponseCacheService->reloadByOfferId($offerID); 
 
        return $result; 
    } 
 
    private function deleteExtraLines($description, $needSpace = false) { 
        $newLine = '<p> </p>'; 
        $countSymbols = strlen($newLine); 
        $completed = false; 
        $spaceDeleted = false; 
        while (!$completed) { 
            $description = trim($description); 
            if (substr($description, -$countSymbols) == $newLine) { 
                $spaceDeleted = true; 
                $description = substr($description, 0, -$countSymbols); 
            } else { 
                $completed = true; 
            } 
        } 
        if ($spaceDeleted and $needSpace) { 
            $description .= $newLine; 
        } 
        return $description; 
    } 
 
    /** 
     * @Route("/admin/offer/crop_teaser_image") 
     */ 
    public function cropTeaserImage(Request $request, KernelInterface $kernel) { 
        $imagePath = $request->request->get('imagePath'); 
        $selection = $request->request->get('selection'); 
        if (!$imagePath || !$selection) { 
            return new Response(); 
        } 
        $teaserMediaFileName = basename($imagePath); 
        $realPath = $kernel->getProjectDir() . '/public'; 
        $selection = json_decode($selection); 
        $x = $selection->x > 0 ? $selection->x : 0; 
        $y = $selection->y > 0 ? $selection->y : 0; 
        $imagine = new Imagine(); 
        $image = $imagine->open($realPath . $imagePath); 
        $image->crop(new Point($x, $y), new Box($selection->width, $selection->height)); 
        $fileName = time() . "_" . $teaserMediaFileName; 
        $fileSystem = new Filesystem(); 
        while ($fileSystem->exists($realPath . ImageService::MEDIA_ROOT . ImageService::INITIAL_PATH . MediaType::TYPE_OFFER_TEASER_PATH . $fileName)) { 
            $fileName = time() . '_' . $fileName; 
        } 
        $newFilePath = ImageService::MEDIA_ROOT . ImageService::INITIAL_PATH . MediaType::TYPE_OFFER_TEASER_PATH . $fileName; 
        $image->save($realPath . $newFilePath); 
        return new Response($newFilePath); 
    } 
 
    private function setOfferTeaserMedia( 
        CacheService $cacheService, 
        ImageService $imageService, 
        EntityManager $entityManager, 
        $mediaTypeID, 
        Offer $offer, 
        $teaserMediaFileName 
    ) { 
        $fileName = basename($teaserMediaFileName); 
        switch ($mediaTypeID) { 
            case Media\OfferAppTeaserMedia::TYPE: 
                $offerTeaserMedia = new Media\OfferAppTeaserMedia(); 
                break; 
            case Media\OfferMobileTeaserMedia::TYPE: 
                $offerTeaserMedia = new Media\OfferMobileTeaserMedia(); 
                break; 
            default: 
                $offerTeaserMedia = new Media\OfferTeaserMedia(); 
        } 
        $offerTeaserMedia->setName($fileName); 
        $offerTeaserMedia->setPath(MediaType::TYPE_OFFER_TEASER_PATH); 
        switch ($mediaTypeID) { 
            case Media\OfferAppTeaserMedia::TYPE: 
                foreach ($offer->getAppTeaserMedias() as $mediaToRemove) { 
                    $offer->removeAppTeaserMedia($mediaToRemove); 
                    $entityManager->remove($mediaToRemove); 
                    $cacheService->deleteMedia($mediaToRemove->getID()); 
                } 
                $offer->addAppTeaserMedia($offerTeaserMedia); 
                $imageService->getImageURLCached($offerTeaserMedia, ImageService::OFFER_APP_TEASER_WIDTH, ImageService::OFFER_APP_TEASER_HEIGHT); 
                break; 
            case Media\OfferMobileTeaserMedia::TYPE: 
                foreach ($offer->getMobileTeaserMedias() as $mediaToRemove) { 
                    $offer->removeMobileTeaserMedia($mediaToRemove); 
                    $entityManager->remove($mediaToRemove); 
                    $cacheService->deleteMedia($mediaToRemove->getID()); 
                } 
                $offer->addMobileTeaserMedia($offerTeaserMedia); 
                $imageService->getImageURLCached($offerTeaserMedia, ImageService::OFFER_MOBILE_TEASER_WIDTH, ImageService::OFFER_MOBILE_TEASER_HEIGHT); 
                break; 
            default: 
                foreach ($offer->getTeaserMedias() as $mediaToRemove) { 
                    $offer->removeTeaserMedia($mediaToRemove); 
                    $entityManager->remove($mediaToRemove); 
                    $cacheService->deleteMedia($mediaToRemove->getID()); 
                } 
                $offer->addTeaserMedia($offerTeaserMedia); 
                $imageService->getImageURLCached($offerTeaserMedia, ImageService::OFFER_TEASER_WIDTH, ImageService::OFFER_TEASER_HEIGHT); 
        } 
        return $offerTeaserMedia; 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_upload_description_images", name="/admin/offer/ajax_upload_description_images") 
     */ 
    public function ajaxUploadDescriptionImages(Request $request, KernelInterface $kernel) { 
        $imageFolder = $kernel->getProjectDir() . Offer::DESCRIPTION_IMAGES_PATH; 
 
        $uploadedFile = $request->files->get('file'); 
        if ($uploadedFile) { 
            $fs = new Filesystem(); 
            $newFileName = time() . '_' . $uploadedFile->getClientOriginalName(); 
 
            while ($fs->exists($imageFolder . $newFileName)) { 
                $newFileName = time() . '_' . $newFileName; 
            } 
            $imagine = new Imagine(); 
            $image = $imagine->open($uploadedFile->getRealPath()); 
            $imageSize = $image->getSize(); 
            $returnFileName = $newFileName; 
            if ($imageSize->getWidth() > 1100) { 
                $returnFileName = OfferRepository::RESIZED_IMAGE_PREFIX . $newFileName; 
                $newImageSize = $imageSize->widen(1100); 
                $image->resize($newImageSize); 
                $image->save($imageFolder . $returnFileName); 
            } 
            $uploadedFile->move($imageFolder, $newFileName); 
 
            return new Response(json_encode(array('location' => $returnFileName))); 
        } else { 
            // Notify editor that the upload failed 
            header("HTTP/1.0 500 Server Error"); 
        } 
    } 
 
    /** 
     * @Route("/admin/ajax/get_order_by_code") 
     */ 
    public function ajaxGetOrderByCode(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = []; 
        $code = $request->request->get("orderCode"); 
        $offerID = $request->request->get("offerID"); 
        $offer = $this->getOfferRepository()->find($offerID); 
        if ($offer) { 
            if ($offerID != Offer::PETROL_OFFER_ID) { 
                $dql = "select orderDetail from Slivki:OfferOrderDetails orderDetail join orderDetail.offerOrder offerOrder where offerOrder.offerID = :offerID and orderDetail.code = :code"; 
                $orderDetail = $this->getDoctrine()->getManager()->createQuery($dql)->setParameters(["offerID" => $offerID, "code" => $code])->setMaxResults(1)->getResult(); 
            } else { 
                $dql = "select orderDetail, codeOption from Slivki:OfferOrderDetails orderDetail  
                  join orderDetail.offerOrder offerOrder  
                  join Slivki:EntityOption codeOption with orderDetail.ID = codeOption.entityID 
                  where offerOrder.offerID = :offerID and orderDetail.code = :code"; 
                $orderDetailsWithOption = $this->getDoctrine()->getManager()->createQuery($dql) 
                    ->setParameters(["offerID" => $offerID, "code" => $code]) 
                    ->getResult(); 
                $orderDetail = []; 
                $orderDetailOption = []; 
                foreach ($orderDetailsWithOption as $item) { 
                    if ($item instanceof OfferOrderDetails) { 
                        $orderDetail[] = $item; 
                    } else { 
                        $orderDetailOption[count($orderDetail) - 1][$item->getName()] = $item->getValue(); 
                    } 
                } 
 
            } 
            if ($orderDetail) { 
                $offerOrder = $orderDetail[0]->getOfferOrder(); 
            } else { 
                $result['result'] = "fail"; 
                return new Response(json_encode($result)); 
            } 
            if ($offerOrder) { 
                $date = $offerOrder->getCreatedOn(); 
                $result['date'] = $date->format('d.m.Y H:m'); 
                $result['email'] = $offerOrder->getUser()->getEmail(); 
                $result['result'] = "success"; 
                if ($offerID == Offer::PETROL_OFFER_ID) { 
                    $result['car_number'] = ''; 
                    $result['phone_number'] = ''; 
                    if (isset($orderDetailOption[0]['car_number'])) { 
                        $result['car_number'] = $orderDetailOption[0]['car_number']; 
                    } 
                    if (isset($orderDetailOption[0]['phone_number'])) { 
                        $result['phone_number'] = $orderDetailOption[0]['phone_number']; 
                    } 
                } 
                $orderDetails = $offerOrder->getOfferOrderDetails()->toArray(); 
                $codes = []; 
                for ($j = 0; $j < count($orderDetails); $j++) { 
                    array_push($codes, $orderDetails[$j]->getCode()); 
                } 
                $currentPhone = $offerOrder->getUser()->getCurrentPhone(); 
                $result['currentPhone'] = $currentPhone ? $currentPhone->getPhoneNumber() . ' ' : ''; 
                $result['code'] = $codes; 
                return new Response(json_encode($result)); 
            } else { 
                $result['result'] = "fail"; 
                return new Response(json_encode($result)); 
            } 
        } else { 
            $result['result'] = "fail"; 
            return new Response(json_encode($result)); 
        } 
    } 
 
    /** 
     * @Route("/admin/ajax_get_codes") 
     */ 
    public function ajaxGetCodes(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = []; 
        $offerID = $request->request->get('offerID'); 
        $offer = $this->getOfferRepository()->find($offerID); 
        $user = $this->getUser(); 
        $manager = $offer->getManager(); 
        if ($offer) { 
            if ($offer->getID() == Offer::BOOKING_OFFER_ID && (!$user->hasRole(UserGroup::ROLE_ADMIN_ID) && $manager->getID() != $user->getID() && $user->getEmail() != 'volga@slivki.by')) { 
                $result['data'] = array([0 => 'недоступно', 1 => 'недоступно', 2 => 'недоступно']); 
                return new Response(json_encode($result)); 
            } 
            $start = $request->request->get('start'); 
            $length = $request->request->get('length'); 
            $orders = $request->request->get('order'); 
            foreach ($orders as $order) { 
                if ($order['column'] == 0) { 
                    $dir = $order['dir']; 
                    if ($offerID != Offer::PETROL_OFFER_ID) { 
                        $offerOrders = $this->getOfferOrderRepository()->findBy(array('offerID' => $offerID, 'status' => [OfferOrder::STATUS_CONFIRM, OfferOrder::STATUS_CONFIRM_FREE_IMPLICITLY]), ['createdOn' => $dir], $length, $start); 
                    } else { 
                        $dql = "select offerOrder, codeOption from Slivki:OfferOrder offerOrder 
                          join offerOrder.offerOrderDetails offerOrderDetails 
                          join offerOrder.offer offer 
                          join Slivki:EntityOption codeOption with offerOrderDetails.ID = codeOption.entityID  
                          where offer.ID = :offerID 
                          order by offerOrderDetails.createdOn $dir"; 
                        $offerOrdersWithOptions = $this->getDoctrine()->getManager()->createQuery($dql) 
                            ->setParameter('offerID', $offerID) 
                            ->setFirstResult($start) 
                            ->setMaxResults($length) 
                            ->getResult(); 
                        $offerOrders = []; 
                        $offerOrdersOptions = []; 
                        foreach ($offerOrdersWithOptions as $item) { 
                            if ($item instanceof OfferOrder) { 
                                $offerOrders[] = $item; 
                            } else { 
                                $offerOrdersOptions[count($offerOrders) - 1][$item->getName()] = $item->getValue(); 
                            } 
                        } 
                    } 
                } 
            } 
            $orders = []; 
            if (!$user->hasRole(UserGroup::ROLE_ADMIN_ID) && $offerID == 137760) { 
                $isHideCode = true; 
            } else { 
                $isHideCode = false; 
            } 
            for ($i = 0; $i < count($offerOrders); $i++) { 
                $order = []; 
                $codes = []; 
                $user = $offerOrders[$i]->getUser(); 
                $order[1] = $user->getCurrentPhone() ? $user->getCurrentPhone()->getPhoneNumber() . ' ' . $user->getEmail() : $user->getEmail(); 
                $date = $offerOrders[$i]->getCreatedOn(); 
                $order[0] = $date->format('d.m.Y H:i:s'); 
                $orderDetails = $offerOrders[$i]->getOfferOrderDetails()->toArray(); 
                for ($j = 0; $j < count($orderDetails); $j++) { 
                    $offerExtension = $orderDetails[0]->getOfferExtension(); 
                    if ($offerExtension instanceof ItemOfferExtension && !$user->hasRole(UserGroup::ROLE_ADMIN_ID)) { 
                        array_push($codes, "****-****"); 
                    } else { 
                        if ($isHideCode) { 
                            array_push($codes, $orderDetails[$j]->getCode(true)); 
                        } else { 
                            array_push($codes, $orderDetails[$j]->getCode()); 
                        } 
                    } 
                } 
                if (count($codes) == 0) { 
                    $length++; 
                    continue; 
                } 
                $order[2] = $codes; 
                if ($offerID == Offer::PETROL_OFFER_ID) { 
                    $order[3] = ''; 
                    $order[4] = ''; 
                    if (isset($offerOrdersOptions[$i]['car_number'])) { 
                        $order[3] = $offerOrdersOptions[$i]['car_number']; 
                    } 
                    if (isset($offerOrdersOptions[$i]['phone_number'])) { 
                        $order[4] = $offerOrdersOptions[$i]['phone_number']; 
                    } 
                } 
                array_push($orders, $order); 
            } 
            $result['data'] = $orders; 
            return new Response(json_encode($result)); 
        } else { 
            return new Response(""); 
        } 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_generate_codes_pool") 
     */ 
    public function ajaxGenerateCodesPool(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = array(); 
        $generatedCoupons = array(); 
        $offerID = $request->request->get('offerID'); 
        $codePoolGeneratorAmount = $request->request->get('codePoolGeneratorAmount'); 
        $offerCodePool = null; 
        if ($offerID && $request->request->get('newPool') != '1') { 
            $entityManager = $this->getDoctrine()->getManager("admin"); 
            $offerRepository = $entityManager->getRepository(Offer::class); 
            $offer = $offerRepository->find($offerID); 
            $offerCodePool = $offer->getLastActiveCodePool(); 
        } 
        if ($request->request->get('isRandomCodes') == 'true') { 
            $codeNumberList = ''; 
            if ($offerCodePool) { 
                $codeNumberList = $offerCodePool->getCodesUsed() . $offerCodePool->getCodesFree() . $offerCodePool->getCodesReserved(); 
            } 
            do { 
                $codeNumber = mt_rand(000, 9999) . '-' . mt_rand(100, 999); 
                if ($offerID == Offer::BOOKING_OFFER_ID) { 
                    $codeNumber = 'BOOK-' . $codeNumber; 
                } 
                if (strpos($codeNumberList, $codeNumber) !== false) { 
                    continue; 
                } 
                $codeNumberList .= $codeNumber; 
                $generatedCoupons[] = $codeNumber; 
            } while (count($generatedCoupons) < $codePoolGeneratorAmount); 
        } else { 
            if ($offerCodePool != null) { 
                $generatedCoupons = $offerCodePool->getNewFreeCodes($codePoolGeneratorAmount, 9999, $offerID == Offer::BOOKING_OFFER_ID ? 'BOOK-' : ''); 
            } else { 
                $tempOfferCodePool = new OfferCodePool; 
                $generatedCoupons = $tempOfferCodePool->getNewFreeCodes($codePoolGeneratorAmount, 9999, $offerID == Offer::BOOKING_OFFER_ID ? 'BOOK-' : ''); 
            } 
        } 
        $result['generatedCoupons'] = $generatedCoupons; 
        return new Response(json_encode($result)); 
    } 
 
    private function getRandomCode($exception) { 
 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_geo_location") 
     */ 
    public function ajaxGetGeoLocation(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = array(); 
 
        $geoLocationID = $request->request->get('geoLocationID'); 
        $geoLocation = $request->getSession()->get('geoLocationList', array()); 
        if (isset($geoLocation[$geoLocationID])) { 
            $geoLocation = $geoLocation[$geoLocationID]; 
        } else { 
            $entityManager = $this->getDoctrine()->getManager("admin"); 
            $entityName = $request->request->get('entity', 'GeoLocation'); 
 
            $entityClassName = GeoLocation::class; 
            if ($entityName === 'MallGeoLocation') { 
                $entityClassName = MallGeoLocation::class; 
            } 
 
            $geoLocationRepository = $entityManager->getRepository($entityClassName); 
            $geoLocation = $geoLocationRepository->find($geoLocationID); 
        } 
 
        $result['geoLocation'] = $geoLocation; 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_edit_geo_location") 
     */ 
    public function ajaxEditGeoLocation(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result['message'] = $this->validateGeoLocationForm($request); 
        if ($result['message'] !== true) { 
            return new Response(json_encode($result)); 
        } 
 
        $result = $this->saveSessionGeoLocation($request); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_add_geo_location") 
     */ 
    public function ajaxAddGeoLocation(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result['message'] = $this->validateGeoLocationForm($request); 
        if ($result['message'] !== true) { 
            return new Response(json_encode($result)); 
        } 
 
        $result = $this->saveSessionGeoLocation($request); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_remove_geo_location") 
     */ 
    public function ajaxRemoveGeoLocation(Request $request, CacheService $cacheService) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = []; 
        $entityManager = $this->getEntityManager(); 
        $geoLocationID = $request->request->get('geoLocationID'); 
        $entityName = $request->request->get('entityName', 'GeoLocation'); 
        if (strpos($geoLocationID, 'new') === false) { 
            $entityClassName = GeoLocation::class; 
            if ($entityName === 'MallGeoLocation') { 
                $entityClassName = MallGeoLocation::class; 
            } 
 
            $geoLocation = $entityManager->getRepository($entityClassName)->find($geoLocationID); 
            if ($geoLocation) { 
                $entityManager->remove($geoLocation); 
                $entityManager->flush(); 
            } 
        } 
        $cacheService->deleteGeoLocation($geoLocationID); 
        $session = $request->getSession(); 
        $geoLocationList = $session->get('geoLocationList', []); 
        if (isset($geoLocationList[$geoLocationID])) { 
            unset($geoLocationList[$geoLocationID]); 
            $session->set('geoLocationList', $geoLocationList); 
        } 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_get_geo_location_list") 
     */ 
    public function ajaxGetGeoLocationList(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = array(); 
        $result['geoLocations'] = ''; 
        $offerID = $request->request->getInt('offerID'); 
        if ($offerID > 0) { 
            $offer = $this->getOfferRepository()->find($offerID); 
            if ($offer) { 
                $result['geoLocations'] = $this->getGeoLocationList($offer); 
            } 
        } 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_refresh_geo_location_list") 
     */ 
    public function ajaxRefreshGeoLocationList(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $result = array(); 
        $geoLocationID = $request->request->get('geoLocationID'); 
        if ($request->request->get('entityType') == 'mall') { 
            $result = $this->getDoctrine()->getManager('admin')->find(MallGeoLocation::class, $geoLocationID); 
        } else { 
            $sessionGeoLocationList = $request->getSession()->get('geoLocationList'); 
            if (isset($sessionGeoLocationList[$geoLocationID])) { 
                $result = $sessionGeoLocationList[$geoLocationID]; 
            } 
        } 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/directors/list") 
     */ 
    public function directorsListAction(Request $request) { 
        ini_set('memory_limit', '256m'); 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $directors = $this->getDoctrine()->getRepository(Director::class)->findAll(); 
        return $this->render('Slivki/admin/directors/list.html.twig', ['directors' => $directors]); 
    } 
 
    /** 
     * @Route("/admin/directors/add") 
     */ 
    public function addDirectorAction(Request $request, Mailer $mailer) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $directorEmail = mb_strtolower(trim($request->request->get('edit-director-email'))); 
        $dql = 'select director from Slivki:Director director where LOWER(director.email) = :email'; 
        $director = $entityManager->createQuery($dql)->setParameter('email', $directorEmail)->getResult(); 
        if (!$director) { 
            $director = new Director(); 
            $director->setName($request->request->get('editDirectorName')); 
            $director->setReceiveLetters($request->request->getBoolean('edit-director-letters')); 
            $director->setLegalEntity($request->request->get('edit-director-legal')); 
            $director->setEmail($directorEmail); 
            $director->setStatus(Director::STATUS_ACTIVE); 
            $director->setTaxID($request->request->get('edit-director-taxID')); 
            $entityManager->persist($director); 
            $this->getUserRepository()->addDirectorGroupToUserByDirectorEmail($directorEmail); 
            $entityManager->flush(); 
            $directorID = $director->getID(); 
            $seoRepository = $entityManager->getRepository(Seo::class); 
            $seo = $seoRepository->findBy(['entityID' => $directorID, 'resourceURL' => SeoRepository::RESOURCE_URL_DIRECTOR_DETAILS], ['ID' => 'DESC'], 1); 
            $requestMainAlias = $request->request->get('editDirectorAlias', ''); 
            $user = $this->getUserRepository()->findBy(['email' => $directorEmail]); 
            if (!$user) { 
                $password = random_int(111111, 999999); 
                $user = new User(); 
                $user->setEmail($directorEmail); 
                $user->encryptPassword($password); 
                $directorUserGroup = $entityManager->getRepository(UserGroup::class)->find(UserGroup::ROLE_SUPPLIER_ID); 
                $user->addUserGroup($directorUserGroup); 
                $user->setStatus(User::STATUS_CONFIRMED); 
                $entityManager->persist($user); 
                $entityManager->flush(); 
 
                $user->setToken(\uniqid($user->getID(), true)); 
                $entityManager->persist($user); 
                $entityManager->flush($user); 
 
                $message = $mailer->createMessage(); 
                $message->setSubject("Регистрация на Slivki.by") 
                    ->setFrom("info@slivki.by", 'Slivki.by') 
                    ->setTo($directorEmail) 
                    ->setBody( 
                        $this->renderView('Slivki/emails/lost_password.html.twig', [ 
                            'password' => $password 
                        ]), 
                        'text/html' 
                    ); 
                $mailer->send($message); 
            } 
            if ($requestMainAlias == '' and $seo) { 
                $entityManager->remove($seo); 
                $entityManager->flush(); 
            } elseif ($requestMainAlias != '') { 
                $seo = new Seo(); 
                $seo->setResourceURL(SeoRepository::RESOURCE_URL_DIRECTOR_DETAILS); 
                $seo->setEntityID($directorID); 
                $seo->setMainAlias($requestMainAlias); 
                $seo->setActive(true); 
                $seo->setMetaTitle($request->request->get('editDirectorMetaTitle', '')); 
                $seo->setMetaDescription($request->request->get('editDirectorMetaDescription', '')); 
                $seo->setMetaKeywords($request->request->get('editDirectorMetaKeywords'), ''); 
                if (!$seoRepository->setAlias($seo)) { 
                    $result['message'] = [ 
                        'title' => 'Ошибка!', 
                        'message' => 'Алиас ' . $requestMainAlias . ' уже существует!', 
                        'type' => 'modal-danger' 
                    ]; 
                    return new JsonResponse($result); 
                } 
            } 
        } else { 
            $director = $director[0]; 
        } 
        return $this->render('Slivki/admin/directors/list.html.twig', ['directors' => [$director]]); 
    } 
 
    /** 
     * @Route("/admin/director/offers/list/{directorID}") 
     */ 
    public function directorOfferListAction($directorID) { 
        $director = $this->getDoctrine()->getRepository(Director::class)->find($directorID); 
        if (!$director) { 
            return new Response(""); 
        } 
        $pageOffer = $director->getPageOffer(); 
        return $this->render('Slivki/admin/directors/offers_list.html.twig', [ 
            'offers' => $director->getOffers(), 
            'pageOfferID' => $pageOffer ? $pageOffer->getID() : -1 
        ]); 
    } 
 
    /** 
     * @Route("/admin/offer/comment/edit") 
     */ 
    public function editCommentAction(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        if (!$this->isGranted('ROLE_ADMIN') && !$this->isGranted('ROLE_MANAGER_COMMENT')) { 
            return new Response(); 
        } 
 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $commentRepository = $entityManager->getRepository(Comment::class); 
        $comment = $commentRepository->find($request->request->get('edit-offer-comment-id')); 
 
        if (!$comment) { 
            return new Response(); 
        } 
 
        $comment->setComment($request->request->get('edit-offer-comment-comment')); 
        $comment->setAdminComment($request->request->get('edit-offer-comment-answer')); 
        $comment->setChecked((bool)$request->request->get('edit-offer-comment-checked')); 
        $comment->setHidden(!(bool)$request->request->get('edit-offer-comment-hidden')); 
        $comment->setRating($request->request->get('edit-offer-comment-rating')); 
 
        $entityManager->flush(); 
        $this->resetCommentsCache($comment->getEntityID(), $comment->getTypeID()); 
 
        return new Response(json_encode($comment)); 
    } 
 
    /** 
     * @Route("/admin/offer/comment/check") 
     */ 
    public function checkCommentAction(Request $request, Mailer $mailer, ValidatorInterface $validator) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        if (!$this->isGranted('ROLE_ADMIN') && !$this->isGranted('ROLE_MANAGER_COMMENT')) { 
            return new Response(); 
        } 
 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $commentRepository = $entityManager->getRepository(Comment::class); 
        $comment = $commentRepository->find($request->request->get('commentID')); 
 
        if (!$comment) { 
            return new Response(); 
        } 
 
        $isChecked = (bool)$request->request->get('value'); 
        $comment->setChecked($isChecked); 
        $entityManager->flush(); 
 
        $offerRepository = $this->getOfferRepository(); 
        if ($isChecked) { 
            $offer = $offerRepository->find($comment->getEntityID()); 
            $userRepository = $this->getUserRepository(); 
            if ($userRepository->addCommentBonus($comment, $offer)) { 
                $this->sendCommentBonusMessage($mailer, $validator, $comment); 
            } 
        } 
 
        return new Response(); 
    } 
 
    /** 
     * @Route("/admin/offer/comment/hide") 
     */ 
    public function hideCommentAction(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        if (!$this->isGranted('ROLE_ADMIN') && !$this->isGranted('ROLE_MANAGER_COMMENT')) { 
            return new Response(); 
        } 
 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $commentRepository = $entityManager->getRepository(Comment::class); 
        $comment = $commentRepository->find($request->request->get('commentID')); 
 
        if (!$comment) { 
            return new Response(); 
        } 
 
        $isHidden = !(bool)$request->request->get('value'); 
        $comment->setHidden($isHidden); 
 
        $entityManager->flush(); 
        $this->resetCommentsCache($comment->getEntityID(), $comment->getTypeID()); 
 
        $userRepository = $this->getUserRepository(); 
        $offer = $this->getOfferRepository()->find($comment->getEntityID()); 
        if ($isHidden) { 
            $userRepository->removeCommentBonus($comment, $offer); 
        } else { 
            $userRepository->addCommentBonus($comment, $offer); 
        } 
 
        return new Response(); 
    } 
 
    private function validateGeoLocationForm(Request $request) { 
        $errorMessage = ''; 
 
        if ($request->request->get('edit-offer-address-street') == '') { 
            $errorMessage .= 'Введите улицу!<br>'; 
        } 
 
        if ($request->request->get('edit-offer-address-building') == '') { 
            $errorMessage .= 'Введите дом!<br>'; 
        } 
 
        if ($request->request->get('edit-offer-latitude') == '' || $request->request->get('edit-offer-longitude') == '') { 
            $errorMessage .= 'Введите координаты!<br>'; 
        } 
 
        if ($errorMessage != '') { 
            $result = array( 
                'title' => 'Ошибка!', 
                'message' => $errorMessage, 
                'type' => 'modal-danger' 
            ); 
            return $result; 
        } 
 
        return true; 
    } 
 
    private function saveSessionGeoLocation(Request $request) { 
        $session = $request->getSession(); 
        $geoLocationList = $session->get('geoLocationList', array()); 
        $requestGeoLocationID = $request->request->get('geo-location-id'); 
 
        $geoLocation['ID'] = $requestGeoLocationID; 
        $geoLocation['city'] = $request->request->get('edit-offer-address-city'); 
        $geoLocation['cityArea'] = $request->request->get('edit-offer-address-area', 0); 
        $geoLocation['street'] = $request->request->get('edit-offer-address-street'); 
        $geoLocation['house'] = $request->request->get('edit-offer-address-building'); 
        $geoLocation['latitude'] = $request->request->get('edit-offer-latitude'); 
        $geoLocation['longitude'] = $request->request->get('edit-offer-longitude'); 
        $geoLocation['description'] = $request->request->get('edit-offer-address-description'); 
        $geoLocation['label'] = $request->request->get('edit-offer-address-label'); 
        $geoLocation['workingHours'] = $request->request->get('edit-offer-address-working-hours'); 
        $geoLocation['bigMapMarker'] = $request->request->has('bigMapMarker'); 
        $geoLocation['pickupPointPartnerID'] = $request->request->get('editOfferAddressPickupPointPartnerID'); 
        $geoLocation['pickupPointSchedule'] = $request->request->get('editOfferAddressPickupPointSchedule'); 
        $geoLocation['pickupPointBelTransSatDepotID'] = $request->request->get('editOfferAddressPickupPointBelTransSatDepotID'); 
        $geoLocation['bepaidCredentials'] = $request->request->get('locationBePaidCredentials'); 
        $geoLocation['callbackChatId'] = $request->request->get('callbackChatId'); 
 
        $geoLocationList[$requestGeoLocationID] = $geoLocation; 
        $session->set('geoLocationList', $geoLocationList); 
 
        $result['message'] = array( 
            'title' => 'Успех!', 
            'message' => 'Адрес успешно сохранен!', 
            'type' => 'modal-success' 
        ); 
 
        return $result; 
    } 
 
    /** 
     * @Route("/admin/offer/set_paid_offer_position") 
     */ 
    public function setPaidOfferPosition(Request $request, KernelInterface $kernel) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $categoryID = $request->request->getInt('categoryID'); 
        if ($categoryID == Category::NEW_OFFER_CATEGORY_ID && !$this->getUser()->hasRole(UserGroup::ROLE_NEW_CATEGORY_MANAGER)) { 
            return $this->redirect("/admin"); 
        } 
        $offerPositionList = $request->request->get('offerPositionList'); 
        $previousPaidOffersPosition = $request->request->get('previousPaidOffersPosition'); 
        $draggedOfferID = $request->request->get('draggedOfferID'); 
        $result = []; 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $categoryRepository = $entityManager->getRepository(Category::class); 
        $currentPaidOffersPosition = json_encode($categoryRepository->getPayedOffersByCategoryID($categoryID)); 
        if ($previousPaidOffersPosition != $currentPaidOffersPosition) { 
            $result = array( 
                'title' => 'Внимание!', 
                'message' => 'Позиции редактировались другим оператором, список обновлен!', 
                'type' => 'modal-warning' 
            ); 
            return new Response(json_encode($result)); 
        } 
        $currentPaidOffersPosition = json_decode($currentPaidOffersPosition, true); 
        $oldPosition = null; 
        if (isset($currentPaidOffersPosition[$draggedOfferID])) { 
            $oldPosition = $currentPaidOffersPosition[$draggedOfferID]['position']; 
        } 
        $offerPositionList = json_decode($offerPositionList, true); 
        $newPosition = $offerPositionList[$draggedOfferID]; 
        $offerPayedCategoryRepository = $entityManager->getRepository(OfferPayedCategory::class); 
        foreach ($offerPositionList as $offerID => $position) { 
            $offerPayedCategory = $offerPayedCategoryRepository->findOneBy(['entityID' => $offerID, 'categoryID' => $categoryID]); 
            if (!$offerPayedCategory) { 
                if ($offerID == $draggedOfferID) { 
                    $offerPayedCategory = new OfferPayedCategory(); 
                    $offerPayedCategory->setCategoryID($categoryID); 
                    $offerPayedCategory->setEntityID($offerID); 
                    $offerPayedCategory->setPosition($position); 
                    $entityManager->persist($offerPayedCategory); 
                } 
                continue; 
            } 
            $offerPayedCategory->setPosition($position); 
        } 
        $entityManager->flush(); 
        $this->saveOfferCategoryPositionsSQL($categoryID); 
        $this->logOperatorAction($request, $draggedOfferID, "$oldPosition -> $newPosition", OperatorActionLog::CHANGE_PAID_OFFER_POSITION); 
        $result['paidOfferPosition'] = json_encode($categoryRepository->getPayedOffersByCategoryID($categoryID)); 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/paid_position/remove") 
     */ 
    public function removePaidOfferPosition(Request $request, KernelInterface $kernel) { 
        $categoryID = $request->request->getInt('categoryID'); 
        $offerID = $request->request->getInt('offerID'); 
        $entityManager = $this->getDoctrine()->getManager("admin"); 
        $offerPayedCategoryRepository = $entityManager->getRepository(OfferPayedCategory::class); 
        $offerPayedCategory = $offerPayedCategoryRepository->findOneBy(['entityID' => $offerID, 'categoryID' => $categoryID]); 
        if ($offerPayedCategory) { 
            $entityManager->remove($offerPayedCategory); 
            $entityManager->flush(); 
        } 
        $categoryRepository = $entityManager->getRepository(Category::class); 
        $result['paidOfferPosition'] = json_encode($categoryRepository->getPayedOffersByCategoryID($categoryID)); 
        $this->refreshOfferCategoriesPosition($kernel, $categoryID); 
        return new Response(json_encode($result)); 
    } 
 
    private function saveOfferCategoryPositionsSQL($categoryID) { 
        $entityManager = $this->getEntityManager(); 
        $categoryRepository = $entityManager->getRepository(Category::class); 
        $offerRepository = $entityManager->getRepository(Offer::class); 
        $activeCategoryList = []; 
        if ($categoryID) { 
            $activeCategoryList[] = $categoryRepository->find($categoryID); 
        } else { 
            $activeCategoryList = $categoryRepository->getActiveCategoriesNotCached(Category::OFFER_CATEGORY_ID); 
        } 
        foreach ($activeCategoryList as $category) { 
            $categoryID = $category->getID(); 
            if ($categoryID == SavePurchaseCountCommand::POPULAR_CATEGORY_ID) { 
                continue; 
            } 
            $offerListSortedByPopularity = $offerRepository->getOffersByCategorySortedByPopularity($category); 
            if (!$offerListSortedByPopularity) { 
                continue; 
            } 
            $dql = "select offerCategoryPosition 
                from Slivki:OfferCategoryPosition offerCategoryPosition index by offerCategoryPosition.entityID 
                where offerCategoryPosition.categoryID = :categoryID"; 
            $query = $entityManager->createQuery($dql); 
            $query->setParameter('categoryID', $categoryID); 
            $offerCategoryPositionList = $query->getResult(); 
            $position = 1; 
            $dbConnection = $entityManager->getConnection(); 
            foreach ($offerListSortedByPopularity as $item) { 
                $offerID = $item->getID(); 
                if (isset($offerCategoryPositionList[$offerID])) { 
                    $offerCategoryPosition = $offerCategoryPositionList[$offerID]; 
                    if ($position != $offerCategoryPosition->getPosition()) { 
                        $sql = "update offer_category_position set position=$position where id=" . $offerCategoryPosition->getID(); 
                        $dbConnection->executeQuery($sql); 
                    } 
                    unset($offerCategoryPositionList[$offerID]); 
                } else { 
                    $sql = "insert into offer_category_position (entity_id, category_id, position)values($offerID, $categoryID, $position)"; 
                    $dbConnection->executeQuery($sql); 
                } 
                $position++; 
            } 
 
            $removeIDList = []; 
            foreach ($offerCategoryPositionList as $item) { 
                $removeIDList[] = $item->getID(); 
            } 
            if (count($removeIDList) > 0) { 
                $sql = "delete from offer_category_position where id in (" . implode(', ', $removeIDList) . ")"; 
                $dbConnection->executeQuery($sql); 
            } 
        } 
    } 
 
    private function refreshOfferCategoriesPosition(KernelInterface $kernel, $categoryID, $background = true) { 
        $category = $this->getCategoryRepository()->find($categoryID); 
        if (!$category) { 
            return; 
        } 
        $command = 'php ' . $kernel->getProjectDir() . '/bin/console purchase-count:save onlyPositions ' . $categoryID; 
        if ($category->getCode() == 'top') { 
            $command = 'php ' . $kernel->getProjectDir() . '/bin/console purchase-count:save onlyPositions --buildPopularOffersCategory=yes'; 
        } 
        if ($background) { 
            $command .= ' > /dev/null &'; 
        } 
        exec("$command"); 
    } 
 
    /** 
     * @Route("/admin/ajax_get_offer_proposals") 
     */ 
    public function ajaxGetOfferProposals(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $offerProposals = $entityManager->getRepository(OfferProposal::class)->findBy(['type' => (int)$request->request->get('type')], ['ID' => 'DESC']); 
        return $this->render('Slivki/admin/offer_proposal/index.html.twig', ['proposals' => $offerProposals]); 
    } 
 
    /** 
     * @Route("/admin/get_offer_proposal") 
     */ 
    public function ajaxGetOfferProposal(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $id = $request->request->get('id'); 
        $offerProposal = $entityManager->getRepository(OfferProposal::class)->find($id); 
        if (!$offerProposal) { 
            $message['success'] = "false"; 
            $message['message'] = "Не удалось получить заявку"; 
            $message['modal'] = "modal-danger"; 
            return new Response(json_encode($message)); 
        } 
        $isJustCheck = $request->request->get('justCheck'); 
        $message['success'] = "true"; 
        if ($isJustCheck == "true") { 
            $checked = $offerProposal->isProcessed() ? false : true; 
            $offerProposal->setProcessed($checked); 
            if ($checked) { 
                $user = $this->getUserRepository()->find($this->getUser()->getID()); 
                $offerProposal->setOperator($user); 
                $message['email'] = $this->getUser()->getEmail(); 
                $message['status'] = "true"; 
            } else { 
                $message['email'] = "<i class=\"fa fa-eye-slash\">"; 
            } 
            $entityManager->flush($offerProposal); 
            $status = $checked ? "\"обработана\"" : "\"ожидает обработки\""; 
            $message['message'] = "Статус заявки [ID = " . $id . "] " . "изменен на " . $status; 
            $message['modal'] = "modal-success"; 
            return new Response(json_encode($message)); 
        } 
        return $this->render('Slivki/admin/offer_proposal/offer_proposal_popup.html.twig', ['offerProposal' => $offerProposal]); 
    } 
 
    /** 
     * @Route("/admin/edit_offer_proposal") 
     */ 
    public function ajaxEditOfferProposal(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $message = []; 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $offerProposal = $entityManager->getRepository(OfferProposal::class)->find($request->request->get('offer-proposal-id')); 
        $contactPerson = $request->request->get('contact-person'); 
        if ($offerProposal->getContactPerson() != $contactPerson) { 
            $message['name'] = $contactPerson; 
        } 
        $offerProposal->setOrganizationName($request->request->get('organization')); 
        $offerProposal->setLegalAddress($request->request->get('legal-address')); 
        $offerProposal->setRequisites($request->request->get('requisites')); 
        $offerProposal->setContactPerson($contactPerson); 
        $offerProposal->setEmail($request->request->get('email')); 
        $offerProposal->setOfferName($request->request->get('offer-name')); 
        $offerProposal->setOfferPrice($request->request->get('offer-price')); 
        $offerProposal->setDiscount($request->request->get('discount')); 
        $offerProposal->setPriceWithDiscount($request->request->get('price-with-discount')); 
        $offerProposal->setOfferConditions($request->request->get('conditions')); 
        $offerProposal->setAdditionalInformation($request->request->get('additional-information')); 
        $offerProposal->setPhone($request->request->get('phone')); 
        $offerProposal->setAddress($request->request->get('address')); 
        $offerProposal->setWebsite($request->request->get('website')); 
        $checkStatus = ''; 
        if ($request->request->get('is-processed') == "on") { 
            $operator = $this->getUserRepository()->find($this->getUser()->getID()); 
            $offerProposal->setOperator($operator); 
            $checkStatus = "true"; 
            $offerProposal->setProcessed(true); 
        } else { 
            $offerProposal->setProcessed(false); 
        } 
        $entityManager->flush($offerProposal); 
        $message['success'] = "true"; 
        $message['message'] = "Заявка успешно обработана!"; 
        $message['modal'] = "modal-success"; 
        $message['status'] = $checkStatus; 
        return new Response(json_encode($message)); 
    } 
 
    /** 
     * @Route("/admin/get_sale_proposals") 
     */ 
    public function ajaxGetSaleProposals(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
    } 
 
    /** @Route("/admin/offer/certificate/save") */ 
    public function saveGiftCertificateAction(Request $request, ImageService $imageService) { 
        $entityManager = $this->getEntityManager(); 
        $certificateteID = $request->request->get('certificateID'); 
        $geoLocationListIDs = $request->request->get('giftCertificateLocation'); 
        $certificate = null; 
        if ($certificateteID) { 
            $certificate = $entityManager->getRepository(GiftCertificate::class)->find($certificateteID); 
        } 
        if (!$certificate) { 
            $certificate = new GiftCertificate(); 
            $offer = $entityManager->getRepository(Offer::class)->find($request->request->get('offerID')); 
            $offer->addGiftCertificate($certificate); 
        } 
        $certificate->setName($request->request->get('name')); 
        $certificate->setPriceRegular(str_replace(',', '.', $request->request->get('price', 0))); 
        $certificate->setPriceOffer(str_replace(',', '.', $request->request->get('offerPrice', 0))); 
        $pricePartnerPurchase = trim($request->request->get('pricePartnerPurchase')); 
        $certificate->setPricePartnerPurchase($pricePartnerPurchase === ''  ? null  : $pricePartnerPurchase); 
        $certificate->setDescription($request->request->get('description')); 
        $certificate->setActive($request->request->has('active')); 
        $certificate->setHidden($request->request->has('hidden')); 
        $certificate->setSpecial123($request->request->getBoolean('special123')); 
        $certificate->setBuyOnlyCode($request->request->getBoolean('buyOnlyCode')); 
        $certificate->setCodesPerItem($request->request->get('codesPerItem')); 
        $certificate->setActiveDays($request->request->getInt('edit-certificate-active-days')); 
        $certificate->setBadgeLabel($request->request->get('badgeLabel')); 
        $certificate->setBadgeBgColor($request->request->get('badgeBgColor')); 
        $certificate->setBadgeTextColor($request->request->get('badgeTextColor')); 
        // if we want to change the suffix, then we will create a new certificate with a new suffix, and simply turn off the current one 
        $certificate->setCodeSuffix($request->request->get('edit-certificate-suffix')); 
        $certificate->setBundlePromoCount($request->request->getInt('bundlePromoCount')); 
        $certificate->setIsSubscription($request->request->getBoolean('isSubscription')); 
        $certificate->setIsRefund($request->request->getBoolean('isRefund')); 
        $certificate->setRefundCommission($request->request->getInt('refundCommission')); 
        $multiUseCodePeriod = $request->request->getInt('multiUseCodePeriod') ?: null; 
        $multiUseCodePerPeriod = $request->request->getInt('multiUseCodePerPeriod') ?: null; 
        $certificate->setMultiUseCodePeriod($multiUseCodePeriod); 
        $certificate->setMultiUseCodePerPeriod($multiUseCodePerPeriod); 
 
        $image = $request->request->get('certificateImage'); 
        if ($image) { 
            $media = $certificate->getMedia(); 
            if ($media) { 
                $entityManager->remove($media); 
            } 
            $media = new Media\GiftCertificateMedia(); 
            $media->setName($image); 
            $media->setPath(MediaType::TYPE_OFFER_TEASER_PATH); 
            $certificate->setMedia($media); 
        } 
        if (is_array($geoLocationListIDs)) { 
            foreach ($geoLocationListIDs as $geoLocationID) { 
                $geoLocation = $entityManager->find(GeoLocation::class, $geoLocationID); 
                if ($geoLocation) { 
                    $certificate->addGeoLocation($geoLocation); 
                } 
            } 
        } else { 
            $geoLocationListIDs = []; 
        } 
        $currentGeoLocationsIDs = []; 
        $geoLocations = $certificate->getGeoLocations(); 
        foreach ($geoLocations as $location) { 
            $currentGeoLocationsIDs[] = $location->getID(); 
        } 
        $geoLocationOnDelete = array_diff($currentGeoLocationsIDs, $geoLocationListIDs); 
        foreach ($geoLocationOnDelete as $locationID) { 
            $geoLocation = $entityManager->find(GeoLocation::class, $locationID); 
            $certificate->removeGeoLocation($geoLocation); 
        } 
        $currentLocationsList = []; 
        $currentLocations = $certificate->getGeoLocations(); 
        foreach ($currentLocations as $location) { 
            $currentLocationsList[] = $location->getID(); 
        } 
        $requestTagIDList = $request->request->get('admin-certificate-tag-id') ? $request->request->get('admin-certificate-tag-id') : []; 
        foreach ($requestTagIDList as $index => $tagID) { 
            $tag = $entityManager->getRepository(GiftCertificateTag::class)->find($tagID); 
            if ($tag) { 
                if ($request->request->get('admin-certificate-tag-deleted')[$index] == "true") { 
                    $certificate->deleteTag($tag); 
                } else { 
                    $certificate->addTag($tag); 
                    $this->logOperatorAction($request, $certificate->getID(), 'add certificate tag ' . $tag->getTag(), OperatorActionLog::ADD_TAG); 
                } 
            } 
        } 
 
        $giftCertificateCategoryIds = array_map( 
            static fn (string $id): int => (int) $id, 
            $request->request->get('giftCertificateCategorySelect', []), 
        ); 
 
        $giftCertificateCategories = $this->giftCertificateCategoryRepository->findByIds($giftCertificateCategoryIds); 
        foreach ($giftCertificateCategories as $giftCertificateCategory) { 
            $giftCertificateCategory->addGiftCertificate($certificate); 
        } 
 
        foreach ($certificate->getCategories() as $giftCertificateCategory) { 
            if (!in_array($giftCertificateCategory->getID(), $giftCertificateCategoryIds, true)) { 
                $giftCertificateCategory->removeGiftCertificate($certificate); 
            } 
        } 
 
        $giftCertificateGiftCategoryIds = array_map( 
            static fn (string $id): int => (int) $id, 
            $request->request->get('giftCertificateGiftCategorySelect', []), 
        ); 
 
        $giftCertificateGiftCategories = $this->giftCertificateGiftCategoryRepository->findByIds($giftCertificateGiftCategoryIds); 
        foreach ($giftCertificateGiftCategories as $giftCertificateGiftCategory) { 
            $giftCertificateGiftCategory->addGiftCertificate($certificate); 
        } 
 
        foreach ($certificate->getGiftCategories() as $giftCertificateGiftCategory) { 
            if (!in_array($giftCertificateGiftCategory->getID(), $giftCertificateGiftCategoryIds, true)) { 
                $giftCertificateGiftCategory->removeGiftCertificate($certificate); 
            } 
        } 
 
        $giftCertificateGroupIds = array_map( 
            static fn (string $id): int => (int) $id, 
            (array) $request->request->get('giftCertificateGroupSelect', []), 
        ); 
 
        $giftCertificateGroups = $this->giftCertificateGroupRepository->findByIds($giftCertificateGroupIds); 
        foreach ($giftCertificateGroups as $giftCertificateGroup) { 
            $giftCertificateGroup->addGiftCertificate($certificate); 
        } 
 
        foreach ($certificate->getGroups() as $giftCertificateGroup) { 
            if (!in_array($giftCertificateGroup->getId(), $giftCertificateGroupIds, true)) { 
                $giftCertificateGroup->removeGiftCertificate($certificate); 
            } 
        } 
 
        $entityManager->flush(); 
 
        $result['categories'] = \implode( 
            ',', 
            array_map( 
                static fn (GiftCertificateCategory $giftCertificateCategory): int => $giftCertificateCategory->getID(), 
                $certificate->getCategories()->getValues(), 
            ), 
        ); 
 
        $result['giftCategories'] = \implode( 
            ',', 
            array_map( 
                static fn (GiftCertificateGiftCategory $giftCertificateGiftCategory): int => $giftCertificateGiftCategory->getID(), 
                $certificate->getGiftCategories()->getValues(), 
            ), 
        ); 
 
        $result['active'] = $certificate->isActive(); 
        $result['locations'] = implode(',', $currentLocationsList); 
        $result['certificateID'] = $certificate->getID(); 
        if ($certificate->getMedia()) { 
            $result['imageURL'] = $imageService->getImageURLCached($certificate->getMedia(), 200, 0); 
        } else { 
            $result['imageURL'] = ''; 
        } 
        $result['activeDays'] = $certificate->getActiveDays(); 
        $result['suffix'] = $certificate->getCodeSuffix(); 
        $result['bundlePromoCount'] = $certificate->getBundlePromoCount(); 
 
        return new JsonResponse($result); 
    } 
 
    /** 
     * @Route("/admin/offer/remove_teaser_logo/{offerID}") 
     */ 
    public function removeTeaserLogoAction($offerID) { 
        $entityManager = $this->getEntityManager(); 
        $result = ''; 
        $media = $entityManager->getRepository(Media::class)->getOfferTeaserLogo($offerID); 
        if (!$media) { 
            return new Response($result); 
        } 
        $entityManager->remove($media); 
        $entityManager->flush(); 
        return new Response($result); 
    } 
 
    /** 
     * @Route("/admin/offer/get_empty_description_block") 
     */ 
    public function getDescriptionsAction(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
        $data['descriptions'] = ['new']; 
        $data['slider'] = $request->request->get('slider'); 
        return $this->render('Slivki/admin/offers/offer_description_block.html.twig', $data); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_add_description_slider_image") 
     */ 
    public function ajaxAddDescriptionSliderImage(Request $request) { 
        if (!$request->isXmlHttpRequest()) { 
            return $this->redirect("/admin"); 
        } 
 
        $result['descriptionSliderImages'] = $this->get('twig')->render( 
            'Slivki/admin/offers/add_offer_description_slider_image.html.twig', [ 
            'imageID' => $request->request->get('imageID'), 
            'imageURL' => $request->request->get('imageURL'), 
            'imageName' => $request->request->get('imageName') 
        ]); 
 
        return new Response(json_encode($result)); 
    } 
 
    /** 
     * @Route("/admin/offer/remove_offer_description/{offerDescriptionID}") 
     */ 
    public function removeOfferDescription(CacheService $cacheService, KernelInterface $kernel, $offerDescriptionID) { 
        $entityManager = $this->getEntityManager(); 
        $offerDescription = $entityManager->find(EntityDescription::class, $offerDescriptionID); 
        if (!$offerDescription) { 
            return new Response(); 
        } 
        $offerDescriptionSliderImages = $offerDescription->getEntityDescriptionSliderImages(); 
        $fs = new Filesystem(); 
        /** @var EntityDescriptionSliderImage $offerDescriptionSliderImage */ 
        foreach ($offerDescriptionSliderImages as $offerDescriptionSliderImage) { 
            $fullPathToImage = $kernel->getProjectDir() . '/public' . $offerDescriptionSliderImage->getImageUrl(); 
            if ($fs->exists($fullPathToImage)) { 
                $fs->remove($fullPathToImage); 
            } 
            $entityManager->remove($offerDescriptionSliderImage); 
        } 
        $offerDescription->getOffer()->setLuceneReindex(true); 
        $entityManager->remove($offerDescription); 
        $entityManager->flush(); 
        $cacheService->deleteEntityDescription($offerDescriptionID); 
        return new Response(); 
    } 
 
    /** 
     * @Route("/admin/offer/remove_offer_description_slider_image/{offerDescriptionSliderImageID}") 
     */ 
    public function removeSaleDescriptionGalleryImage($offerDescriptionSliderImageID) { 
        $entityManager = $this->getEntityManager(); 
        $saleDescriptionGalleryImage = $entityManager->find(EntityDescriptionSliderImage::class, $offerDescriptionSliderImageID); 
        if ($saleDescriptionGalleryImage) { 
            $entityManager->remove($saleDescriptionGalleryImage); 
            $entityManager->flush(); 
        } 
        return new Response(); 
    } 
 
    /** 
     * @Route("/admin/offer/ajax_upload_images") 
     */ 
    public function ajaxUploadImages(Request $request, KernelInterface $kernel) { 
        $imageFolder = $kernel->getProjectDir() . Offer::DESCRIPTION_IMAGES_PATH; 
        $uploadedFile = $request->files->get('file'); 
        if ($uploadedFile) { 
            $fs = new Filesystem(); 
            $originalName = $uploadedFile->getClientOriginalName(); 
            $newFileName = time() . '_' . $originalName; 
            while ($fs->exists($imageFolder . $newFileName)) { 
                $newFileName = time() . '_' . $newFileName; 
            } 
            $imagine = new Imagine(); 
            $image = $imagine->open($uploadedFile->getRealPath()); 
            $imageSize = $image->getSize(); 
            $returnImageName = $newFileName; 
            $bigImage = false; 
            if ($imageSize->getWidth() > 100 && $imageSize->getHeight() > 100) { 
                $limitImageWidth = 1100; 
                $returnImageName = SaleRepository::HASWM_IMAGE_PREFIX . $newFileName; 
                $image->save($imageFolder . $returnImageName); 
                $image = $this->createImageWithWatermark($image, $imagine); 
                if ($image) { 
                    $image->save($imageFolder . SaleRepository::WITHWM_IMAGE_PREFIX . $newFileName); 
                    unset($imagine, $image); 
                } 
                if ($imageSize->getWidth() > $limitImageWidth) { 
                    unlink($imageFolder . $returnImageName); 
                    $bigImage = true; 
                    $imagine = new Imagine(); 
                    $image = $imagine->open($uploadedFile->getRealPath()); 
                    $newFileName = SaleRepository::RESIZED_IMAGE_PREFIX . $newFileName; 
                    $returnImageName = SaleRepository::HASWM_IMAGE_PREFIX . $newFileName; 
                    $newImageSize = $imageSize->widen($limitImageWidth); 
                    $image->resize($newImageSize); 
                    $image->save($imageFolder . $returnImageName); 
                    $image = $this->createImageWithWatermark($image, $imagine); 
                    if ($image) { 
                        $image->save($imageFolder . SaleRepository::WITHWM_IMAGE_PREFIX . $newFileName); 
                    } 
                } 
                unlink($uploadedFile->getRealPath()); 
            } else { 
                $uploadedFile->move($imageFolder, $returnImageName); 
            } 
            return new Response(json_encode(array('location' => $returnImageName, 'bigImage' => $bigImage))); 
        } else { 
            // Notify editor that the upload failed 
            header("HTTP/1.0 500 Server Error"); 
        } 
    } 
 
    /** @Route("/admin/offer/suggest/{cityID}") */ 
    public function suggestAction(Request $request, $cityID) { 
        $sql = "select id, title as text from offer where offer.active and now() between offer.active_since and offer.active_till  
            and title ilike '%" . pg_escape_string($request->query->get('q')) . "%'  
            and id in (select entity_id from category2entity inner join category on category2entity.category_id = category.id and category.city_id = " . (int)$cityID . ")"; 
        $offerList = $this->getDoctrine()->getManager()->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_ASSOC); 
        return new Response(json_encode($offerList)); 
    } 
 
    /** @Route("/admin/offer/codes/used/get/{offerID}") */ 
    public function getUsedCodesAction($offerID) { 
        $offer = $this->getEntityManager()->find(Offer::class, $offerID); 
        if (!$offer) { 
            $content = ''; 
        } else { 
            $content = $offer->getLastActiveCodePool()->getCodesUsed(); 
        } 
        $response = new StreamedResponse(function () use ($content) { 
            $handle = fopen('php://output', 'r+'); 
            fputs($handle, str_replace("\n", "\r\n", $content)); 
            fclose($handle); 
        }); 
        $response->setStatusCode(200); 
        $response->headers->set('Content-Type', 'text/plain'); 
        $response->headers->set('Content-Disposition', 'attachment; filename="used-codes-' . $offerID . '.txt"'); 
        return $response; 
    } 
 
    /** @Route("/admin/offer/show_in_telegram_bot/set") */ 
    public function setShowInTelegramBot(Request $request) { 
        $offerID = $request->request->getInt('offerID'); 
        if (!$offerID) { 
            return new Response(); 
        } 
        $entityManager = $this->getEntityManager(); 
        $offer = $entityManager->find(Offer::class, $offerID); 
        if (!$offer) { 
            return new Response(); 
        } 
        $offer->setTelegramBotShow($request->request->getBoolean('show')); 
        $entityManager->flush(); 
        return new  Response(); 
    } 
 
    /** @Route("/admin/offer/certificate/position/save") */ 
    public function setCertificatePosition(Request $request) { 
        $certificateListID = $request->request->get('certificatePositionList'); 
        $entityManager = $this->getEntityManager(); 
        foreach ($certificateListID as $id => $position) { 
            $certificate = $entityManager->find(GiftCertificate::class, $id); 
            $certificate->setPosition($position); 
        } 
        $entityManager->flush(); 
        return new Response(); 
    } 
 
    /** @Route("/admin/offer/food_extension/get/{foodOfferExtensionID}") */ 
    public function getOfferExtensionAction( 
        $foodOfferExtensionID, 
        OfferExtensionOnlineCategoryRepositoryInterface $offerExtensionOnlineCategoryRepository, 
        QueryBusInterface $queryBus 
    ): Response { 
        $foodOfferExtensionID = (int)$foodOfferExtensionID; 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $foodOfferExtension = $entityManager->find(FoodOfferExtension::class, $foodOfferExtensionID); 
        if (!$foodOfferExtension) { 
            $foodOfferExtension = new FoodOfferExtension(); 
        } 
 
        return $this->render('Slivki/admin/offers/edit_food_extension_form.html.twig', [ 
            'foodOfferExtension' => $foodOfferExtension, 
            'offerExtensionCategoryList' => $entityManager 
                ->getRepository(OfferExtensionCategory::class) 
                ->findAll(), 
            'offerExtensionOnlineCategoryList' => $offerExtensionOnlineCategoryRepository->findAll(), 
            'visibilities' => $queryBus->handle(new GetOfferExtensionVisibilitiesQuery($foodOfferExtensionID)), 
        ]); 
    } 
 
    /** @Route("/admin/offer/food_extension/save/{offerID}") */ 
    public function saveOfferExtensionAction( 
        $offerID, 
        Request $request, 
        OfferExtensionOnlineCategoryRepositoryInterface $offerExtensionOnlineCategoryRepository, 
        MessageBusInterface $commandBus 
    ): JsonResponse { 
        $foodOfferExtensionID = $request->request->getInt('editFoodID'); 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $foodOfferExtension = $entityManager->find(FoodOfferExtension::class, $foodOfferExtensionID); 
        $oldID = 0; 
        if (!$foodOfferExtension) { 
            $foodOfferExtension = $request->request->get('editOfferFoodType') === 'FoodOfferOptionExtension' 
                ? new FoodOfferOptionExtension() 
                : new FoodOfferExtension(); 
            $entityManager->find(Offer::class, $offerID)->addExtension($foodOfferExtension); 
        } 
 
        $foodOfferExtension->setName($request->request->get('editFoodName')); 
        $foodOfferExtension->setShortDescription($request->request->get('editFoodShortDescription')); 
        $foodOfferExtension->setDescription($request->request->get('editFoodDescription')); 
        $foodOfferExtension->setPriceDescription($request->request->get('editFoodPriceDescription')); 
        $foodOfferExtension->setPartnerItemID($request->request->get('editFoodPartnerID')); 
        $foodOfferExtension->setPrice((float)str_replace(',', '.', $request->request->get('editFoodRegularPrice'))); 
        $foodOfferExtension->setDishDeliveryPrice((float)str_replace(',', '.', $request->request->get('editOfferDishDeliveryPrice'))); 
        $foodOfferExtension->setPickupPrice((float)str_replace(',', '.', $request->request->get('editOfferDishPickupPrice'))); 
        $foodOfferExtension->setIsDelivery($request->request->getBoolean('switchOnDelivery')); 
        $foodOfferExtension->setIsPickup($request->request->getBoolean('switchOnPickup')); 
        $foodOfferExtension->setPriceDeliveryType($request->request->get('priceDeliveryTypeOffer')); 
        $foodOfferExtension->setProductsPerCode($request->request->getInt('editFoodProductsPerCode')); 
        $foodOfferExtension->setActive(true); 
        $foodOfferExtension->setSauceNeed($request->request->getBoolean('switchOnSauceNeed')); 
        $foodOfferExtension->setSpecial123($request->request->getBoolean('special123')); 
        $foodOfferExtension->setBadgeLabel($request->request->get('badgeLabel')); 
        $foodOfferExtension->setBadgeBgColor($request->request->get('badgeBgColor')); 
        $foodOfferExtension->setBadgeTextColor($request->request->get('badgeTextColor')); 
        $weight = $request->request->get('editFoodWeight'); 
        $foodOfferExtension->setWeight($weight ? (float)str_replace(',', '.', $weight) : null); 
        $componentsCount = $request->request->getInt('editFoodСomponentsСount'); 
        $foodOfferExtension->setComponentsCount($componentsCount ?: null); 
        $foodImage = $request->request->get('editOfferFoodImage'); 
        if ($foodImage) { 
            $foodExtensionMedia = $foodOfferExtension->getMedia(); 
            if ($foodExtensionMedia) { 
                $entityManager->remove($foodExtensionMedia); 
            } 
            $foodExtensionMedia = new Media\OfferExtensionMedia(); 
            $foodExtensionMedia->setName($foodImage); 
            $foodExtensionMedia->setPath(MediaType::DEFAULT_IMAGE_PATH); 
            $entityManager->persist($foodExtensionMedia); 
            $foodOfferExtension->setMedia($foodExtensionMedia); 
        } 
 
        $priceByTimePrice = $request->request->get('foodPriceByTimePrice', []); 
        $priceByTimeHoursFrom = $request->request->get('foodPriceByTimeHoursFrom', []); 
        $priceByTimeHoursTo = $request->request->get('foodPriceByTimeHoursTo', []); 
        $priceByTime = []; 
        foreach ($priceByTimePrice as $key => $item) { 
            $priceByTime[] = [$priceByTimeHoursFrom[$key], $priceByTimeHoursTo[$key], $item]; 
        } 
        $foodOfferExtension->setPriceByTime(json_encode($priceByTime)); 
 
        $offerExtensionCategoryIDList = (array) $request->request->get('editOfferFoodCategorySelect', []); 
        foreach ($offerExtensionCategoryIDList as $offerExtensionCategoryID) { 
            $offerExtensionCategory = $entityManager->find( 
                OfferExtensionCategory::class, 
                $offerExtensionCategoryID 
            ); 
            if ($offerExtensionCategory) { 
                $offerExtensionCategory->addOfferExtension($foodOfferExtension); 
                if ($request->request->getBoolean('addSauceNeed')) { 
                    foreach ($offerExtensionCategory->getOfferExtensions() as $extension) { 
                        if ($extension->getOffer()->getID() === $offerID) { 
                            $extension->setSauceNeed(true); 
                        } 
                    } 
                } elseif ($request->request->getBoolean('deleteSauceNeed')) { 
                    foreach ($offerExtensionCategory->getOfferExtensions() as $extension) { 
                        if ($extension->getOffer()->getID() === $offerID) { 
                            $extension->setSauceNeed(false); 
                        } 
                    } 
                } 
            } 
        } 
 
        /** @var OfferExtensionCategory $offerExtensionCategory */ 
        foreach ($foodOfferExtension->getCategories()->toArray() as $offerExtensionCategory) { 
            if (!in_array($offerExtensionCategory->getID(), $offerExtensionCategoryIDList)) { 
                $offerExtensionCategory->removeOfferExtension($foodOfferExtension); 
            } 
        } 
 
        $offerExtensionOnlineCategoryIdList = (array) $request->request->get('editOfferFoodOnlineCategorySelect', []); 
        foreach ($offerExtensionOnlineCategoryIdList as $offerExtensionOnlineCategoryId) { 
            $offerExtensionOnlineCategory = $offerExtensionOnlineCategoryRepository->findById($offerExtensionOnlineCategoryId); 
            if (!$offerExtensionOnlineCategory instanceof OfferExtensionOnlineCategory) { 
                continue; 
            } 
 
            $offerExtensionOnlineCategory->addOfferExtension($foodOfferExtension); 
        } 
 
        foreach ($foodOfferExtension->getOnlineCategories() as $offerExtensionOnlineCategory) { 
            if (!in_array($offerExtensionOnlineCategory->getID(), $offerExtensionOnlineCategoryIdList)) { 
                $offerExtensionOnlineCategory->removeOfferExtension($foodOfferExtension); 
            } 
        } 
 
        $entityManager->flush(); 
 
        $commandBus->dispatch(new SaveOfferExtensionOnlineCategoryOfferRelationsCommand($offerID)); 
 
        return new JsonResponse([ 
            'id' => $foodOfferExtension->getID(), 
            'name' => $foodOfferExtension->getName(), 
            'old' => $oldID, 
        ]); 
    } 
 
    /** @Route("/admin/offer/food_extension/remove/{foodOfferExtensionID}") */ 
    public function removeOfferExtensionAction(OfferCacheService $offerCacheService, $foodOfferExtensionID): Response 
    { 
        $foodOfferExtensionID = (int)$foodOfferExtensionID; 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $foodOfferExtension = $entityManager->find(FoodOfferExtension::class, $foodOfferExtensionID); 
        if ($foodOfferExtension) { 
            $entityManager->remove($foodOfferExtension); 
            $entityManager->flush(); 
            $offerCacheService->deleteExtension($foodOfferExtensionID); 
        } 
 
        return new Response(); 
    } 
 
    /** @Route("/admin/offer/online-settings/save", methods={"POST"}) */ 
    public function saveOfferOnlineOrderSettingsAction(Request $request): JsonResponse 
    { 
        $offerID = $request->request->getInt('offerID'); 
        if (!$offerID) { 
            return new JsonResponse(['status' => 'error', 'message' => 'ID оффера не было передано в параметрах'], Response::HTTP_OK); 
        } 
 
        if ($offerID == 253544) { 
            Logger::instance('SLIVKIPAYDEBUG')->info($this->getUser()->getEmail()); 
        } 
 
        $entityManager = $this->getEntityManager(); 
        $offer = $entityManager->find(Offer::class, $offerID); 
        if (!$offer) { 
            return new JsonResponse(['status' => 'error', 'message' => 'Оффер не найден'], Response::HTTP_OK); 
        } 
        $onlineOrderSettings = $offer->getOnlineOrderSettings(); 
        if (!$onlineOrderSettings) { 
            $onlineOrderSettings = new OnlineOrderSettings(); 
        } 
        $minDeliverySum = $request->request->get('minDeliverySum'); 
        $processedMinDeliverySum = ($minDeliverySum || $minDeliverySum === "0") ? str_replace(',', '.', $minDeliverySum) : null; 
        $onlineOrderSettings->setMinDeliverySum($processedMinDeliverySum); 
        $minSumForFreeDelivery = $request->request->get('minSumForFreeDelivery'); 
        $processedMinSumForFreeDelivery = ($minSumForFreeDelivery || $minSumForFreeDelivery === "0") ? str_replace(',', '.', $minSumForFreeDelivery) : null; 
        $onlineOrderSettings->setMinSumForFreeDelivery($processedMinSumForFreeDelivery); 
        $deliveryPrice = $request->request->get('deliveryPrice'); 
        $processedDeliveryPrice = ($deliveryPrice || $deliveryPrice === "0") ? str_replace(',', '.', $deliveryPrice) : null; 
        $onlineOrderSettings->setDeliveryPrice($processedDeliveryPrice); 
        $orderPeriodInDays = $request->request->get('orderPeriodInDays'); 
        $processedDeliveryPrice = ($orderPeriodInDays || $orderPeriodInDays === "0") ? intval($orderPeriodInDays) : null; 
        $onlineOrderSettings->setOrderPeriodInDays($processedDeliveryPrice); 
        $onlineOrderSettings->setAllowedPaymentMethods($request->request->get('allowedPaymentMethods')); 
        $onlineOrderSettings->setPickupEnabled($request->request->getBoolean('pickupEnabled')); 
        $onlineOrderSettings->setDefaultPickup($request->request->getBoolean('defaultPickup')); 
        $onlineOrderSettings->setDeliveryEnabled($request->request->getBoolean('deliveryEnabled')); 
        $onlineOrderSettings->setEmail($request->request->get('email')); 
        $onlineOrderSettings->setDeliveryTimeFrom($request->request->get('deliveryTimeFrom')); 
        $onlineOrderSettings->setDeliveryTimeTill($request->request->get('deliveryTimeTill')); 
        $onlineOrderSettings->setDeliveryPriceInfo($request->request->get('deliveryPriceInfo') ?: null); 
 
        $deliverySchedule = $request->request->get('deliverySchedule'); 
        $onlineOrderSettings->setDeliverySchedule(empty($deliverySchedule) ? null : $deliverySchedule); 
 
        $onlineOrderSettings->setDeliveryLeadType($request->request->get('deliveryLeadType')); 
        $deliveryLeadTime = $request->request->get('deliveryLeadTime'); 
        $onlineOrderSettings->setDeliveryLeadTime($deliveryLeadTime === '' ? null : $deliveryLeadTime); 
 
        $onlineOrderSettings->setDeliveryIntervalBetweenOrdersType($request->request->get('deliveryIntervalBetweenOrdersType')); 
        $deliveryIntervalBetweenOrdersTime = $request->request->get('deliveryIntervalBetweenOrdersTime'); 
        $onlineOrderSettings->setDeliveryIntervalBetweenOrdersTime($deliveryIntervalBetweenOrdersTime === '' ? null : $deliveryIntervalBetweenOrdersTime); 
 
        $onlineOrderSettings->setDeliveryDisableType($request->request->get('deliveryDisableType')); 
        $deliveryDisableTime = $request->request->get('deliveryDisableTime'); 
        $onlineOrderSettings->setDeliveryDisableTime($deliveryDisableTime === '' ? null : $deliveryDisableTime); 
 
        $onlineOrderSettings->setDeliveryNearlyEnabled($request->request->getBoolean('deliveryNearlyEnabled')); 
        $pickupLeadTime = $request->request->get('pickupLeadTime'); 
        $onlineOrderSettings->setPickupLeadTime($pickupLeadTime === '' ? null : (int) $pickupLeadTime); 
        $onlineOrderSettings->setPriceCodeDependsOnOrder($request->request->get('priceCodeDependsOnOrder' ?: null)); 
 
        $hasDeliveryWorkingTime = false; 
        $deliveryWorkingTime = []; 
        foreach ($request->request->get('deliveryWorkingTime') as $item) { 
            $deliveryOneDayWorkingTime = $this->serializer->deserialize($item, DeliveryOneDayWorkingTimeDto::class, SerializerConfig::JSON); 
            if (!$deliveryOneDayWorkingTime->isDayOff()) { 
                $hasDeliveryWorkingTime = true; 
            } 
            $deliveryWorkingTime[] = $deliveryOneDayWorkingTime; 
        } 
 
        $onlineOrderSettings->setDeliveryWorkingTime($hasDeliveryWorkingTime ? $this->serializer->serialize($deliveryWorkingTime, SerializerConfig::JSON) : null); 
 
        $pickupCookingTime = $request->request->get('pickupCookingTime'); 
        $onlineOrderSettings->setPickupCookingTime('' === $pickupCookingTime ? null : $pickupCookingTime); 
        $onlineOrderSettings->setPendingOrderAllowed($request->request->getBoolean('pendingOrderAllowed')); 
        $receivingOrdersSchedule = $request->request->get('receivingOrdersSchedule'); 
        $onlineOrderSettings->setReceivingOrdersSchedule( 
            null === $receivingOrdersSchedule 
                ? null 
                : json_decode($receivingOrdersSchedule, true, 512, JSON_THROW_ON_ERROR) 
        ); 
 
        $offer->setOnlineOrderSettings($onlineOrderSettings); 
        $entityManager->flush(); 
 
        return new JsonResponse(['status' => 'success', 'message' => 'Настройки сохранены'], Response::HTTP_OK); 
    } 
 
    /** @Route("/admin/offer/set/api/payed-category") */ 
    public function setApiPayedCategoryAction(Request $request) { 
        $categoryID = $request->request->getInt('categoryID'); 
        $offerID = $request->request->getInt('offerID'); 
        $position = $request->request->getInt('position'); 
        $entityManager = $this->getDoctrine()->getManager('admin'); 
        $payedCategoryRepository = $entityManager->getRepository(OfferPayedCategoryMobile::class); 
        $payedCategory = $payedCategoryRepository->findOneBy(['categoryID' => $categoryID, 'entityID' => $offerID]); 
        if (!$payedCategory) { 
            $payedCategory = new OfferPayedCategoryMobile(); 
            $payedCategory->setCategoryID($categoryID); 
            $payedCategory->setEntityID($offerID); 
            $entityManager->persist($payedCategory); 
        } 
        if(!$position) { 
            $entityManager->remove($payedCategory); 
        } else { 
            $isExist = $payedCategoryRepository->findOneBy(['categoryID' => $categoryID, 'position' => $position]); 
            if ($isExist) { 
                $offer = $entityManager->find(Offer::class, $isExist->getEntityID()); 
                $hasCategory = $offer->hasCategory($categoryID); 
                if ($isExist && $hasCategory) { 
                    return new JsonResponse(['error' => true, 'msg' => 'Позиция уже занята']); 
                } 
            } 
            if ($isExist && !$hasCategory) { 
                $entityManager->remove($isExist); 
            } 
            $payedCategory->setPosition($position); 
        } 
        $entityManager->flush(); 
        return new JsonResponse(['categoryID' => $categoryID, 'offerID' => $offerID, 'position' => $position]); 
    } 
 
    /** @Route("/admin/offer/certificate/get/tags/{certificateID}") */ 
    public function getGiftCertificateTagsAction(Request $request, $certificateID) { 
        $entityManager = $this->getEntityManager(); 
        $certificate = $entityManager->getRepository(GiftCertificate::class)->find($certificateID); 
        if (!$certificate) { 
            return new Response(); 
        } 
        $result['html'] = $this->get('twig')->render('Slivki/admin/tags/gift_certificate_list.html.twig', ['tags' => $certificate->getTags()]); 
        return new JsonResponse($result); 
    } 
 
    /** @Route("/admin/offer_extension/position/update") */ 
    public function updateOfferExtensionPosition(Request $request): JsonResponse 
    { 
        $em = $this->getDoctrine()->getManager('admin'); 
 
        $foodPositions = $request->request->get('position'); 
        if ($foodPositions) { 
            foreach ($foodPositions as $foodId => $position) { 
                /** @var OfferExtension|null $foodExtension */ 
                $foodExtension = $em->find(OfferExtension::class, (int) $foodId); 
 
                if (null === $foodExtension) { 
                    continue; 
                } 
 
                $foodExtension->setPosition((int) $position); 
            } 
 
            $em->flush(); 
        } 
 
        return new JsonResponse(); 
    } 
}