src/Aqarmap/Bundle/ListingBundle/Controller/ListingController.php line 771
<?phpnamespace Aqarmap\Bundle\ListingBundle\Controller;use App\Exception\LogicHttpException;use Aqarmap\Bundle\CreditBundle\Constant\CreditStatus;use Aqarmap\Bundle\CreditBundle\Entity\Credit;use Aqarmap\Bundle\CreditBundle\Services\CreditManager;use Aqarmap\Bundle\FeatureToggleBundle\Service\FeatureToggleManager;use Aqarmap\Bundle\FinancialAidsBundle\Service\FinancialAidService;use Aqarmap\Bundle\ListingBundle\Constant\LeadTypes;use Aqarmap\Bundle\ListingBundle\Constant\ListingCategories;use Aqarmap\Bundle\ListingBundle\Constant\ListingFeaturedTypes;use Aqarmap\Bundle\ListingBundle\Constant\ListingFeatures;use Aqarmap\Bundle\ListingBundle\Constant\ListingSections;use Aqarmap\Bundle\ListingBundle\Constant\ListingSellerRoles;use Aqarmap\Bundle\ListingBundle\Constant\ListingSource;use Aqarmap\Bundle\ListingBundle\Constant\ListingStatus;use Aqarmap\Bundle\ListingBundle\Constant\PropertyRegistrationStatusOption;use Aqarmap\Bundle\ListingBundle\Constant\ResaleListingsConstant;use Aqarmap\Bundle\ListingBundle\Contracts\PhoneManagerInterface;use Aqarmap\Bundle\ListingBundle\Contracts\RelatedResultServiceInterface;use Aqarmap\Bundle\ListingBundle\Entity\CallRequest;use Aqarmap\Bundle\ListingBundle\Entity\File;use Aqarmap\Bundle\ListingBundle\Entity\Listing;use Aqarmap\Bundle\ListingBundle\Entity\ListingPhone;use Aqarmap\Bundle\ListingBundle\Entity\Phone;use Aqarmap\Bundle\ListingBundle\Entity\Section;use Aqarmap\Bundle\ListingBundle\Event\ListingEvent;use Aqarmap\Bundle\ListingBundle\Exception\InvalidLeadValidationHttpException;use Aqarmap\Bundle\ListingBundle\Form\AdvancedFilterType;use Aqarmap\Bundle\ListingBundle\Form\AdvancedSearchType;use Aqarmap\Bundle\ListingBundle\Form\CallRequestFormType;use Aqarmap\Bundle\ListingBundle\Form\ContactSellerFormType;use Aqarmap\Bundle\ListingBundle\Form\ContactSellerWideFormType;use Aqarmap\Bundle\ListingBundle\Form\LandingPageFormType;use Aqarmap\Bundle\ListingBundle\Form\ListingInitializeType;use Aqarmap\Bundle\ListingBundle\Form\ListingType;use Aqarmap\Bundle\ListingBundle\Form\LiteListingType;use Aqarmap\Bundle\ListingBundle\Form\Model\LandingPage;use Aqarmap\Bundle\ListingBundle\Form\MultipleSearchFormType;use Aqarmap\Bundle\ListingBundle\Form\PhotoType;use Aqarmap\Bundle\ListingBundle\Form\QuickLeadType;use Aqarmap\Bundle\ListingBundle\Repository\ListingPhotoRepository;use Aqarmap\Bundle\ListingBundle\Service\AdvancedFilterFormTypeManager;use Aqarmap\Bundle\ListingBundle\Service\AdvancedSearchFormTypeManager;use Aqarmap\Bundle\ListingBundle\Service\CallRequestManager;use Aqarmap\Bundle\ListingBundle\Service\Contracts\ListingLeadManagerInterface;use Aqarmap\Bundle\ListingBundle\Service\Contracts\LocationManagerInterface;use Aqarmap\Bundle\ListingBundle\Service\FreeListingService;use Aqarmap\Bundle\ListingBundle\Service\InteractionService;use Aqarmap\Bundle\ListingBundle\Service\ListingFeatureService;use Aqarmap\Bundle\ListingBundle\Service\ListingManager;use Aqarmap\Bundle\ListingBundle\Service\ListingRuleMatcher;use Aqarmap\Bundle\ListingBundle\Service\Mortgage\MortgageService;use Aqarmap\Bundle\ListingBundle\Service\SpecialAddListingService;use Aqarmap\Bundle\ListingBundle\Service\V4\CompoundDetailService;use Aqarmap\Bundle\MainBundle\Form\ConfirmFeaturedFormType;use Aqarmap\Bundle\MainBundle\Form\ConfirmFormType;use Aqarmap\Bundle\MainBundle\Service\MobileDetectionService;use Aqarmap\Bundle\MainBundle\Service\Setting;use Aqarmap\Bundle\MessageBundle\Service\Composer;use Aqarmap\Bundle\NeighborhoodBundle\Service\NeighborhoodManager;use Aqarmap\Bundle\NotificationBundle\DatabaseNotification;use Aqarmap\Bundle\NotifierBundle\Event\NotifierEvent;use Aqarmap\Bundle\OTPBundle\Contract\OtpServiceInterface;use Aqarmap\Bundle\SearchBundle\Services\CompoundFaqsService;use Aqarmap\Bundle\SearchBundle\Services\ElasticListingSearch\DefaultListingSearch;use Aqarmap\Bundle\TopSellerBundle\Model\TopSeller;use Aqarmap\Bundle\TopSellerBundle\Service\TopSellerRetrievalService;use Aqarmap\Bundle\UserBundle\Constant\UserServicesType;use Aqarmap\Bundle\UserBundle\Constant\UserTypes;use Aqarmap\Bundle\UserBundle\Entity\User;use Aqarmap\Bundle\UserBundle\Entity\UserServices;use Aqarmap\Bundle\UserBundle\Form\QuickRegistrationFormType;use Aqarmap\Bundle\UserBundle\Repository\UserPackagesRepository;use Aqarmap\Bundle\UserBundle\Services\UserActivityService;use Aqarmap\Bundle\UserBundle\Services\UserManager;use Aqarmap\Bundle\UserBundle\Services\UserPackagesService;use Aqarmap\Bundle\UserBundle\Services\UserServicesManager;use Doctrine\ORM\EntityManager;use Doctrine\ORM\EntityManagerInterface;use FOS\RestBundle\Controller\Annotations as Rest;use FOS\RestBundle\View\View;use FOS\UserBundle\Model\UserManagerInterface;use Gedmo\Translatable\TranslatableListener;use Knp\Component\Pager\PaginatorInterface;use Liip\ImagineBundle\Imagine\Cache\CacheManager;use Psr\Log\LoggerInterface;use Psr\Log\LogLevel;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\EventDispatcher\EventDispatcherInterface;use Symfony\Component\ExpressionLanguage\Expression;use Symfony\Component\Form\FormInterface;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;use Symfony\Component\Routing\Attribute\Route;use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;use Symfony\Component\Security\Http\Attribute\IsGranted;use Symfony\Contracts\Translation\TranslatorInterface;use Vich\UploaderBundle\Handler\DownloadHandler;use Vich\UploaderBundle\Templating\Helper\UploaderHelper;/*** Listing controller.*/class ListingController extends AbstractController{public function __construct(private readonly Composer $messageComposer,OtpServiceInterface $otpService,private readonly DatabaseNotification $databaseNotification,private readonly LoggerInterface $logger,private readonly TranslatorInterface $translator,private readonly FeatureToggleManager $featureToggleManager,private readonly Setting $setting,private readonly ListingManager $listingManager,private readonly EventDispatcherInterface $dispatcher,private readonly InteractionService $interactionService,private readonly NeighborhoodManager $neighborhoodManager,private readonly DefaultListingSearch $defaultListingSearch,private readonly RelatedResultServiceInterface $relatedResultService,LocationManagerInterface $locationManager,private readonly TopSellerRetrievalService $topSellerRetrievalService,private readonly FinancialAidService $financialAidService,private readonly ListingLeadManagerInterface $listingLeadManager,private readonly CompoundFaqsService $compoundFaqsService,private readonly PaginatorInterface $paginator,private readonly UserActivityService $userActivityService,private readonly MobileDetectionService $mobileDetectionService,private readonly CacheManager $imagine,private readonly UploaderHelper $uploaderHelper,private readonly CallRequestManager $callRequestManager,private readonly AuthorizationCheckerInterface $authorizationChecker,TokenStorageInterface $tokenStorage,private readonly MortgageService $mortgageService,private readonly ListingRuleMatcher $listingRuleMatcher,private readonly CreditManager $creditManager,private readonly UserServicesManager $userServicesManager,private readonly UserManagerInterface $FOSUserManager,private readonly PhoneManagerInterface $phoneManager,FreeListingService $freeListingService,private readonly ListingFeatureService $listingFeatureService,private readonly UserManager $userManager,private readonly AdvancedSearchFormTypeManager $advancedSearchFormTypeManager,private readonly AdvancedFilterFormTypeManager $advancedFilterFormTypeManager,private readonly SpecialAddListingService $specialAddListingService,private readonly CompoundDetailService $compoundDetailService,private readonly TranslatableListener $translatableListener,private readonly UserPackagesRepository $userPackagesRepository,private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,) {}/*** Listing Details Action.*/#[Route(path: '/{id}/{notification}', defaults: ['notification' => 0], requirements: ['id' => '\d+'], options: ['i18n' => false, 'expose' => true], name: 'listing_view', methods: ['GET'])]#[Route(path: '/listing/{id}/notification/{notification}', defaults: ['notification' => 0], name: 'listing_view_notification', methods: ['GET'])]#[Route(path: '/listing/{id}', requirements: ['id' => '\d+'], options: ['expose' => true], name: 'listing_details', methods: ['GET'])]#[Route(path: '/listing/{id}-{slug}', requirements: ['id' => '\d+', 'slug' => '.+'], name: 'listing_slug', methods: ['GET'])]public function read(Request $request, Listing $listing, EntityManagerInterface $em, UserServicesManager $userServicesManager){if ($request->get('notification')) {try {$this->databaseNotification->markOneAsRead($request->get('notification'));} catch (\Exception $exception) {$this->logger->log(LogLevel::ERROR, $exception->getMessage());}}// Redirect to the right URL if the URL is short-URL or the listing slug is incorrectif (('listing_slug' != $request->get('_route')|| $request->attributes->get('slug') != $listing->getSlug())&& !empty($listing->getSlug())) {return $this->redirectToRoute('listing_slug', array_merge($request->query->all(), ['id' => $listing->getId(),'slug' => $listing->getSlug(),]), Response::HTTP_MOVED_PERMANENTLY);}$listingStatus = !\in_array($listing->getStatus(), [ListingStatus::LIVE, ListingStatus::PENDING]);if ($listingStatus && !$request->query->get('noredirect') && $listing->getUser() != $this->getUser()) {if (!$listing->getSection()->getSearchable()) {return $this->redirectToRoute('compound_search', [], Response::HTTP_FOUND);}try {$searchableLocation = $listing->getLocation()->getNearestSearchable();} catch (\Exception) {$this->addFlash('danger',$this->translator->trans('listing.not_available'));return $this->redirectToRoute('homepage', [], Response::HTTP_FOUND);}return $this->redirectToRoute('search', ['section_slug' => $listing->getSection()->getSlug(),'property_type_slug' => $listing->getPropertyType()->getSlug(),'location_slug' => $searchableLocation->getSlug(),], Response::HTTP_MOVED_PERMANENTLY);}$listingRepo = $em->getRepository(Listing::class);if ($notifierId = $request->query->get('notifier')) {if (null !== $notifier = $em->getRepository(\Aqarmap\Bundle\NotifierBundle\Entity\Notifier::class)->find($notifierId)) {$this->dispatcher->dispatch(new NotifierEvent($notifier), 'aqarmap.notifier.interaction');} else {$this->logger->warning('Notifier with id: '.$notifierId.' was not found!');}}$this->interactionService->increaseViews($listing, $this->getUser());$relatedListingCriteriaMapper = $this->relatedResultService->getRelatedListingCriteriaMapper($listing);$relatedListings = $this->defaultListingSearch->search($relatedListingCriteriaMapper)['searchResults'];$topSeller = $this->createTopSeller($listing);$topSearchableCompanies = $this->topSellerRetrievalService->getTopSellerPersonalData($topSeller, $request->getLocale());$searchableLocation = $listing->getLocation()->getNearestSearchable();$isPlaceHoldered = false;$userProfilePhoto = $listing->getUser()->isValidPersonalPhoto() ? $listing->getUser()->getPersonalPhoto() : null;if ($listing->getLogo() || ($listing->getParent() && $listing->getParent()->getLogo())) {if ($listing->getParent() && $listing->getParent()->getLogo()) {}} elseif (!empty($listing->getPhotosForSlider()) && $listing->getUser()->getIsValidLogo()) {$isPlaceHoldered = true;}$this->financialAidService->setFinancialAidInListing($listing);$activeListingsCount = $listing->getUser()->getActiveListingsCount();$leadsCount = 0;if ($this->featureToggleManager->isEnabled('web.client.served.count')) {$leadsCount = $listing->getUser()->getClientServedCount();}$listing = current($this->listingManager->setUserActivities([$listing],[$listing->getId()]));$hasUserMadeLead = false;if ($user = $this->getUser()) {$hasUserMadeLead = $this->listingLeadManager->hasUserMadeLead($listing, $user);}$compoundFaqs = [];$listingDetails = $listing;if ($listing->isProject()) {$compoundFaqs = $this->compoundFaqsService->generateFaqData($listing);$resaleRegularListingsPaginated = $this->paginator->paginate($listingRepo->getSectionListings($listing, null, ListingSections::FOR_SALE),max($request->query->getInt('page', ResaleListingsConstant::PAGE), ResaleListingsConstant::PAGE),ResaleListingsConstant::LIMIT);$this->compoundDetailService->getPropertyTypeChildrens($listing, $request->getLocale());$liveUnitsPaginated = $listing->getPropertyTypeChildren();$this->compoundDetailService->getPropertyTypeUnitsChildrens($listing, ListingSections::FOR_SALE, $request->getLocale());$resaleUnitsPaginated = $listing->getPropertyTypeChildren();$this->compoundDetailService->getPropertyTypeUnitsChildrens($listing, ListingSections::FOR_RENT, $request->getLocale());$rentUnitsPaginated = $listing->getPropertyTypeChildren();}$request->cookies->get('user-agent');$mobileDetection = $this->mobileDetectionService->mobileDetection($request, $return);$return = ['listing' => $listingDetails,'searchableLocation' => $searchableLocation,'contact_seller_form' => $this->contactSellerForm($listing)->createView(),'quick_registration_form' => $this->quickRegistrationForm()->createView(),'call_request' => $this->callRequestForm($listing)->createView(),'related_listings' => $relatedListings,'relatedListingsCount' => (null != $relatedListings) ? $relatedListings->getTotalItemCount() : 0,'location_statistics' => $this->neighborhoodManager->getStatistics($listing->getLocation()->getNearestNeighborhood(),$listing->getPropertyType()),'topSearchableCompanies' => $topSearchableCompanies,'topSearchableCompaniesCount' => \count($topSearchableCompanies),'isPlaceHoldered' => $isPlaceHoldered,'userProfilePhoto' => $userProfilePhoto,'activeListingsCount' => $activeListingsCount,'leadsCount' => $leadsCount,'featureToggle' => $this->userActivityService->getFeatureToggles(),'leadAnalytics' => $this->listingManager->getLeadAnalytics($listing),'otherUnits' => $this->listingManager->getOtherUnits($listing, $request->getLocale()),'hasUserMadeLead' => $hasUserMadeLead,'resaleRegularListings' => $resaleRegularListingsPaginated ?? null,'resaleUnitsPaginated' => $resaleUnitsPaginated ?? null,'liveUnitsPaginated' => $liveUnitsPaginated ?? null,'rentUnitsPaginated' => $rentUnitsPaginated ?? null,'compoundFaqs' => $compoundFaqs,'isMobile' => $mobileDetection['isMobile'],'hasCompoundRatingService' => $user ? $userServicesManager->hasActiveService(UserServicesType::COMPOUND_RATING,$user->getId()) : false,];if ($mobileDetection['isMobile']) {$nearestLocations = $em->getRepository(\Aqarmap\Bundle\ListingBundle\Entity\Location::class)->getNearestLocations([$listing->getLocation()]);$return['nearestLocations'] = $nearestLocations;foreach ($mobileDetection as $key => $val) {$return[$key] = $val;}return $this->render('@AqarmapListing/Listing/read-mob.html.twig', $return);}$return['discussions'] = $em->getRepository(\Aqarmap\Bundle\DiscussionBundle\Entity\Discussion::class)->getTrendingWithLocation($listing->getLocation()->getId(), 3);return $this->render('@AqarmapListing/Listing/read.html.twig', $return);}/*** TopSeller Attributes from listing data.** @param Listing** @return TopSeller*/private function createTopSeller($listing){$topSeller = new TopSeller();$topSeller->setLocation($listing->getLocation()->getId());$topSeller->setSection($listing->getSection()->getId());$topSeller->setPropertyType($listing->getPropertyType()->getId());return $topSeller;}/*** Advanced Search Form.*/protected function createAdvancedSearchForm(): FormInterface{return $this->advancedSearchFormTypeManager->setAction($this->generateUrl('listing_advanced_search'))->setFormType(AdvancedSearchType::class)->setMethodType('Post')->setSettings($this->setting)->applyOptions()->createForm();}/*** Advanced Search Form.*/protected function createAdvancedFilterForm(): FormInterface{$customFields = $this->customFieldService->getCachedCustomFields();return $this->advancedFilterFormTypeManager->setAction($this->generateUrl('listing_filter_search'))->setFormType(AdvancedFilterType::class)->setMethodType('Post')->setSettings($this->setting)->setCustomFields($customFields)->applyOptions()->createForm();}/*** Multiple Search Form.*/protected function createMultipleSearchForm(): FormInterface{return $this->advancedSearchFormTypeManager->setAction($this->generateUrl('listing_multiple_search'))->setFormType(MultipleSearchFormType::class)->setMethodType('Post')->setSettings($this->setting)->applyOptions()->createForm();}/*** Latest Listings Action.*/#[Route(path: '/listing/latest', name: 'listing_latest', methods: ['GET'])]public function latest(Request $request): Response{/** @var EntityManager $em */$em = $this->managerRegistry->getManager();$pagination = $this->paginator->paginate($em->getRepository(Listing::class)->getLatestListings(),$request->query->getInt('page', 1));return $this->render('@AqarmapListing/Listing/latest.html.twig', ['listings' => $pagination,]);}#[Route(path: '/listing/latest/{section}.{_format}')]public function CSVLatestListings(Request $request, Section $section): Response{/** @var EntityManager $em */$em = $this->managerRegistry->getManager();$listings = $em->getRepository(Listing::class)->findBy(['section' => $section,'status' => ListingStatus::LIVE,], ['id' => 'desc'], 100);$handle = fopen('php://memory', 'r+');fputcsv($handle, [$request->query->get('id', 'id'),$request->query->get('section', 'section'),$request->query->get('description', 'description'),$request->query->get('image', 'image'),$request->query->get('link', 'link'),$request->query->get('title', 'title'),$request->query->get('price', 'price'),$request->query->get('formatted_price', 'formatted_price'),$request->query->get('price_currency', 'price_currency'),$request->query->get('location', 'location'),$request->query->get('address', 'address'),$request->query->get('property_type', 'property_type'),$request->query->get('availability', 'availability'),$request->query->get('condition', 'condition'),]);foreach ($listings as $listing) {$thumb = null;if ($listing->getMainPhoto()) {$thumb = $this->imagine->generateUrl($this->uploaderHelper->asset($listing->getMainPhoto()->getFile(), 'file'),'large');}$description = preg_split('/\n/', mb_substr($listing->getDescription(), 0, 200), \PREG_SPLIT_DELIM_CAPTURE);fputcsv($handle, [$listing->getId(),$section->getTitle(),$description[0],$thumb,$this->generateUrl('listing_view', ['id' => $listing->getId()], true),$listing->getTitle(),$listing->getPrice(),number_format($listing->getPrice()),sprintf('%s %s', number_format($listing->getPrice()), 'EGP'),$listing->getLocation()->getTitle(),$listing->getAddress(),$listing->getPropertyType()->getTitle(),'in stock','new',]);}rewind($handle);$content = stream_get_contents($handle);fclose($handle);return new Response($content, Response::HTTP_OK, ['Content-Type' => 'application/force-download','Content-Disposition' => sprintf('attachment; filename="latest-listings - %s - %s.csv"',$section->getTitle(),date('Y-m-d H-i-s')),]);}/*** @deprecated** @return array*/#[Route(path: '/listing/{id}/one', name: 'landing_page', methods: ['GET', 'POST'])]#[Rest\View]public function landingPage(Request $request, Listing $listing){$form = $this->createForm(LandingPageFormType::class, $landingPage = new LandingPage(), ['action' => $this->generateUrl('landing_page', ['id' => $listing->getId()]),]);$form->handleRequest($request);if ($form->isSubmitted() && $form->isValid()) {if (!($user = $this->FOSUserManager->findUserByEmail($landingPage->getUser()->getEmail()))) {$user = $this->userManager->createUserWithoutPassword($form->get('user')->getData(), $form->get('user'), $request);}if (!$form->get('message')->getData()) {$callRequest = new CallRequest();$callRequest->setListing($listing);$callRequest->setUser($user);$this->callRequestManager->submitCallRequest($callRequest);} else {// Compose a message$composer = $this->messageComposer;$composer->setSender($user);$composer->compose($form->get('message')->getData(), $listing);}}return ['form' => $form->createView(),'listing' => $listing,];}/*** Add Listing First Step Action.*/#[Route(path: '/listing/initialize', name: 'listing_initialize', options: ['expose' => true])]public function initialize(Request $request){$user = $this->getUser();if (false === $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {return $this->redirectToRoute('aqarmap_add_listing');}$isPhoneVerified = true;if ($user instanceof User) {$isPhoneVerified = $user->isPhoneVerified();}$hasRentalPackage = $this->userPackagesRepository->hasRentalPackage($user);$initializeOptions = ['action' => $this->generateUrl('listing_initialize'),'method' => 'POST','em' => $this->managerRegistry->getManager(),'is_admin' => $this->authorizationChecker->isGranted('ROLE_ADMIN'),'has_rental_package' => $hasRentalPackage,'parentUser' => $user,];$form = $this->createForm(ListingInitializeType::class, $listing = new Listing(), $initializeOptions);$listingEvent = new ListingEvent($listing);$this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.pre_submitted');$form->handleRequest($request);if ($form->isSubmitted() && $form->isValid() && ($isPhoneVerified || $user->getHasActiveSubscription())) {$listing = $this->listingManager->createDraft($listing);// Add user phone number to the listingif ($listing->getUser()->getPhoneNumber()) {// link user phone with this listing// TODO: Suggest only the main number for now, later on we will suggest the main + last 2 numbers.$this->listingManager->suggestListingPhoneNumbers([$listing->getUser()->getPhoneNumber()],$listing);}return $this->redirectToRoute('listing_edit', ['id' => $listing->getId(),]);}return $this->render('@AqarmapListing/Listing/initialize.html.twig', ['form' => $form,'isPhoneVerified' => $isPhoneVerified,]);}/*** Add Listing V2.** @throws \Doctrine\ORM\NonUniqueResultException*/#[Route(path: '/listing/initialize/{step}', name: 'add_listing')]#[Route(path: '/listing/initialize/{id}/{step}', name: 'edit_listing')]#[IsGranted(attribute: 'IS_AUTHENTICATED_REMEMBERED')]public function addListing(): Response{return $this->render('@AqarmapListing/Listing/add.html.twig', ['title' => $this->translator->trans('listing.add_your_listing'),'featureToggle' => ['accept_adding_phones' => $this->featureToggleManager->isEnabled('web.addlisting.accept_adding_phones'),'google_maps_location' => $this->featureToggleManager->isEnabled('web.addlisting.google_maps_location'),],]);}/*** Add Listing groups.** @throws \Doctrine\ORM\NonUniqueResultException*/#[Route(path: '/listing/add/', name: 'add_listing_steps')]#[Route(path: '/listing/{id}/edit/steps', name: 'edit_listing_steps')]#[IsGranted(attribute: 'IS_AUTHENTICATED_REMEMBERED')]public function addListingSteps(): Response{return $this->render('@AqarmapListing/Listing/addSteps.html.twig', ['title' => $this->translator->trans('listing.add_your_listing'),'featureToggle' => ['accept_adding_phones' => $this->featureToggleManager->isEnabled('web.addlisting.accept_adding_phones'),'google_maps_location' => $this->featureToggleManager->isEnabled('web.addlisting.google_maps_location'),],]);}/*** Listing Post Action* This action manage adding & editing listings.*/#[Route(path: '/listing/{id}/edit/', name: 'listing_edit', requirements: ['id' => '\d+'], options: ['expose' => true])]#[IsGranted(attribute: new Expression('(is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])) or is_granted("ROLE_ADMIN")'), subject: ['listing'])]public function post(Request $request, Listing $listing): Response{$user = $this->getUser();// if user doesn't have phone or active subscription, redirect to my listings with an error flash messageif ($user instanceof User && (!$user->isPhoneVerified() && !$user->getHasActiveSubscription())) {$this->addFlash('danger', $this->translator->trans('listing.notice.cannot_add_before_verify'));return $this->redirectToRoute('aqarmap_listing_default_mylistings');}$form = $this->createForm(ListingType::class, $listing, ['action' => $this->generateUrl('listing_edit', ['id' => $listing->getId()]),'method' => 'POST','listingIsLiveFor5Days' => $this->listingManager->checkListingLiveDays($listing),'is_admin' => $this->authorizationChecker->isGranted('ROLE_ADMIN'),'user_country' => $this->setting->getSetting('general', 'country'),'user_type' => $listing->getUser()?->getUserType(),'isMortgageOptionsEnabled' => $this->featureToggleManager->isEnabled('web.mortgage.options'),'isListingMarketPropertyTypesEnabled' => $this->featureToggleManager->isEnabled('web.listing.market.property.types'),]);$form->handleRequest($request);if ($request->isMethod('POST')) {if ($form->isSubmitted() && $form->isValid()) {$this->updateWhatsAppPhones($listing->getUser()->getId(), $request->request->all('phoneIds'), $request->request->all('hasWhatsApp'));$listing = $this->handleListingPhones($listing, $request->request->all('listing')['phones'] ?? []);$this->handleUserPhones($listing->getUser(), $request->request->all('listing')['phones'] ?? []);$this->listingManager->saveListing($listing);if ($this->featureToggleManager->isEnabled('web.add.listing.translations')) {if ('en' == $request->getLocale()) {$criteria = ['reversedLocale' => 'ar','title-ar' => $request->request->get('title-ar'),'description-ar' => $request->request->get('description-ar'),];} else {$criteria = ['reversedLocale' => 'en','title-en' => $request->request->get('title-en'),'description-en' => $request->request->get('description-en'),];}$this->listingManager->updateListingTranslationsFields($listing, $criteria);} else {$this->listingManager->updateListingTranslations($listing);}if ($this->featureToggleManager->isEnabled('web.mortgage.options')) {$propertyRegistrationStatus = $form->has('propertyRegistrationStatus') ? $form->get('propertyRegistrationStatus')->getData() : null;if (\in_array($propertyRegistrationStatus, PropertyRegistrationStatusOption::getValidMorgageOptions())) {$this->mortgageService->addEligibleMortgageTypes($listing);} else {$this->listingManager->setELigibleMortgageToNull($listing);}$listing = $this->mortgageService->addMortgageApproval($listing, $form);}$listingEvent = new ListingEvent($listing);$this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');if (ListingSource::SCRAPPING == $listing->getSource()|| ListingSource::LITE == $listing->getSource()) {return $this->redirectToRoute('listing_view', ['id' => $listing->getId()]);}return $this->redirectToRoute('listing_upload', ['id' => $listing->getId(), '_locale' => $request->get('_locale')]);}$this->addFlash('danger', $this->translator->trans('static.problem_error_message'));}$translatedLocale = 'en' == $request->getLocale() ? 'ar' : 'en';return $this->render('@AqarmapListing/Listing/post.html.twig', ['form' => $form,'listing' => $listing,'title_translation' => $this->listingTitleTranslations($listing, $translatedLocale),'description_translation' => $this->listingDescriptionTranslations($listing, $translatedLocale),'brokerChoices' => UserTypes::getBrokerChoices(),]);}/*** @return array|mixed*/private function listingTitleTranslations(Listing $listing, string $locale){$this->translatableListener->setTranslatableLocale($locale);$listing->setTranslatableLocale($locale);return $listing->getTitle() ?? $this->listingManager->listingTitleTranslations($listing, $locale);}private function listingDescriptionTranslations(Listing $listing, string $locale){$this->translatableListener->setTranslatableLocale($locale);$listing->setTranslatableLocale($locale);return $listing->getDescription() ?? $this->listingManager->listingTitleTranslations($listing, $locale);}private function handleListingPhones(Listing $listing, array $phones): Listing{$listing->clearPhones();foreach ($phones as $phone) {$phoneNumber = $phone['number'];$countryCode = $phone['countryCode'];$phone = new Phone($countryCode.$phoneNumber, $countryCode);$listing->addPhone(new ListingPhone($phoneNumber, $listing, $countryCode, $phone));}return $listing;}private function handleUserPhones(User $user, array $phones): void{foreach ($phones as $phone) {$originalPhoneNumber = $phone['number'];$countryCode = $phone['countryCode'];$phoneNumber = $this->phoneManager->trimZero($originalPhoneNumber, $countryCode);$this->phoneManager->addNewUserPhone($phoneNumber, $countryCode, $user, true, false, null, $originalPhoneNumber);}}/*** Listing Post Action* This action manage adding & editing listings.** @return array|RedirectResponse*/#[Route(path: '/listing/{id}/preview/', name: 'listing_preview', requirements: ['id' => '\d+'])]#[IsGranted(attribute: new Expression("(is_granted('IS_AUTHENTICATED_REMEMBERED') and is_granted('ROLE_OWNER', listing)) or is_granted('ROLE_ADMIN')"))]public function preview(Listing $listing): Response{return $this->render('@AqarmapListing/Listing/preview.html.twig', ['listing' => $listing,]);}/*** Listing Post Action* This action manage adding & editing listings.*/#[Route(path: '/listing/lite', name: 'listing_lite_add')]public function postLite(Request $request){/** @var EntityManager $em */$em = $this->managerRegistry->getManager();$form = $this->createForm(LiteListingType::class,null,['em' => $em,'action' => $this->generateUrl('listing_lite_add'),'method' => 'post',]);if ($request->isMethod('POST')) {$form->handleRequest($request);if ($form->isSubmitted() && $form->isValid()) {$listing = $form->getData();$listing->setSellerRole(ListingSellerRoles::OWNER);$this->listingManager->saveListing($listing);// add listing phone to new phones table ;$this->phoneManager->addListingPhonesList($listing->getPhones(), '', $listing);$this->listingManager->addLiteListingTitleAndDescriptionTranslation($listing);$listingEvent = new ListingEvent($listing);$this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.padding_review'));if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {$this->addFlash('info',$this->translator->trans('add_listing_page.info_messages.eid_delayed_review'));}return $this->redirectToRoute('homepage');}$this->addFlash('danger', $this->translator->trans('static.problem_error_message'));}return $this->render('@AqarmapListing/Listing/postLite.html.twig', ['form' => $form,]);}/*** Add Listing First Step Action.*/#[Route(path: '/listing/{id}/edit/photos', name: 'listing_upload', requirements: ['id' => '\d+'], options: ['expose' => true])]#[IsGranted(attribute: new Expression('(is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])) or is_granted("ROLE_ADMIN")'), subject: ['listing'])]public function upload(Request $request, Listing $listing){$form = $this->createForm(PhotoType::class, null, ['method' => 'POST',]);$form->handleRequest($request);$listingRules = $this->listingRuleMatcher->match($listing);if ($form->isSubmitted() && $form->isValid() && $request->isMethod('POST')) {$listingPhotos = [];try {$listingPhotos = $this->listingManager->addListingPhotos($listing, $form->get('file')->getData());$listingEvent = new ListingEvent($listing);$this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');$this->listingManager->saveListing($listing);// If not Ajax requestif (!$request->isXmlHttpRequest()) {$this->logger->error('Not AJAX');return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));}} catch (\Exception $exception) {$this->logger->error($exception->getMessage());}return View::create(['files' => $listingPhotos], Response::HTTP_OK);}return $this->render('@AqarmapListing/Listing/upload.html.twig', ['requiredPhotosCount' => $listingRules['required_photos'] ?? 0,'listing' => $listing,'form' => $form,]);}/*** Should be called after photos are uploaded.*/#[Route(path: '/listing/{id}/finish', name: 'listing_finish', requirements: ['id' => '\d+'])]#[IsGranted(attribute: new Expression('(is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])) or is_granted("ROLE_ADMIN")'), subject: ['listing'])]public function finish(Listing $listing, UserPackagesService $userPackagesService): Response{$listingEvent = new ListingEvent($listing);if (!$userPackagesService->canListInLocation($listing)) {$this->addFlash('danger', $this->translator->trans('credit.can_not_list_in_location'));return $this->redirectToRoute('listing_upload', ['id' => $listing->getId(),], Response::HTTP_FOUND);}$this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');$response = $listingEvent->getResponse();if (null === $response) {if (ListingStatus::PENDING === $listing->getStatus()) {$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.padding_review'));if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {$this->addFlash('info',$this->translator->trans('add_listing_page.info_messages.eid_delayed_review'));}}$response = new RedirectResponse($this->generateUrl('listing_slug',['id' => $listing->getId(), 'slug' => $listing->getSlug()]));}return $response;}/*** SWAT special add listing feature page.*/#[Route(path: '/listing/{id}/feature', requirements: ['id' => '\d+'], name: 'special_add_listing_feature')]#[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]public function specialAddListingFeature(Listing $listing): RedirectResponse{return $this->redirectToRoute('listing_finish', ['id' => $listing->getId()]);}/*** @return RedirectResponse|Response*/#[Route(path: '/listing/{id}/make_it_featured', requirements: ['id' => '\d+'], name: 'listing_confirm_featured_credit', methods: ['GET'])]#[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]public function confirmFeaturedPublishing(Listing $listing){if (!\in_array($listing->getStatus(), [ListingStatus::PENDING, ListingStatus::LIVE])) {$this->addFlash('danger',$this->translator->trans('listing.featured_failure_statement.not_live_or_pending'));return $this->redirectToRoute('aqarmap_listing_default_mylistings');}if (UserTypes::INDIVIDUAL == $listing->getUser()->getUserType()) {$listingRules = $this->listingFeatureService->getFeaturedListingRules($listing, ['sold_by_owner', 'sold_by_owner_sponsored']);} else {$listingRules = $this->listingFeatureService->getFeaturedListingRules($listing, ['featured', 'premium', 'sponsored', 'spotlight']);}/** @var User $user */$user = $this->getUser();return $this->render('@AqarmapListing/Listing/featuredListingCheckout.html.twig',['listingRules' => $listingRules,'listingId' => $listing->getId(),'haveFeesToFeature' => $this->listingManager->userHasFeesToFeature($user, $listing),]);}#[Route(path: '/listing/{id}/make_it_featured', options: ['expose' => true], requirements: ['id' => '\d+'], name: 'listing_confirm_publish_featured_credit_post', methods: ['POST'])]#[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]public function prepareFeaturedListingPayment(Listing $listing, Request $request): RedirectResponse{$listingRules = $this->listingManager->getListingRules($listing);$fees = $request->query->get('fees', $listingRules['featured_fees']);$duration = $request->query->get('duration', $listingRules['featured_duration']);$listingFeaturedType = $request->query->get('listingFeaturedType', ListingFeaturedTypes::FEATURED);$listingFeature = $request->query->get('listingFeature', ListingFeatures::FEATURED);$listingStatus = $listing->getStatus();/** @var User $user */$user = $this->getUser();if (!$this->listingManager->isAffordable($user, $fees)) {$this->addFlash('danger', $this->translator->trans('credit.not_enough_featuring_credit', ['link' => $this->generateUrl('aqarmap_buy_credit', ['listing_id' => $listing->getId()]),]));return $this->redirectToRoute('listing_confirm_featured_credit', ['id' => $listing->getId(),], Response::HTTP_FOUND);}$featuredText = $this->translator->trans(ListingFeaturedTypes::getFeaturedText($listingFeaturedType));$rules = ['featuredFees' => $fees,'featuredDuration' => $duration,'listingFeaturedType' => $listingFeaturedType,'listingFeature' => $listingFeature,'featuredText' => $featuredText,];if ($this->listingManager->requiresFeaturingReview($listingFeaturedType)) {try {$this->listingManager->makeItFeatured($listing, $rules);if (ListingStatus::LIVE == $listingStatus) {$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.pending_featuring', [':featured_type:' => $featuredText]));} else {$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.padding_review'));if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {$this->addFlash('info',$this->translator->trans('add_listing_page.info_messages.eid_delayed_review'));}}} catch (\Exception $exception) {$this->addFlash('danger', $this->translator->trans($exception->getMessage()));}if (ListingStatus::LIVE == $listingStatus) {return $this->redirectToRoute('aqarmap_listing_default_mylistings');}return $this->redirectToRoute('listing_finish', ['id' => $listing->getId(),]);}try {$this->listingManager->makeItFeatured($listing, $rules);if (ListingStatus::LIVE == $listing->getStatus()) {$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.featured',[':listing_title:' => $listing->getTitle(), ':featured_type:' => $featuredText]));return $user->hasValidAccessToLiveApp() ?$this->redirect(sprintf('%s/%s', $this->getParameter('user_dashboard_url'), 'listings')) :$this->redirectToRoute('aqarmap_listing_default_mylistings');}$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.padding_review'));if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {$this->addFlash('info',$this->translator->trans('add_listing_page.info_messages.eid_delayed_review'));}return $this->redirectToRoute('listing_finish', ['id' => $listing->getId(),]);} catch (\Exception $e) {$buyCreditLink = $this->generateUrl('page_view', ['slug' => 'buy-credit'], true);if ($this->setting->getSetting('features', 'payments')) {$buyCreditLink = $this->generateUrl('aqarmap_buy_credit');}$this->addFlash('danger', $this->translator->trans($e->getMessage(),['%link%' => $buyCreditLink],'exceptions'));}return $this->redirectToRoute('listing_confirm_featured_credit', ['id' => $listing->getId(),], Response::HTTP_FOUND);}/*** @return array|RedirectResponse*/#[Route(path: '/listing/{id}/payment_confirmation', requirements: ['id' => '\d+'], name: 'listing_confirm_publish_credit', methods: ['GET'])]#[IsGranted(attribute: new Expression('is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])'), subject: ['listing'])]public function confirmPublishing(Listing $listing, UserPackagesService $userPackagesService): Response{$listingRule = $this->listingRuleMatcher->match($listing);/** @var EntityManager $em */$em = $this->managerRegistry->getManager();// User Balance$userDetails = $listing->getUser();$available_balance = $this->userPackagesRepository->getTotalCreditsByUser($userDetails);$userId = $userDetails->getId();$em->getRepository(User::class)->findOneBy(['id' => $userId]);$listingManger = $this->listingManager;if (!$userPackagesService->canListInLocation($listing)) {$this->addFlash('danger', $this->translator->trans('credit.can_not_list_in_location'));return $this->redirectToRoute('listing_upload', ['id' => $listing->getId(),], Response::HTTP_FOUND);}$userServiceRepository = $em->getRepository(UserServices::class);if ($this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS, $userId)&& ListingCategories::UNLIMITED != $listing->getCategory()&& ListingStatus::DRAFT != $listing->getStatus()) {if ($userServiceRepository->passUnlimitedListing($listing, $this->creditManager, $listingManger) || $listing->getPublicationCredit()) {if ($this->listingFeatureService->isFeaturedOffersAvailable($listing)) {return $this->redirectToRoute('listing_confirm_featured_credit', ['id' => $listing->getId(),]);}return $this->redirectToRoute('listing_finish', ['id' => $listing->getId(),]);}}$isUserInSpecialAddListingGroup = $this->specialAddListingService->hasSpecialAddListingGroup($userDetails);$userUnlimitedListings = $this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS, $userId);$userHasNoFreeListingService = !$userUnlimitedListings;$userHasNoFreeListingQuote = ($userUnlimitedListings && 0 == $userUnlimitedListings['remainingQuota']);if ($isUserInSpecialAddListingGroup) {if ($userHasNoFreeListingService || $userHasNoFreeListingQuote) {return $this->redirectToRoute('special_add_listing_feature', ['id' => $listing->getId()]);}}$form = $this->ConfirmPaymentForm($listing);return $this->render('@AqarmapListing/Listing/confirmPublishing.html.twig',['listing' => $listing,'fees' => $listingRule['publication_fees'],'duration' => $listingRule['duration'],'available_balance' => $available_balance,'form' => $form->createView(),]);}/*** @return array*/#[Route(path: '/listing/{id}/list_rejections', requirements: ['id' => '\d+'], name: 'listing_list_rejections', methods: ['GET'])]#[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]public function listRejections(Listing $listing, Request $request): Response{if ($request->get('notification')) {try {$this->databaseNotification->markOneAsRead($request->get('notification'));} catch (\Exception $exception) {$this->logger->log(LogLevel::ERROR, $exception->getMessage());}}return $this->render('@AqarmapListing/Listing/confirmPublishing.html.twig',['listing' => $listing,]);}/*** @return array|RedirectResponse*/#[Route(path: '/listing/{id}/payment_confirmation', requirements: ['id' => '\d+'], name: 'listing_confirm_publish_credit_post', methods: ['POST'])]#[IsGranted(attribute: new Expression('is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])'), subject: ['listing'])]public function prepareListingPayment(Listing $listing, Request $request, UserPackagesService $userPackagesService): RedirectResponse{$listingRule = $this->listingRuleMatcher->match($listing);/** @var EntityManager $em */$em = $this->managerRegistry->getManager();// User Balance$available_balance = $this->userPackagesRepository->getTotalCreditsByUser($listing->getUser());$userId = $listing->getUser()->getId();$listingManger = $this->listingManager;if (!$userPackagesService->canListInLocation($listing)) {$this->addFlash('danger', $this->translator->trans('credit.can_not_list_in_location'));return $this->redirectToRoute('listing_upload', ['id' => $listing->getId(),], Response::HTTP_FOUND);}$userServiceRepository = $em->getRepository(UserServices::class);if ($this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS, $userId)) {if ($userServiceRepository->passUnlimitedListing($listing, $this->creditManager, $listingManger)) {if (!$this->listingFeatureService->isFeaturedOffersAvailable($listing)) {return $this->redirectToRoute('listing_finish', ['id' => $listing->getId(),]);}return $this->redirectToRoute('listing_confirm_featured_credit', ['id' => $listing->getId(),]);}}$form = $this->ConfirmPaymentForm($listing);$form->handleRequest($request);if ($form->isSubmitted() && $form->isValid()) {// Payment Confirmed?// If user cancel payment redirect him to his listing,if (!$form->get('confirm')->isClicked()) {return $this->redirectToRoute('listing_view', ['id' => $listing->getId(),], Response::HTTP_FOUND);}// If user credit expired, complain.$enforceCredit = $this->setting->getSetting('features', 'enforce_credits_expiration');/** @var User $user */$user = $this->getUser();if ($enforceCredit && 0 === $user->getAbsoluteCreditExpiryDays()) {$this->addFlash('danger', $this->translator->trans('credit.credit_can_not_use', ['link' => $this->generateUrl('aqarmap_buy_credit', ['listing_id' => $listing->getId()]),]));return $this->redirectToRoute('listing_confirm_publish_credit', ['id' => $listing->getId(),], Response::HTTP_FOUND);}// User already paidif ($listing->getPublicationCredit()) {$this->addFlash('info', $this->translator->trans('credit.already_paid'));} else {// User don't have enough creditsif ($listingRule['publication_fees'] > $available_balance) {$this->addFlash('danger', $this->translator->trans('credit.not_enough_credits'));} else {// Subtract publication fees$credits = $this->creditManager->deduction($listing->getUser(),$listingRule['publication_fees'],'Listing Fees');foreach ($credits as $credit) {if ($credit instanceof Credit) {$credit->setStatus(CreditStatus::SUCCESS);$this->listingManager->addFeature($listing, ListingFeatures::PAID, null, $credit);if (!$this->listingFeatureService->isFeaturedOffersAvailable($listing)) {return $this->redirectToRoute('listing_finish', ['id' => $listing->getId(),]);}}}return $this->redirectToRoute('listing_confirm_featured_credit', ['id' => $listing->getId(),'ref' => 'add_listing',]);}}}$this->addFlash('danger', 'Unexpected error occurred.');return $this->redirectToRoute('listing_confirm_publish_credit', ['id' => $listing->getId(),]);}private function ConfirmPaymentForm(Listing $listing){return $this->createForm(ConfirmFormType::class, null, ['method' => 'POST','action' => $this->generateUrl('listing_confirm_publish_credit_post', ['id' => $listing->getId()]),]);}/*** @return \Symfony\Component\Form\Form*/private function confirmFeaturedPaymentForm(Listing $listing){return $this->createForm(ConfirmFeaturedFormType::class, null, ['method' => 'POST','action' => $this->generateUrl('listing_confirm_publish_featured_credit_post',['id' => $listing->getId()]),]);}/*** Delete Listing entity.*/#[Route(path: '/listing/{id}/delete', requirements: ['id' => '\d+'], name: 'listing_delete', options: ['expose' => true])]#[IsGranted(attribute: new Expression('is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])'), subject: ['listing'])]public function delete(Listing $listing, Request $request): RedirectResponse{if (\in_array('ROLE_PREVENT_DELETE_LISTING', $this->getUser()->getRoles())) {throw new AccessDeniedHttpException("Forbidden, user don't have this permession.");}if (ListingStatus::EXPIRED == $listing->getStatus()) {throw $this->createNotFoundException('Listing is expired.');}$this->listingManager->remove($listing, ListingStatus::USER_DELETED);$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.deleted'));return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));}/*** unDelete Listing entity.*/#[Route(path: '/listing/{id}/undelete', requirements: ['id' => '\d+'], name: 'listing_undelete')]#[IsGranted(attribute: new Expression('is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])'), subject: ['listing'])]public function undelete(Listing $listing): Response{if (ListingStatus::USER_DELETED != $listing->getStatus()) {throw $this->createNotFoundException('Unable to find this listing.');}$this->managerRegistry->getManager();$this->listingManager->changeStatus($listing, ListingStatus::PENDING);$listingEvent = new ListingEvent($listing);$this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');$response = $listingEvent->getResponse();if (null === $response) {if (ListingStatus::PENDING === $listing->getStatus()) {$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.padding_review'));if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {$this->addFlash('info',$this->translator->trans('add_listing_page.info_messages.eid_delayed_review'));}}$response = new RedirectResponse($this->generateUrl('listing_slug',['id' => $listing->getId(), 'slug' => $listing->getSlug()]));}return $response;}/*** Creates "Request a Call" button.** @return \Symfony\Component\Form\Form*/public function callRequestForm(Listing $listing){return $this->createForm(CallRequestFormType::class, null, ['method' => 'POST','action' => $this->generateUrl('aqarmap_listing_call_request', ['id' => $listing->getId()]),]);}/*** Creates contact seller form.** @param Listing $listing The listing entity** @return \Symfony\Component\Form\Form The form*/public function contactSellerForm(Listing $listing){return $this->createForm(ContactSellerFormType::class, null, ['method' => 'POST','action' => $this->generateUrl('aqarmap_listing_contact_seller', ['id' => $listing->getId()]),]);}/*** Creates contact seller form.** @param Listing $listing The listing entity** @return \Symfony\Component\Form\Form The form*/public function contactSellerWideForm(Listing $listing){return $this->createForm(ContactSellerWideFormType::class, null, ['method' => 'POST','action' => $this->generateUrl('aqarmap_listing_contact_seller', ['id' => $listing->getId()]),]);}/*** Creates quick registration form.** @return \Symfony\Component\Form\Form The form*/public function quickRegistrationForm(){return $this->createForm(QuickRegistrationFormType::class, null, ['method' => 'POST','action' => $this->generateUrl('aqarmap_user_quick_registration'),]);}/*** Contact Seller Action.** @return array|\Symfony\Component\Form\Form*/#[Route(path: '/listing/{id}/contact_seller', requirements: ['id' => '\d+'], name: 'aqarmap_listing_contact_seller', options: ['expose' => true], defaults: ['_format' => 'json'], methods: ['POST'])]#[Rest\View]public function contactSeller(Listing $listing, Request $request){$form = $this->contactSellerForm($listing);if ($request->request->has('contact_seller_wide')) {$form = $this->contactSellerWideForm($listing);}$lead = $request->get('lead');$originalPhoneNumber = $lead['phone'];$phoneNumber = $lead ? $this->phoneManager->trimZero($lead['phone'], $request->get('countryCode')) : null;$message = json_decode((string) $request->get('message'), true);$hasEmail = !$request->get('isAutoGeneratedEmail', 0);$user = $this->getUser();$form->handleRequest($request);if ($lead) {$form = $this->createForm(QuickLeadType::class, null, ['method' => 'POST','csrf_protection' => false,]);/** @var User $user */$user = $this->FOSUserManager->findUserByEmail($lead['email']);if (!$user && !$hasEmail) {$user = $this->userManager->findLatestByPhone($phoneNumber, $request->get('countryCode'));}if (!$user && $hasEmail) {$user = $this->userManager->findAndReplaceUserAndEmail($phoneNumber, $lead['email'], $request->get('countryCode'));}$phone = $this->phoneManager->findOrSavePhoneNumber($phoneNumber, $request->get('countryCode'), null, $originalPhoneNumber);if (!$user) {$user = $this->FOSUserManager->createUser();$user->setFullName($lead['name'])->setPhoneNumber($lead['phone'])->setTempOriginalPhoneNumber($originalPhoneNumber)->setEmail($lead['email'])->setHasEmail($hasEmail)->setIsQucikRegistered(true);$this->userManager->quickRegister($user, $form, $request, true, false, false);$registerMessage = $this->translator->trans('popup_form.success');}$this->phoneManager->addNewUserPhone($phoneNumber, $request->get('countryCode'), $user, true, false, null, $originalPhoneNumber);}if ($request->isMethod('POST')) {// Get current logged in user$user ??= $this->getUser();$composer = $this->messageComposer;$composer->setSender($user)->compose($message['content'], $listing, null, $message['type'] ?? LeadTypes::SEND_MESSAGE);$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.message_sent'));return ['status' => 'ok','message' => $this->translator->trans('listing.success_message_seller'),];}return $form;}/*** Contact Seller Action.*/#[Route(path: '/listing/{id}/call_request', requirements: ['id' => '\d+', '_format' => 'json'], name: 'aqarmap_listing_call_request', options: ['expose' => true], defaults: ['_format' => 'json'], methods: ['POST'])]#[Rest\View]public function callRequest(Request $request, Listing $listing){$lead = $request->get('lead');$countryCode = $request->get('countryCode', $lead['countryCode'] ?? '+20');$originalPhoneNumber = $lead['phone'];$phoneNumber = $lead ? $this->phoneManager->trimZero($lead['phone'], $countryCode) : null;$user = $this->getUser();$registerMessage = '';$callRequest = new CallRequest();if ($lead) {$form = $this->createForm(QuickLeadType::class, null, ['method' => 'POST','csrf_protection' => false,]);$form->handleRequest($request);$hasEmail = !$request->get('isAutoGeneratedEmail', 0);/** @var User $user */$user = $this->FOSUserManager->findUserByEmail($lead['email']);if (!$user && !$hasEmail) {$user = $this->userManager->findLatestByPhone($phoneNumber, $countryCode);}if (!$user && $hasEmail) {$user = $this->userManager->findAndReplaceUserAndEmail($phoneNumber, $lead['email'], $request->get('countryCode'));}$phone = $this->phoneManager->findOrSavePhoneNumber($phoneNumber, $countryCode, null, $originalPhoneNumber);if (!$user) {$user = $this->FOSUserManager->createUser();$user->setFullName($lead['name'])->setPhoneNumber($lead['phone'])->setTempCountryCode($countryCode)->setTempOriginalPhoneNumber($originalPhoneNumber)->setEmail($lead['email'])->setHasEmail($hasEmail)->setIsQucikRegistered(true);$this->userManager->quickRegister($user, $form, $request, true, false, false);$registerMessage = $this->translator->trans('popup_form.success');}$callRequest->setPhone($phone);$callRequest->setLeadEmail($lead['email']);$callRequest->setLeadFullName($lead['name']);$this->phoneManager->addNewUserPhone($phoneNumber, $countryCode, $user, true, false, null, $originalPhoneNumber);}// Create Call Request$callRequest->setUser($user);$callRequest->setListing($listing);$form = $this->callRequestForm($listing);$form->handleRequest($request);$isPostRequestAndValidForm = $request->isMethod('POST') && ($form->isSubmitted() && $form->isValid());$isNotCheckForm = (false == $request->get('check_form'));if ($isPostRequestAndValidForm || $isNotCheckForm) {try {$this->callRequestManager->submitCallRequest($callRequest, null, $request->query->get('sourceRoute', ''));return ['status' => 'ok','message' => $this->translator->trans('listing.success_call_request'),'registerMessage' => $registerMessage,];} catch (InvalidLeadValidationHttpException $exception) {return ['status' => $exception->getStatusCode(),'message' => $exception->getMessage(),];}}return $form;}/*** Show how to add a listing for new users.*/#[Route(path: '/add_listing', name: 'aqarmap_add_listing')]public function addListingRoles(): Response{return $this->render('@AqarmapListing/Listing/addListingRoles.html.twig',[]);}/*** @return RedirectResponse|Response*/#[Route(path: '/listing/{id}/relist', requirements: ['id' => '\d+'], name: 'aqarmap_listing_relist', options: ['expose' => true])]#[IsGranted(attribute: new Expression('is_granted("ROLE_USER") and is_granted("ROLE_OWNER", subject["listing"])'), subject: ['listing'])]public function relist(Listing $listing){if (!\in_array($listing->getStatus(), [ListingStatus::EXPIRED, ListingStatus::USER_DELETED])) {throw new LogicHttpException('Whoops! Looks like the listing you are trying to relist in not expired!');}$em = $this->managerRegistry->getManager();$listingRepo = $em->getRepository(Listing::class);$relistChild = $listingRepo->getRelistChild($listing);if ($relistChild) {$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.relist'));return new RedirectResponse($this->generateUrl('listing_slug',['id' => $relistChild->getId(),'slug' => $relistChild->getSlug(),]));}$listing = $this->listingManager->relist($listing);// Check if the listing require more photos or require repayment, and redirection.$listingEvent = new ListingEvent($listing);$this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.resubmitted');$response = $listingEvent->getResponse();if (null === $response) {if (\in_array($listing->getStatus(), [ListingStatus::PENDING, ListingStatus::LIVE])) {$this->addFlash('success',$this->translator->trans('add_listing_page.success_messages.relist'));}$response = new RedirectResponse($this->generateUrl('listing_slug',['id' => $listing->getId(),'slug' => $listing->getSlug(),]));}return $response;}#[Route(path: '/listing/transfer/scraped/{id}', requirements: ['id' => '\d+'], name: 'aqarmap_listing_transfer_ownership', options: ['expose' => true], methods: ['POST'])]public function transferScrapedListingOwnership(Listing $listing): JsonResponse{/** @var User $user */$user = $this->getUser();/** @var EntityManager $em */$em = $this->managerRegistry->getManager();if (!$listing->canChangeScrapedListing()) {throw new LogicHttpException();}$listing->setUser($user);$em->persist($listing);$em->flush($listing);return new JsonResponse();}#[Route(path: '/listing/{id}/pump_up', requirements: ['id' => '\d+'], name: 'confirm_listing_pump_up', methods: ['POST'])]#[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]public function confirmPumpUpListing(Listing $listing, Request $request): RedirectResponse{$pumpUpForm = $this->confirmFeaturedPaymentForm($listing);$pumpUpForm->handleRequest($request);if ($request->isMethod('POST') && $pumpUpForm->isValid()) {if (!$pumpUpForm->get('confirm')->isClicked()) {return $this->redirectToRoute('aqarmap_listing_default_mylistings', [], Response::HTTP_FOUND);}try {$this->listingManager->pumpUp($listing);$this->addFlash('success',$this->translator->trans('credit.pump_up_success', [':listing_title:' => $listing->getTitle()]));} catch (\Exception $e) {$this->addFlash('danger', $e->getMessage());}}return $this->redirectToRoute('aqarmap_listing_default_mylistings');}/*** @return array|RedirectResponse*/#[Route(path: '/listing/{id}/pump_up', requirements: ['id' => '\d+'], name: 'listing_pump_up', methods: ['GET'])]#[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]public function pumpUpListing(Listing $listing){$listingRules = $this->listingManager->getListingRules($listing);$listingOwner = $listing->getUser();$pumpUpFees = $listingRules['pump_up_fees'];$pumpUpOccurrence = $listingRules['pump_up_occurrence'];$pumpUpDuration = $listingRules['pump_up_duration'];if (!$this->listingManager->isPumpUpAvailable($listingRules)) {$this->addFlash('danger',$this->translator->trans('credit.pump_up_not_available'));return $this->redirectToRoute('aqarmap_listing_default_mylistings');}if (!$this->listingManager->isAffordable($listingOwner, $pumpUpFees)) {$this->addFlash('danger',$this->translator->trans('credit.pump_up_can_not_use'));return $this->redirectToRoute('aqarmap_listing_default_mylistings');}/** @var EntityManager $em */$em = $this->managerRegistry->getManager();$em->getRepository(Credit::class);$pumpUpForm = $this->createForm(ConfirmFeaturedFormType::class, null, ['method' => 'POST','action' => $this->generateUrl('listing_pump_up',['id' => $listing->getId()]),'confirm_message' => $this->translator->trans('listing.pump_up.confirm'),'cancel_message' => $this->translator->trans('listing.pump_up.cancel'),]);return $this->render('@AqarmapListing/Listing/pumpUpListing.html.twig',['fees' => $pumpUpFees,'duration' => $pumpUpDuration,'occurrence' => $pumpUpOccurrence,'form' => $pumpUpForm,]);}/*** Listing Details Single Page App.*/#[Route(path: '/listingApp/{id}', requirements: ['id' => '\d+'], name: 'listing_details_app', methods: ['GET'])]public function listingDetailsApp(Listing $listing): Response{return $this->render('@AqarmapListing/Listing/listingDetailsApp.html.twig',['listingId' => $listing->getReferenceId(),]);}/*** Delete Listing Photos.** @throws \Doctrine\ORM\OptimisticLockException*/#[Route(path: '/photos/delete', name: 'listing_bulk_delete_photo', requirements: ['id' => '\d+'])]public function bulkDeletePhoto(Request $request, ListingPhotoRepository $listingPhotoRepository, ListingManager $listingManager): RedirectResponse{$photosIds = $request->get('photos');try {if ($photosIds) {$photos = $listingPhotoRepository->getPhotos($photosIds);$listingManager->bulkDeletePhotos($photos);} else {$this->addFlash('danger', 'No photos selected for deletion');}} catch (\Exception) {$this->addFlash('danger', 'Something went wrong');}return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));}/*** @throws \Exception*/#[Route(path: '/brochure/{file}/download', name: 'download_brochure')]public function downloadBrochure(File $file, DownloadHandler $downloadHandler): Response{$response = $downloadHandler->downloadObject($file, 'file');// force specific content type instead of using default "application/octet-stream".$response->headers->set('content-type', 'application/pdf');return $response;}/*** Update WhatsApp Phones.*/private function updateWhatsAppPhones(int $userId, array $phones = [], array $whatsApp = []): void{foreach ($phones as $index => $phone) {$whatsApp[$index] = isset($whatsApp[$index]) && 'true' === $whatsApp[$index];$this->phoneManager->updateWhatsApp($userId, (int) $phone, $whatsApp[$index], true);}}}