src/Aqarmap/Bundle/ListingBundle/Controller/Api/ListingController.php line 304
- <?php
- namespace Aqarmap\Bundle\ListingBundle\Controller\Api;
- use App\Exception\BadRequestHttpException;
- use App\Exception\LogicHttpException;
- use Aqarmap\Bundle\CreditBundle\Constant\CreditStatus;
- use Aqarmap\Bundle\CreditBundle\Contract\CreditManagerInterface;
- use Aqarmap\Bundle\CreditBundle\Entity\Credit;
- use Aqarmap\Bundle\FeatureToggleBundle\Service\FeatureToggleManager;
- use Aqarmap\Bundle\ListingBundle\Constant\CountryCodes;
- use Aqarmap\Bundle\ListingBundle\Constant\LeadTypes;
- use Aqarmap\Bundle\ListingBundle\Constant\ListingFeaturedTypes;
- use Aqarmap\Bundle\ListingBundle\Constant\ListingFeatures;
- use Aqarmap\Bundle\ListingBundle\Constant\ListingStatus;
- use Aqarmap\Bundle\ListingBundle\Constant\ListingSyncedFields;
- use Aqarmap\Bundle\ListingBundle\Constant\PhotoTypes;
- use Aqarmap\Bundle\ListingBundle\Contracts\PhoneManagerInterface;
- use Aqarmap\Bundle\ListingBundle\Entity\CallRequest;
- use Aqarmap\Bundle\ListingBundle\Entity\Listing;
- use Aqarmap\Bundle\ListingBundle\Entity\ListingNote;
- use Aqarmap\Bundle\ListingBundle\Entity\ListingPhone;
- use Aqarmap\Bundle\ListingBundle\Entity\ListingPhoto;
- use Aqarmap\Bundle\ListingBundle\Entity\Photo;
- use Aqarmap\Bundle\ListingBundle\Entity\PropertyType;
- use Aqarmap\Bundle\ListingBundle\Entity\Section;
- use Aqarmap\Bundle\ListingBundle\Event\LeadEvent;
- use Aqarmap\Bundle\ListingBundle\Event\ListingEvent;
- use Aqarmap\Bundle\ListingBundle\Event\ListingUpdatedEvent;
- use Aqarmap\Bundle\ListingBundle\Form\ContactSellerFormType;
- use Aqarmap\Bundle\ListingBundle\Form\ListingApiType;
- use Aqarmap\Bundle\ListingBundle\Form\ListingNoteType;
- use Aqarmap\Bundle\ListingBundle\Form\PhotoType;
- use Aqarmap\Bundle\ListingBundle\Form\QuickContactSellerType;
- use Aqarmap\Bundle\ListingBundle\Form\QuickCreateLeadFormType;
- use Aqarmap\Bundle\ListingBundle\Form\QuickLeadType;
- use Aqarmap\Bundle\ListingBundle\Model\LeadModel;
- use Aqarmap\Bundle\ListingBundle\Repository\ListingNoteRepository;
- use Aqarmap\Bundle\ListingBundle\Repository\ListingRepository;
- use Aqarmap\Bundle\ListingBundle\Service\CallRequestManager;
- use Aqarmap\Bundle\ListingBundle\Service\FavouriteService;
- use Aqarmap\Bundle\ListingBundle\Service\InteractionService;
- use Aqarmap\Bundle\ListingBundle\Service\LeadService;
- use Aqarmap\Bundle\ListingBundle\Service\ListingManager;
- use Aqarmap\Bundle\ListingBundle\Service\ListingNoteService;
- use Aqarmap\Bundle\ListingBundle\Service\ListingRateService;
- use Aqarmap\Bundle\ListingBundle\Service\ListingRuleMatcher;
- use Aqarmap\Bundle\ListingBundle\Service\LocationManager;
- use Aqarmap\Bundle\ListingBundle\Service\Mortgage\MortgageService;
- use Aqarmap\Bundle\ListingBundle\Service\NewsFeed\ListingNewsFeed;
- use Aqarmap\Bundle\ListingBundle\Twig\ListingExtension;
- use Aqarmap\Bundle\MainBundle\Controller\Api\BaseController;
- use Aqarmap\Bundle\MainBundle\Service\Setting;
- use Aqarmap\Bundle\MessageBundle\Service\Composer;
- use Aqarmap\Bundle\TopSellerBundle\Model\TopSeller;
- use Aqarmap\Bundle\TopSellerBundle\Service\TopSellerRetrievalService;
- use Aqarmap\Bundle\UserBundle\Entity\User;
- use Aqarmap\Bundle\UserBundle\Services\UserManager;
- use Doctrine\Common\Collections\Collection;
- use Doctrine\ORM\EntityManager;
- use Doctrine\ORM\EntityManagerInterface;
- use Doctrine\ORM\OptimisticLockException;
- use Doctrine\ORM\ORMException;
- 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 OpenApi\Attributes as OA;
- use Symfony\Bridge\Doctrine\Attribute\MapEntity;
- use Symfony\Component\EventDispatcher\EventDispatcherInterface;
- use Symfony\Component\ExpressionLanguage\Expression;
- use Symfony\Component\Form\Form;
- use Symfony\Component\HttpFoundation\File\UploadedFile;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpFoundation\Response;
- use Symfony\Component\HttpKernel\Attribute\Cache;
- use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
- use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
- use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
- use Symfony\Component\Security\Http\Attribute\IsGranted;
- use Symfony\Contracts\Translation\TranslatorInterface;
- /**
- * Class ListingController.
- */
- class ListingController extends BaseController
- {
- /**
- * @var TokenStorageInterface
- */
- protected $tokenStorage;
- /** @var FOSUserManager */
- private $fosUserManager;
- public function __construct(
- private readonly Composer $messageComposer,
- private readonly FavouriteService $favouriteService,
- private readonly PaginatorInterface $paginator,
- private readonly InteractionService $interactionService,
- private readonly ListingManager $listingManager,
- private readonly EventDispatcherInterface $dispatcher,
- UserManagerInterface $fosUserManager,
- private readonly TranslatorInterface $translator,
- private readonly TranslatableListener $translatableListener,
- private readonly UserManager $userManager,
- private readonly ListingManager $listingService,
- private readonly ListingNoteService $listingNoteService,
- private readonly ListingRuleMatcher $listingRuleMatcher,
- private readonly LocationManager $locationManager,
- Setting $setting,
- private readonly PhoneManagerInterface $phoneManager,
- private readonly FeatureToggleManager $featureToggle,
- private readonly ListingRateService $listingRateService,
- TokenStorageInterface $tokenStorage,
- private readonly LeadService $leadManager,
- private readonly CallRequestManager $callRequestManager,
- private readonly MortgageService $mortgageService,
- private readonly CreditManagerInterface $creditManager,
- private readonly ListingExtension $listingExtension,
- private readonly ListingNewsFeed $listingNewsFeed,
- private readonly EntityManagerInterface $entityManager,
- private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
- ) {
- $this->fosUserManager = $fosUserManager;
- $this->tokenStorage = $tokenStorage;
- }
- /**
- * Get Listing.
- *
- * )
- */
- #[Rest\Get('/api/v2/listing/{id}', requirements: ['id' => '\d+'], options: ['i18n' => false], name: 'aqarmap_api_get_listing_v2')]
- #[Rest\View(serializerGroups: ['Default', 'Details', 'Compound'])]
- #[Cache(expires: '+2 hours', maxage: '+2 hours', smaxage: '+2 hours', public: false, vary: ['Accept-Language', 'X-Accept-Version', 'Accept'])]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function getListing(Listing $listing): array
- {
- return ['listing' => $listing];
- }
- /**
- * Listing details.
- */
- #[Rest\Get('/api/v4/listing/{id}', requirements: ['id' => '\d+'], options: ['i18n' => false], name: 'aqarmap_api_get_listing_v4')]
- #[Rest\View(serializerGroups: ['listingDetails', 'listingDetailsWithLocationCompound'])]
- #[Cache(expires: '+6 hours', maxage: '+6 hours', smaxage: '+6 hours', public: true, vary: ['Accept-Language', 'X-Accept-Version', 'Accept'])]
- public function getListingDetails(int $id, ListingRepository $listingRepository, ListingManager $listingManager): array
- {
- $entityManagerFilters = $this->entityManager->getFilters();
- if ($entityManagerFilters->isEnabled('softdeleteable')) {
- $entityManagerFilters->disable('softdeleteable');
- }
- $listing = $listingRepository->find($id);
- $entityManagerFilters->enable('softdeleteable');
- return ['listing' => $listingManager->serializeListing($listing)];
- }
- /**
- * Get Listing Children (Project Units).
- *
- * )
- *
- * @return array
- */
- #[Rest\Get('/api/v2/listing/{id}/children', options: ['i18n' => false], name: 'aqarmap_api_get_listing_children_v2')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function getListingChildren(Listing $listing)
- {
- return $this->respond($listing->getLiveChildren());
- }
- /**
- * @return Collection
- *
- * @throws ORMException
- * @throws OptimisticLockException
- */
- #[Rest\Post('/api/v2/listing/{listing}/phones', options: ['i18n' => false], name: 'aqarmap_api_get_listing_phones_v2')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[OA\Parameter(name: 'lead', in: 'query', description: '', required: false)]
- public function getListingPhone(Listing $listing, Request $request, ?User $user = null)
- {
- $version = (float) ltrim((string) $request->headers->get('X-Accept-Version'), 'v');
- $leadModel = new LeadModel();
- $currentUrl = $request->getUri();
- if (str_contains($currentUrl, 'v2')) {
- if (!$user = $this->getUser() && $version <= 2.13) {
- throw new AccessDeniedHttpException();
- }
- }
- $form = $this->createForm(QuickLeadType::class, null, [
- 'method' => 'POST',
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- $lead = $form->getData();
- $phoneManager = $this->phoneManager;
- $originalPhoneNumber = $lead['phone'];
- $phoneNumber = $phoneManager->trimZero($lead['phone'], $lead['countryCode']);
- $aqarmapUserService = $this->userManager;
- $hasEmail = !$lead['isAutoGeneratedEmail'];
- /** @var UserManagerInterface $userManager */
- $userManager = $this->fosUserManager;
- /** @var User $user */
- $user = $userManager->findUserByEmail($lead['email']);
- $countryCode = $lead['countryCode'];
- if (!$user && !$hasEmail) {
- $user = $aqarmapUserService->findLatestByPhone($phoneNumber, $countryCode);
- }
- if (!$user && $hasEmail) {
- $user = $aqarmapUserService->findAndReplaceUserAndEmail($phoneNumber, $lead['email'], $countryCode);
- }
- if (!$user) {
- $user = $userManager->createUser();
- $user
- ->setFullName($lead['name'])
- ->setPhoneNumber($lead['phone'])
- ->setTempOriginalPhoneNumber($originalPhoneNumber)
- ->setTempCountryCode($lead['countryCode'])
- ->setEmail($lead['email'])
- ->setHasEmail($hasEmail)
- ->setLanguage('ar');
- $user = $aqarmapUserService->quickRegistration($form, $user, $request);
- }
- $phone = $phoneManager->addNewUserPhone($phoneNumber, $lead['countryCode'], $user, true, false, null, $originalPhoneNumber);
- $userManager->updateUser($user);
- $userManager->reloadUser($user);
- $leadModel->setPhone($phone->getPhone());
- $leadModel->setName($request->request->get('name', $lead['name']));
- $leadModel->setEmail($request->request->get('email', $lead['email']));
- $leadService = $this->leadManager;
- $leadModel->setLeadType(LeadTypes::SHOW_PHONE);
- $leadModel->setListing($listing);
- $leadModel->setSource('api');
- $leadModel->setUser($user);
- $lead = $leadService->addLead($leadModel);
- if ($lead) {
- $this->dispatcher->dispatch(
- new LeadEvent(
- $listing,
- $user,
- $lead
- ),
- 'aqarmap.listing.show_seller_number'
- );
- }
- return $listing->getPhones();
- }
- /**
- * @return bool|Form
- *
- * @throws AccessDeniedHttpException
- */
- #[Rest\Post('/api/v2/listing/{listing}/contact_seller', options: ['i18n' => false], name: 'aqarmap_api_listing_contact_seller_v2')]
- #[Rest\QueryParam(name: 'campaign', description: 'Campaign Name')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[OA\Parameter(name: 'campaign', in: 'query', description: 'Campaign Name', required: false)]
- #[OA\Parameter(name: 'contact_seller', in: 'query', description: '', required: false)]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function contactSeller(Request $request, Listing $listing, ?User $user = null)
- {
- $currentUrl = $request->getUri();
- if (str_contains($currentUrl, 'v2')) {
- if (!$user = $this->getUser()) {
- throw new AccessDeniedHttpException();
- }
- }
- $form = $this->createForm(ContactSellerFormType::class, null, [
- 'method' => 'POST',
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- if ($form->isSubmitted() && $form->isValid()) {
- // Get campaign name
- $campaign = $request->query->get('campaign');
- $message = $form->getData();
- // Send contact seller message and send a lead
- $composer = $this->messageComposer;
- $composer
- ->setSender($user)
- ->compose($message['message'], $listing, $campaign);
- return true;
- }
- return $form;
- }
- /**
- * @return Response $response
- *
- * @throws \Exception
- */
- #[Rest\Post('/api/v2/listing/{listing}/contact_seller/quick', options: ['i18n' => false], name: 'aqarmap_api_listing_quick_contact_seller_v2')]
- #[Rest\QueryParam(name: 'campaign', description: 'Campaign Name')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[OA\Parameter(name: 'campaign', in: 'query', description: 'Campaign Name', required: false)]
- #[OA\Parameter(name: 'contact_seller', in: 'query', description: '', required: false)]
- #[OA\Response(response: 201, description: 'Returned when user created and message sent successfully')]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- #[OA\Response(response: 403, description: 'Returned when parameter is missing')]
- public function contactSellerWithQuickRegistration(Request $request, Listing $listing): Response
- {
- if (!$this->isValidQuickContactSellerParameters($request->get('contact_seller'))) {
- return new Response(null, Response::HTTP_FORBIDDEN);
- }
- $form = $this->createForm(QuickContactSellerType::class, null, [
- 'method' => 'POST',
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- if ($form->isSubmitted() && !$form->isValid()) {
- return new Response(null, Response::HTTP_FORBIDDEN);
- }
- $userManager = $this->userManager;
- $fromData = $form->getData();
- $user = $userManager->createQuickUser($request, $form);
- $campaign = $request->query->get('campaign');
- $composer = $this->messageComposer;
- $composer
- ->setSender($user)
- ->compose($fromData['message'], $listing, $campaign);
- return new Response(null, Response::HTTP_CREATED);
- }
- private function isValidQuickContactSellerParameters(array $parameters): bool
- {
- if (
- !\array_key_exists('email', $parameters)
- || !\array_key_exists('phone', $parameters)
- || !\array_key_exists('countryCode', $parameters)
- ) {
- return false;
- }
- return true;
- }
- /**
- * @return bool|array
- */
- #[Rest\Post('/api/v2/listing/{listing}/call_request', options: ['i18n' => false], name: 'aqarmap_api_listing_call_request_v2')]
- #[Rest\QueryParam(name: 'campaign', description: 'Campaign Name')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- public function callRequest(Listing $listing, Request $request, ?User $user = null)
- {
- $version = (float) ltrim((string) $request->headers->get('X-Accept-Version'), 'v');
- $callRequest = new CallRequest();
- $currentUrl = $request->getUri();
- if (str_contains($currentUrl, 'v2')) {
- if (!$user = $this->getUser() && $version <= 2.13) {
- throw new AccessDeniedHttpException();
- }
- }
- $form = $this->createForm(QuickLeadType::class, null, [
- 'method' => 'POST',
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- $lead = $form->getData();
- /** @var UserManagerInterface $userManager */
- $userManager = $this->fosUserManager;
- $aqarmapUserManager = $this->userManager;
- $hasEmail = !$lead['isAutoGeneratedEmail'];
- $phoneManager = $this->phoneManager;
- $originalPhoneNumber = $lead['phone'];
- $countryCode = $lead['countryCode'];
- $phoneNumber = $phoneManager->trimZero($lead['phone'], $countryCode);
- /** @var User $user */
- $user = $userManager->findUserByEmail($lead['email']);
- if (!$user && !$hasEmail) {
- $user = $aqarmapUserManager->findLatestByPhone($phoneNumber, $countryCode);
- }
- if (!$user && $hasEmail) {
- $user = $aqarmapUserManager->findAndReplaceUserAndEmail($phoneNumber, $lead['email'], $countryCode);
- }
- if (!$user) {
- $user = $userManager->createUser();
- $user
- ->setFullName($lead['name'])
- ->setPhoneNumber($lead['phone'])
- ->setTempOriginalPhoneNumber($originalPhoneNumber)
- ->setTempCountryCode($lead['countryCode'])
- ->setEmail($lead['email'])
- ->setHasEmail($hasEmail)
- ->setLanguage('ar');
- $user = $aqarmapUserManager->quickRegistration($form, $user, $request);
- }
- $phone = $phoneManager->addNewUserPhone($phoneNumber, $lead['countryCode'], $user, true, false, null, $originalPhoneNumber);
- $userManager->updateUser($user);
- $userManager->reloadUser($user);
- $callRequest->setPhone($phone->getPhone());
- $callRequest->setLeadFullName($request->request->get('name'));
- $callRequest->setLeadEmail($request->request->get('email'));
- $campaign = $request->request->get('campaign');
- $callRequest->setUser($user);
- $callRequest->setListing($listing);
- $this->callRequestManager->submitCallRequest($callRequest, $campaign);
- return true;
- }
- /**
- * Add New User Listing.
- *
- * @return View|Form
- */
- #[Rest\Post('/api/v2/listing', options: ['i18n' => false], name: 'aqarmap_api_add_listing')]
- #[IsGranted(attribute: 'ROLE_USER')]
- #[OA\Parameter(name: 'listing', in: 'query', description: '', required: false)]
- #[OA\Response(response: 201, description: 'Returned when successfully created')]
- #[OA\Response(response: 400, description: 'Returned when validation error')]
- public function addListing(Request $request)
- {
- $form = $this->createForm(ListingApiType::class, $listing = new Listing(), [
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- if ($form->isSubmitted() && $form->isValid()) {
- if ($this->getUser()->getPhoneNumber()) {
- $listing->addPhone(new ListingPhone($this->getUser()->getPhoneNumber()));
- }
- $listingManager = $this->listingService;
- $listing->setUser($this->getUser());
- $listing->setStatus(ListingStatus::DRAFT);
- $listingManager->saveListing($listing);
- $listingEvent = new ListingEvent($listing);
- $this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');
- return View::create()->setData($listing)->setStatusCode(Response::HTTP_CREATED);
- }
- return View::create()->setData($form)->setStatusCode(Response::HTTP_BAD_REQUEST);
- }
- /**
- * Create Single Listing Note.
- */
- #[Rest\Post('/api/v2/listing/{id}/note', options: ['i18n' => false])]
- #[Rest\RequestParam(name: 'body', description: 'Note Body')]
- #[Rest\RequestParam(name: 'source', description: 'Supported sources: 1 = Website, 2 = Consumer App, 3 = Live App')]
- #[Rest\RequestParam(name: 'last_modified_at', description: 'dateTime')]
- #[Rest\RequestParam(name: 'created_at', description: 'dateTime')]
- #[IsGranted(attribute: 'ROLE_USER')]
- public function postListingSingleNote(
- Request $request,
- #[MapEntity(id: 'listing')]
- Listing $listing,
- ListingNoteRepository $listingNoteRepository,
- EntityManagerInterface $em,
- ) {
- $currentUser = $this->getUser();
- $listingNote = $listingNoteRepository->findOneBy([
- 'user' => $currentUser,
- 'listing' => $listing,
- ]);
- if (empty($listingNote)) {
- $listingNote = new ListingNote();
- $listingNote->setUser($currentUser);
- $listingNote->setListing($listing);
- $listingNote->setCreatedAt(new \DateTime());
- }
- $form = $this->createForm(ListingNoteType::class, $listingNote);
- $form->handleRequest($request);
- if ($form->isSubmitted() && $form->isValid()) {
- $em->persist($listingNote);
- $em->flush();
- return $this->json([
- 'message' => 'Successfully submitted',
- ], Response::HTTP_CREATED);
- }
- return $this->json([
- 'message' => 'Error occurred',
- ], Response::HTTP_BAD_REQUEST);
- }
- /**
- * Create Bulk Listing Note.
- *
- * @return array
- */
- #[Rest\Post('/api/listing/note', options: ['i18n' => false])]
- #[Rest\Post('/api/v2/listing/note', options: ['i18n' => false])]
- #[IsGranted(attribute: 'ROLE_USER')]
- public function postListingBulkNote(Request $request)
- {
- $listingNoteService = $this->listingNoteService;
- $listingNoteService->addBulk($request);
- return $this->respond('Note Added Successfully!');
- }
- /**
- * Update Listing.
- *
- * @return View|Form
- */
- #[Rest\Post('/api/v2/listing/{id}', options: ['i18n' => false], name: 'aqarmap_api_update_listing')]
- #[Rest\View]
- #[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]
- #[OA\Parameter(name: 'listing', in: 'query', description: '', required: false)]
- #[OA\Response(response: 200, description: 'Returned when successfully Updated')]
- #[OA\Response(response: 400, description: 'Returned when validation error')]
- public function updateListing(Listing $listing, Request $request)
- {
- $listing->clearAttributes();
- $form = $this->createForm(ListingApiType::class, $listing, [
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- if ($form->isSubmitted() && $form->isValid()) {
- if ($this->getUser()->getPhoneNumber()) {
- $listing->addPhone(new ListingPhone($this->getUser()->getPhoneNumber()));
- }
- $listingManager = $this->listingService;
- $listingManager->saveListing($listing);
- $listingEvent = new ListingEvent($listing);
- $this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');
- return View::create()->setData($listing)->setStatusCode(Response::HTTP_OK);
- }
- return View::create()->setData($form)->setStatusCode(Response::HTTP_BAD_REQUEST);
- }
- /**
- * Upload listing photos.
- *
- * @return View|array
- */
- #[Rest\Post('/api/v2/listing/{id}/photos', options: ['i18n' => false], name: 'aqarmap_api_upload_listing_photos')]
- #[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]
- #[OA\Parameter(name: 'photos', in: 'query', description: '', required: false)]
- #[OA\Response(response: 201, description: 'Returned when successfully created')]
- #[OA\Response(response: 400, description: 'Returned when validation error')]
- public function upload(Request $request, Listing $listing)
- {
- $form = $this->createForm(PhotoType::class, null, [
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- if ($form->isSubmitted() && $form->isValid()) {
- $outputFiles = [];
- $listingManager = $this->listingService;
- $maxOrder = $listingManager->getMaxListingPhotoOrder($listing);
- foreach ($form->get('file')->getData() as $index => $file) {
- $photo = new Photo();
- $photo->setFile($file);
- $listingPhoto = new ListingPhoto();
- $listingPhoto->setFile($photo);
- $listingPhoto->setCaption($photo->getFile()->getClientOriginalName());
- $listingPhoto->setOrder($maxOrder + $index + 1);
- $outputFiles[] = $listingPhoto;
- $listing->addPhoto($listingPhoto);
- }
- $listingEvent = new ListingEvent($listing);
- $this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');
- $listingManager->saveListing($listing);
- return View::create()->setData($outputFiles)->setStatusCode(Response::HTTP_CREATED);
- }
- return [
- 'listing' => $listing,
- 'form' => $form->createView(),
- ];
- }
- /**
- * Delete Listing entity.
- */
- #[Rest\Delete('/api/v2/listing/{listing}', options: ['i18n' => false], name: 'aqarmap_api_delete_listing')]
- #[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]
- #[OA\Response(response: 204, description: 'Returned when successfully Deleted')]
- #[OA\Response(response: 404, description: 'Returned when Listing is not found')]
- #[OA\Response(response: 403, description: 'Returned when you are trying to remove listing that not yours.')]
- public function delete(Listing $listing)
- {
- if (\in_array('ROLE_PREVENT_DELETE_LISTING', $this->getUser()->getRoles())) {
- throw new AccessDeniedHttpException("Forbidden, user don't have this permession.");
- }
- $listingManager = $this->listingService;
- $listingManager->remove($listing, ListingStatus::USER_DELETED);
- return new Response(null, Response::HTTP_NO_CONTENT);
- }
- /**
- * Undelete Listing entity.
- *
- * @return array
- */
- #[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]
- #[Rest\View]
- #[Rest\Get('/api/v2/listing/{listing}/undelete', name: 'aqarmap_api_undelete_listing', options: ['i18n' => false])]
- #[OA\Response(response: 200, description: 'Returned when successfully undeleted')]
- #[OA\Response(response: 404, description: 'Returned when Listing is not found or is not on user deleted state')]
- #[OA\Response(response: 403, description: 'Returned when you are trying to remove listing that not yours.')]
- public function undelete(Listing $listing)
- {
- if (ListingStatus::USER_DELETED != $listing->getStatus()) {
- throw $this->createNotFoundException('Unable to find this listing.');
- }
- $listingManager = $this->listingService;
- $listingManager->changeStatus($listing, ListingStatus::PENDING);
- $listingEvent = new ListingEvent($listing);
- $this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.resubmitted');
- return ['listing' => $listing];
- }
- /**
- * Republish Listing entity.
- *
- * @return array
- */
- #[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]
- #[Rest\View]
- #[OA\Response(response: 200, description: 'Returned when successfully Republished')]
- #[OA\Response(response: 404, description: 'Returned when Listing is not found or is not on Expired state')]
- #[OA\Response(response: 403, description: 'Returned when you are trying to Republish listing that not yours.')]
- #[Rest\Get('/api/v2/listing/{listing}/relist', name: 'aqarmap_api_republish_listing', options: ['i18n' => false])]
- public function relist(Listing $listing)
- {
- if (ListingStatus::EXPIRED != $listing->getStatus()) {
- throw $this->createNotFoundException('Unable to find this listing.');
- }
- $em = $this->managerRegistry->getManager();
- $listingRepo = $em->getRepository(Listing::class);
- $relistChild = $listingRepo->getRelistChild($listing);
- // If the expired listing already republished before .. return the republished version.
- if ($relistChild) {
- return ['listing' => $relistChild];
- }
- $listingManager = $this->listingService;
- $listing = $listingManager->relist($listing);
- $listingEvent = new ListingEvent($listing);
- $this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.resubmitted');
- return ['listing' => $listing];
- }
- /**
- * Feature A Listing.
- *
- * @return View
- */
- #[Rest\Post('/api/v2/listing/{listing}/feature', options: ['i18n' => false], name: 'aqarmap_api_feature_listing')]
- #[Rest\RequestParam(name: 'type', description: 'Feature Type, 1 for payment, 2 for making it featured')]
- #[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]
- public function feature(Listing $listing, Request $request)
- {
- $type = $request->get('type');
- if (!$type) {
- throw new BadRequestHttpException('Please Specify the feature type');
- }
- $matcher = $this->listingRuleMatcher;
- $listingRule = $matcher->match($listing);
- $translator = $this->translator;
- $featuredDuration = $listingRule['featured_duration'];
- $featuredFees = $listingRule['featured_fees'];
- if (ListingFeatures::FEATURED == $type) {
- // Check if there is a value for featured_duration & featured_fees
- if (empty($featuredDuration) || empty($featuredFees)) {
- throw new LogicHttpException($translator->trans('Making a listing Featured is not available for this listing.', [], 'exceptions'));
- }
- try {
- $this->listingService->makeItFeatured(
- $listing,
- [
- 'featuredFees' => $featuredFees,
- 'featuredDuration' => $featuredDuration,
- 'listingFeaturedType' => ListingFeaturedTypes::FEATURED,
- 'listingFeature' => $type,
- ]
- );
- } catch (\Exception $e) {
- throw new LogicHttpException($translator->trans($e->getMessage(), [], 'exceptions'));
- }
- } elseif (ListingFeatures::PAID == $type) {
- /** @var \Aqarmap\Bundle\CreditBundle\Services\CreditManager $creditManager */
- $creditManager = $this->creditManager;
- if ($listing->getPublicationCredit()) {
- throw new LogicHttpException($translator->trans('credit.already_paid'));
- } elseif ($listingRule['publication_fees'] > $creditManager->getBalance($listing->getUser())) {
- throw new LogicHttpException($translator->trans('credit.not_enough_credits'));
- }
- // Subtract publication fees
- $credits = $creditManager->deduction($listing->getUser(), $listingRule['publication_fees'], 'Listing Fees', CreditStatus::PENDING);
- foreach ($credits as $credit) {
- if ($credit instanceof Credit) {
- $this->listingService->addFeature($listing, ListingFeatures::PAID, null, $credit);
- }
- }
- $listingEvent = new ListingEvent($listing);
- $this->dispatcher->dispatch($listingEvent, 'aqarmap.listing.submitted');
- }
- return View::create()->setData(['listing' => $listing]);
- }
- // -------------------------------------------------------------------------//
- // ++++++++++++++ Quick contact seller & call request Actions +++++++++++++++//
- // -------------------------------------------------------------------------//
- /**
- * ).
- *
- * @return bool|Form|array
- *
- * @throws AccessDeniedHttpException
- *
- * ===============================================================
- * |
- * | DEPRECATED: USE QuickCreateLeadAction::LeadController instead
- * |
- * ===============================================================
- */
- #[Rest\Post('/api/v2/listing/{listing}/quick_create_lead', options: ['i18n' => false], name: 'aqarmap_api_listing_quick_create_lead')]
- #[Rest\QueryParam(name: 'campaign', description: 'Campaign Name')]
- #[Rest\QueryParam(name: 'country_code', default: null, description: 'Country Code')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function quickCreateLead(Request $request, Listing $listing)
- {
- $form = $this->createForm(QuickCreateLeadFormType::class, null, [
- 'method' => 'POST',
- 'csrf_protection' => false,
- ]);
- $form->handleRequest($request);
- if ($form->isSubmitted() && $form->isValid()) {
- $lead = $form->getData();
- /** @var UserManagerInterface $userManager */
- $userManager = $this->fosUserManager;
- $leadModel = new LeadModel();
- try {
- /** @var User $user */
- if ($user = $userManager->findUserByEmail($form->get('email')->getData())) {
- $phone = $this->phoneManager->addNewUserPhone(
- $lead['phoneNumber'],
- '+'.str_replace(' ', '', $request->get('country_code')),
- $user,
- true,
- true,
- CountryCodes::getCountryFromCodeNumber('+'.str_replace(' ', '', $request->get('country_code'))),
- $lead['phoneNumber']
- );
- $userManager->updateUser($user);
- $leadModel->setUser($user);
- } else {
- $user = $userManager->createUser();
- $user
- ->setFullName($lead['fullName'])
- ->setEmail($lead['email'])
- ->setLanguage($request->getLocale());
- $user = $this->userManager->quickRegistration($form, $user, $request);
- $phone = $this->phoneManager->addNewUserPhone(
- $lead['phoneNumber'],
- '+'.str_replace(' ', '', $request->get('country_code')),
- $user,
- true,
- true,
- CountryCodes::getCountryFromCodeNumber('+'.str_replace(' ', '', $request->get('country_code'))),
- $lead['phoneNumber']
- );
- $userManager->reloadUser($user);
- $leadModel->setUser($user);
- }
- } catch (\Exception) {
- return [
- 'status' => 'error',
- 'message' => 'Cannot create a user.',
- ];
- }
- if ($user) {
- try {
- $leadModel->setEmail($lead['email']);
- $leadModel->setName($lead['fullName']);
- $leadModel->setPhone($phone->getPhone());
- $leadModel->setCampaign($request->request->get('campaign'));
- $leadModel->setMessage($form->get('message')->getData());
- $leadModel->setListing($listing);
- $this->listingService->quickCreateLead($leadModel);
- return [
- 'status' => 'ok',
- ];
- } catch (\Exception) {
- return [
- 'status' => 'error',
- 'message' => 'Cannot create the lead.',
- ];
- }
- }
- }
- return $form;
- }
- /**
- * Get Listing Rules.
- *
- * )
- *
- * @return array
- */
- #[Rest\Get('/api/v2/listing/{id}/rules', options: ['i18n' => false], name: 'aqarmap_api_get_listing_rules')]
- #[IsGranted(attribute: 'ROLE_OWNER', subject: 'listing')]
- #[Rest\View]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function getListingRules(Listing $listing)
- {
- $listingMatcher = $this->listingRuleMatcher;
- $rules = $listingMatcher->match($listing);
- return ['rules' => $rules];
- }
- /**
- * Get Listing Note.
- *
- * @return array
- */
- #[Rest\Get('/api/v2/listing/{id}/note', options: ['i18n' => false], name: 'aqarmap_api_get_listing_note')]
- #[IsGranted(attribute: 'ROLE_USER')]
- #[Rest\View]
- #[OA\Parameter(name: 'propertyType', in: 'query', description: 'propertyType of the unites', required: false)]
- #[OA\Parameter(name: 'section', in: 'query', description: 'Section of the unites', required: false)]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function getListingNote(Listing $listing)
- {
- /** @var EntityManager $em */
- $em = $this->managerRegistry->getManager();
- $listingNoteRepo = $em->getRepository(ListingNote::class);
- return $listingNoteRepo->findOneBy([
- 'user' => $this->getUser(),
- 'listing' => $listing,
- ]);
- }
- /**
- * Get account statistics (Listings Statistics).
- *
- * @throws \Exception
- */
- #[Rest\Get('/api/user/listings/statistics', requirements: ['id' => '\d+'], options: ['expose' => true, 'i18n' => false], name: 'aqarmap_api_get_user_listings_rates_counts')]
- #[Rest\Post('/api/v2/user/listings/statistics', options: ['i18n' => false], name: 'aqarmap_api_get_user_listings_rates_counts_v2')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[IsGranted(attribute: 'ROLE_USER')]
- public function getUserListingsPerformanceStatistics(
- Request $request,
- #[MapEntity(id: 'user')]
- ?User $user = null,
- ): View {
- $isSubAccount = null != $user && $this->getUser() === $user->getParent();
- $startDate = null;
- $period = $request->query->get('period', null);
- if (!$this->getUser() && !$isSubAccount) {
- throw new AccessDeniedHttpException();
- }
- $user = $user ?: $this->getUser();
- if ('7Days' == $period) {
- $startDate = date('Y-m-d', strtotime('-7 days'));
- } elseif ('30Days' == $period) {
- $startDate = date('Y-m-d', strtotime('-30 days'));
- }
- return $this->respond([
- 'rates' => $this->listingService->getUserListingsPerformanceStatistics($user, $startDate, $period),
- ]);
- }
- /**
- * Generates XML file for Listings News feed for marketing purpose.
- *
- * @return Response
- */
- #[Rest\Get('/api/listings/feed/{platform}', options: ['i18n' => false], name: 'aqarmap_api_get_listings_news_feed', defaults: ['page' => 1])]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- public function getNewsFeed($platform, Request $request)
- {
- $criteria = [];
- $page = min($request->query->getInt('page') ?: 1, ListingNewsFeed::MAX_PAGES);
- $limit = min($request->query->getInt('limit', 100), 100);
- if ((int) $request->query->getInt('page', 1) > $page) {
- throw new NotFoundHttpException('Exceeded maximum number of pages');
- }
- if ($request->query->get('ugc')) {
- $data = explode(',', $request->query->get('ugc'));
- $data = array_map('intval', $data);
- $criteria['groupCategory'] = array_filter($data);
- }
- if ($request->query->get('ug')) {
- $data = explode(',', $request->query->get('ug'));
- $data = array_map('intval', $data);
- $criteria['userGroup'] = array_filter($data);
- }
- if ($request->query->get('hl')) {
- $criteria['locale'] = $request->query->get('hl');
- }
- if ($request->query->get('maxlead')) {
- $criteria['maxlead'] = $request->query->get('maxlead');
- }
- if ($request->query->get('feat')) {
- $criteria['feat'] = $request->query->get('feat');
- }
- if ($request->query->get('location')) {
- $locations = $this->locationManager
- ->buildLocationsArrayByParentId($request->query->get('location'));
- if (!empty($locations)) {
- $criteria['locations'] = $locations;
- }
- }
- if ($request->query->get('section')) {
- $data = explode(',', $request->query->get('section'));
- $data = array_map('intval', $data);
- $criteria['sections'] = array_filter($data);
- }
- $news = $this->listingNewsFeed;
- $offset = ($page - 1) * $limit;
- $excludedKeys = ['sections', 'maxlead'];
- if (!array_diff(array_keys($criteria), $excludedKeys)) {
- throw new BadRequestHttpException(sprintf('Invalid Request: Please add at least one additional filter besides %s.', implode(', ', $excludedKeys)));
- }
- if ('json' == $request->query->get('format')) {
- return $this->responseJson($news->asJson($offset, $limit, $criteria));
- }
- return $this->responseXml($news->asXml($offset, $limit, $platform, $criteria));
- }
- /**
- * Stateful endpoint to update listing fields.
- */
- #[Rest\Post('api/listing/{id}/edit', name: 'update_listing_field', options: ['i18n' => false, 'expose' => true])]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[IsGranted(attribute: 'ROLE_EDIT_REVIEW_LISTINGS')]
- #[IsGranted(attribute: new Expression('is_granted("ROLE_ADMIN") or is_granted("ROLE_OWNER", subject["listing"])'), subject: ['listing'])]
- public function update(Listing $listing, Request $request): View
- {
- $listingManager = $this->listingManager;
- $isEnabled = $this->featureToggle
- ->isEnabled('web.mortgage.options');
- $mortgage = $request->get('eligibleForMortgage');
- $fields = $request->request->all();
- if ($isEnabled) {
- if (true == $mortgage) {
- $this->mortgageService->addEligibleMortgageTypes($listing);
- } else {
- $listingManager->setEligibleMortgageToNull($listing);
- }
- unset($fields['eligibleForMortgage']);
- }
- $this->dispatcher->dispatch(
- new ListingUpdatedEvent($listing, $fields),
- ListingUpdatedEvent::UPDATED
- );
- $listing = $listingManager->update($listing, $fields);
- if (ListingStatus::LIVE == $listing->getStatus()) {
- $listingManager->changeStatus($listing, ListingStatus::PENDING);
- }
- return $this->respond([
- 'listing' => $listing,
- 'msg' => 'Listing was updated successfully',
- ]);
- }
- /**
- * Stateful endpoint to get Photos Of The Given Listings.
- */
- #[Rest\Get('/api/listings/{listing}/photos', name: 'aqarmap_api_get_listing_photos', options: ['expose' => true, 'i18n' => false])]
- #[IsGranted(attribute: new Expression('is_granted("ROLE_ADMIN") or is_granted("ROLE_OWNER", subject["listing"])'), subject: ['listing'])]
- public function getListingPhotos(Listing $listing): View
- {
- $listingPhotos = $listing->getPhotos();
- $listingPhotosData = [];
- foreach ($listingPhotos as $listingPhoto) {
- $listingPhotosData[] = [
- 'id' => $listingPhoto->getId(),
- 'type' => $listingPhoto->getType(),
- 'caption' => $listingPhoto->getCaption(),
- 'file' => $listingPhoto->getFile(),
- ];
- }
- return $this->respond($listingPhotosData);
- }
- /**
- * Get Photo Types.
- *
- * @return Response
- */
- #[Rest\Get('/api/listings/photoTypes', name: 'aqarmap_api_get_listing_photo_types', options: ['expose' => true, 'i18n' => false])]
- public function getPhotoTypes()
- {
- return $this->respond(PhotoTypes::getPhotoTypes());
- }
- /**
- * Upload Listing Photo.
- *
- * @return array
- *
- * @throws OptimisticLockException
- */
- #[Rest\Post('/api/listing/{id}/upload_photo', name: 'aqarmap_api_admin_upload_listing_photo', options: ['expose' => true, 'i18n' => false])]
- public function uploadListingPhoto(Listing $listing)
- {
- $outputFiles = [];
- $listingManager = $this->listingManager;
- $maxOrder = $listingManager->getMaxListingPhotoOrder($listing);
- $photo = new Photo();
- $file = $_FILES['file'];
- $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type']);
- $photo->setFile($file);
- $listingPhoto = new ListingPhoto();
- $listingPhoto->setFile($photo);
- $listingPhoto->setCaption($photo->getFile()->getClientOriginalName());
- $listingPhoto->setOrder($maxOrder + 1);
- $outputFiles[] = $listingPhoto;
- $listing->addPhoto($listingPhoto);
- $em = $this->managerRegistry->getManager();
- $em->persist($listing);
- $em->flush();
- return $this->respond(['status' => 'OK']);
- }
- /**
- * Gets rate details of listing.
- */
- #[Rest\Get('/api/v2/listing/{listing}/rates', options: ['i18n' => false])]
- #[Rest\Get('/api/listing/{listing}/rates', options: ['expose' => true, 'i18n' => false], name: 'aqarmap_api_listing_rates_details')]
- #[Rest\View(serializerGroups: ['Rates'])]
- #[Cache(expires: '+1 week', maxage: '+1 week', smaxage: '+1 week', public: false, vary: ['Accept-Language', 'X-Accept-Version', 'Accept'])]
- public function getRateDetails(Listing $listing)
- {
- return $this->respond(
- current($this->listingRateService->getRatesDetails([$listing]))
- );
- }
- /**
- * @return View
- */
- #[Rest\Get('/api/v2/listing/{listing}/preview', options: ['i18n' => false])]
- #[Rest\Get('/api/listing/{listing}/preview', options: ['expose' => true, 'i18n' => false], name: 'aqarmap_api_listing_preview_data')]
- #[Rest\View(serializerGroups: ['Preview'])]
- public function getListingPreviewData(Listing $listing)
- {
- return $this->respond($listing);
- }
- /**
- * @return JsonResponse
- *
- * @throws \Exception
- */
- #[Rest\Get('/api/listing/{listing}/lead-analytics', options: ['i18n' => false, 'expose' => true], name: 'aqarmap_api_listing_lead_analytics')]
- public function getLeadAnalytics(Listing $listing)
- {
- $analytics = $this->listingService->getLeadAnalytics($listing);
- return $this->respond($analytics);
- }
- /**
- * @return string
- */
- #[Rest\Delete('/api/v2/listing/{listing}/favourite', options: ['i18n' => false])]
- #[Rest\Delete('/api/listing/{listing}/favourite', options: ['i18n' => false], name: 'aqarmap_api_remove_favourite_listing')]
- #[IsGranted(attribute: 'ROLE_USER')]
- public function deleteFavourite(Request $request)
- {
- $this->favouriteService->deleteByListing($request->attributes->get('listing'));
- return $this->respond('Favourite Deleted Successfully!');
- }
- /**
- * @return string
- */
- #[Rest\Delete('/api/v2/listing/{listing}/note', options: ['i18n' => false])]
- #[Rest\Delete('/api/listing/{listing}/note', options: ['i18n' => false], name: 'aqarmap_api_remove_listing_note')]
- #[IsGranted(attribute: 'ROLE_USER')]
- public function deleteNote(Request $request)
- {
- $this->listingNoteService->deleteByListing($request->attributes->get('listing'));
- return $this->respond('Note Deleted Successfully!');
- }
- #[Rest\Post('/api/listing/{listing}/rate-review', options: ['i18n' => false, 'expose' => true], name: 'aqarmap_api_change_listing_rate_review_status')]
- #[IsGranted(attribute: 'ROLE_ADMIN')]
- public function rateReview(Request $request, Listing $listing): View
- {
- $this->listingService->updateIsRateReviewed($listing, $request->request->get('isReviewed'));
- return $this->respond('Listing rate review status changed successfully');
- }
- #[Rest\Get('/api/listing/{id}/similar_listings_count', options: ['i18n' => false, 'expose' => true], name: 'aqarmap_api_get_similar_listings_count')]
- #[Rest\View(serializerGroups: ['Default', 'Details'])]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function getSimilarListingsCount(Listing $listing): int
- {
- $listingManager = $this->listingService;
- try {
- $count = $listingManager->countSimilarListings($listing);
- } catch (\Exception $exception) {
- echo $exception->getMessage();
- $this->errorLogger->error(shell_exec("Error retriving similar listings count! {$exception->getMessage()}"));
- $count = 0;
- }
- return $count;
- }
- #[Rest\Get('/api/v2/listings/notes', options: ['i18n' => false])]
- #[Rest\Get('/api/listings/notes', name: 'aqarmap_api_listing_notes_and_favourites', options: ['i18n' => false])]
- #[Rest\QueryParam(name: 'from', description: '[favourites|notes]')]
- #[Rest\View(serializerGroups: ['Default', 'List'])]
- public function getListingsWithNotes(Request $request): array
- {
- $listingsIdWithNotes = [];
- if ($content = $request->getContent()) {
- $listingsIdWithNotes = json_decode($content, true);
- }
- $listings = $this->managerRegistry->getRepository(Listing::class)
- ->getByIdsQuery(array_column($listingsIdWithNotes, 'listingId'));
- $pagination = $this->paginator->paginate(
- $listings,
- $request->query->getInt('page', 1),
- $request->query->getInt('limit', 10)
- );
- $data = $this->listingService->setStaticNotesFromPaginator($pagination, $listingsIdWithNotes);
- if ('favourites' == $request->query->get('from')) {
- return ['favourite' => $data];
- }
- return ['note' => $data];
- }
- /**
- * ApiDoc(
- * resource = true,
- * section = "Listing",
- * description="Get ApprovalRejectionWaitingTime",
- * statusCodes={
- * 200="Returned when successful",
- * }
- * ).
- *
- * @return array
- *
- * @throws \Exception
- */
- #[Rest\Get('/api/listing/arwt', options: ['i18n' => false], name: 'aqarmap_api_listing_arwt')]
- #[Rest\View]
- public function getApprovalRejectionWaitingTime(Request $request)
- {
- $criteria = array_merge(
- $request->query->all(),
- ['actionTime' => true]
- );
- $listingManager = $this->listingService;
- $listingExtension = $this->listingExtension;
- return [
- 'arwt' => $listingExtension->waited($listingManager->getApprovalRejectionWaitingTime($criteria)),
- ];
- }
- /**
- * filter Listing Children with property type (Project Units).
- *
- * @return array
- */
- #[Rest\Get('/api/listing/{id}/children', name: 'aqarmap_api_get_listing_children', options: ['i18n' => false])]
- #[Rest\QueryParam(name: 'propertyType', description: 'propertyType of the unites')]
- #[Rest\View(serializerGroups: ['UnitDetails'])]
- #[OA\Parameter(name: 'propertyType', description: 'propertyType of the unites', in: 'query', required: false)]
- #[OA\Response(response: 404, description: 'Returned when the listing is not found')]
- public function filterListingChildren(
- Listing $listing,
- #[MapEntity(id: 'propertyType')]
- ?PropertyType $propertyType = null,
- ): View {
- if (!$this->getUser()) {
- throw new AccessDeniedHttpException();
- }
- return $this->respond($listing->getLiveChildren($propertyType));
- }
- /**
- * API for cloning listing.
- */
- #[Rest\Post('/api/listing/{id}/clone', name: 'aqarmap_api_clone_listing_children', options: ['i18n' => false])]
- #[Rest\Post('/api/v2/listing/{id}/clone', name: 'aqarmap_api_v2_clone_listing_children', options: ['i18n' => false])]
- #[Rest\RequestParam(name: 'propertyType', description: 'propertyType of the unites')]
- #[Rest\RequestParam(name: 'section', description: 'Section of the unites')]
- #[IsGranted(attribute: 'IS_AUTHENTICATED_REMEMBERED')]
- #[Rest\View(serializerGroups: ['UnitDetails'])]
- #[OA\Parameter(name: 'propertyType', description: 'propertyType of the unites', in: 'query', required: false)]
- #[OA\Parameter(name: 'section', description: 'Section of the unites', in: 'query', required: false)]
- #[OA\Response(response: 404, description: 'Returned when the listing, propertyType or section is not found')]
- public function cloneListing(
- #[MapEntity(expr: 'repository.find(request.get("section"))', stripNull: false)]
- ?Section $section,
- #[MapEntity(expr: 'repository.find(request.get("propertyType"))', stripNull: false)]
- ?PropertyType $propertyType,
- Listing $sourceListing
- ): View {
- $syncedFields = $sourceListing->getParent() ? ListingSyncedFields::UNIT_FIELDS : ListingSyncedFields::PARENT_FIELDS;
- try {
- $listing = $this->listingManager->initializeListingForCloning($sourceListing, $propertyType, $section, $this->getUser());
- $this->listingManager->syncListingForProject(
- [
- 'targetListingId' => $listing->getId(),
- 'sourceListingId' => $sourceListing->getId(),
- 'syncedFields' => $syncedFields,
- 'targetListingSavedAt' => $listing->getUpdatedAt()->getTimestamp(),
- ]
- );
- return $this->respond($listing->getId());
- } catch (\Exception $exception) {
- throw new \Exception('Could not clone listing', null, $exception);
- }
- }
- #[Rest\Get('/api/v2/listing/{listing}/top-seller', options: ['i18n' => false], name: 'aqarmap_api_listing_top_seller')]
- #[Rest\View(serializerGroups: ['TopCustomers'])]
- public function getListingTopSeller(Listing $listing, TopSellerRetrievalService $topSellerRetrievalService)
- {
- $topSeller = new TopSeller();
- $topSeller->setLocation($listing->getLocation()->getId());
- $topSeller->setSection($listing->getSection()->getId());
- $topSeller->setPropertyType($listing->getPropertyType()->getId());
- return $topSellerRetrievalService->getTopSellerPersonalData($topSeller);
- }
- #[Rest\Get('/api/v2/listing/{listing}/related-listings', name: 'aqarmap_api_listing_related_listings', options: ['i18n' => false])]
- #[Cache(expires: '+1 days', maxage: '+1 days', smaxage: '+1 days', public: true, vary: ['Accept-Language', 'X-Accept-Version', 'Accept'])]
- #[Rest\View(serializerGroups: ['RelatedListingsV2'])]
- public function getRelatedListing(Listing $listing, ListingManager $listingManager, ListingRepository $listingRepository)
- {
- try {
- $relatedListingsElasticResponse = $listingManager->getRelatedListingsElasticResponse($listing);
- $listingsQueryBuilder = $listingRepository->getListingsByIds(array_column($relatedListingsElasticResponse['items'], 'id'));
- return $listingsQueryBuilder->getQuery()->getResult();
- } catch (\Exception $exception) {
- throw new \Exception('Could not get related listings', null, $exception);
- }
- }
- #[Rest\Post('/api/v2/listing/{id}/views', name: 'aqarmap_api_add_listing_views', requirements: ['id' => '\d+'], options: ['i18n' => false])]
- #[Rest\View]
- public function increaseListingViews(Listing $listing): array
- {
- try {
- $this->interactionService->increaseViews($listing, $this->getUser());
- return [
- 'status' => 'ok',
- 'message' => 'Views Created Successfully!',
- ];
- } catch (\Exception $exception) {
- throw new \Exception('Could not increase listing views', null, $exception);
- }
- }
- }