src/Aqarmap/Bundle/ListingBundle/Entity/Location.php line 50

  1. <?php
  2. namespace Aqarmap\Bundle\ListingBundle\Entity;
  3. use App\Entity\Location\LocationTier;
  4. use Aqarmap\Bundle\DiscussionBundle\Entity\Discussion;
  5. use Aqarmap\Bundle\ExchangeBundle\Entity\ExchangeRequest;
  6. use Aqarmap\Bundle\ListingBundle\Constant\LocationTypes;
  7. use Aqarmap\Bundle\ListingBundle\Constant\PhotoTypes;
  8. use Aqarmap\Bundle\ListingBundle\Repository\LocationRepository;
  9. use Aqarmap\Bundle\NeighborhoodBundle\Entity\LocationCompound;
  10. use Aqarmap\Bundle\NeighborhoodBundle\Entity\LocationStatistics;
  11. use Aqarmap\Bundle\NotifierBundle\Entity\Notifier;
  12. use Aqarmap\Bundle\UserBundle\Constant\UserInterestStatus;
  13. use Aqarmap\Bundle\UserBundle\Entity\UserInterest;
  14. use Doctrine\Common\Collections\ArrayCollection;
  15. use Doctrine\Common\Collections\Collection;
  16. use Doctrine\Common\Collections\Criteria;
  17. use Doctrine\ORM\Mapping as ORM;
  18. use Gedmo\Mapping\Annotation as Gedmo;
  19. use Gedmo\Sluggable\Handler\TreeSlugHandler;
  20. use Gedmo\Translatable\Translatable;
  21. use JMS\Serializer\Annotation as Serializer;
  22. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  23. use Symfony\Component\Serializer\Annotation\Groups;
  24. /**
  25. * Location.
  26. */
  27. #[UniqueEntity('slug')]
  28. #[ORM\Table(name: 'locations')]
  29. #[ORM\Index(columns: ['disabled'])]
  30. #[ORM\Index(columns: ['listings_counter'])]
  31. #[ORM\Index(columns: ['searchable'])]
  32. #[ORM\Index(columns: ['lat'])]
  33. #[ORM\Index(columns: ['lon'])]
  34. #[ORM\Index(columns: ['root'])]
  35. #[ORM\Index(columns: ['root', '_left', '_right'])]
  36. #[ORM\Index(columns: ['home_filter', 'is_compound_location', 'listing_id'])]
  37. #[ORM\Entity(repositoryClass: LocationRepository::class)]
  38. #[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'write_rare')]
  39. #[Gedmo\TranslationEntity(class: LocationTranslation::class)]
  40. #[Gedmo\Tree(type: 'nested')]
  41. #[Serializer\ExclusionPolicy('all')]
  42. class Location implements Translatable, \Stringable
  43. {
  44. /**
  45. * @var int
  46. */
  47. #[ORM\Column(name: 'id', type: 'integer')]
  48. #[ORM\Id]
  49. #[ORM\GeneratedValue(strategy: 'AUTO')]
  50. #[Serializer\Groups(['Default', 'listingDetails', 'List', 'MiniList', 'Data', 'Autocomplete', 'Details', 'Neighborhood', 'NeighborhoodStatistics', 'Discussion', 'Exchange', 'LocationFlat', 'Search', 'AutocompleteV3', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'Translation', 'SlugResolver', 'RelatedListingsV2', 'locationListingV2', 'leadsBank', 'UserFavoriteListings'])]
  51. #[Groups(['valuation:read'])]
  52. #[Serializer\Expose]
  53. private $id;
  54. #[ORM\Column(name: 'title', type: 'string', length: 50)]
  55. #[Gedmo\Translatable]
  56. #[Serializer\Groups(['Default', 'listingDetails', 'List', 'MiniList', 'Data', 'Details', 'Neighborhood', 'NeighborhoodStatistics', 'Discussion', 'Exchange', 'LocationFlat', 'Search', 'Translation', 'SlugResolver', 'Autocomplete', 'MyLeads', 'leadsBank', 'LocationStatistics', 'topAreasV2'])]
  57. #[Serializer\Expose]
  58. private string $title;
  59. /**
  60. * @var string
  61. */
  62. #[ORM\Column(name: 'alias', type: 'string', length: 512, nullable: true)]
  63. #[Gedmo\Translatable]
  64. #[Serializer\Groups(['SlugResolver'])]
  65. #[Serializer\Expose]
  66. private $alias;
  67. /**
  68. * @var string
  69. */
  70. #[ORM\Column(name: 'description', type: 'text', length: 512, nullable: true)]
  71. #[Gedmo\Translatable]
  72. #[Serializer\Groups(['Neighborhood'])]
  73. #[Serializer\Expose]
  74. private $description;
  75. #[ORM\Column(length: 128, unique: true)]
  76. #[Gedmo\Slug(fields: ['title'])]
  77. #[Gedmo\SlugHandler(class: TreeSlugHandler::class, options: [
  78. 'parentRelationField' => 'parent',
  79. 'separator' => '/',
  80. ])]
  81. #[Serializer\Groups(['Default', 'listingDetails', 'List', 'MiniList', 'Data', 'Details', 'Neighborhood', 'LocationFlat', 'Autocomplete', 'AutocompleteV3', 'DefaultV4', 'SearchV4', 'SlugResolver', 'RelatedListingsV2', 'UserFavoriteListings', 'topAreasV2'])]
  82. #[Groups(['valuation:read'])]
  83. #[Serializer\Expose]
  84. private string $slug = '';
  85. #[ORM\Column(name: 'lat', type: 'float', nullable: true)]
  86. #[Serializer\Groups(['DataJS', 'SSRData'])]
  87. #[Serializer\Since('v2.14')]
  88. #[Serializer\Expose]
  89. private ?float $lat = null;
  90. #[ORM\Column(name: 'lon', type: 'float', nullable: true)]
  91. #[Serializer\Groups(['DataJS', 'SSRData'])]
  92. #[Serializer\Since('v2.14')]
  93. #[Serializer\Expose]
  94. private ?float $lon = null;
  95. #[ORM\Column(name: 'zoom', type: 'smallint', nullable: true)]
  96. #[Serializer\Groups(['DataJS', 'SSRData'])]
  97. #[Serializer\Since('v2.14')]
  98. #[Serializer\Expose]
  99. private ?int $zoom = null;
  100. /**
  101. * @var array
  102. */
  103. #[ORM\Column(name: 'coordinates', type: 'array', nullable: true)]
  104. private $coordinates;
  105. #[ORM\Column(type: 'boolean')]
  106. #[Serializer\Expose]
  107. #[Serializer\Groups(['List', 'Data', 'Details', 'LocationFlat'])]
  108. private $searchable;
  109. #[ORM\Column(name: 'home_filter', type: 'boolean')]
  110. #[Serializer\Expose]
  111. #[Serializer\Groups(['Neighborhood'])]
  112. private $homeFilter = false;
  113. #[ORM\Column(name: 'statistics_filter', type: 'boolean')]
  114. #[Serializer\Expose]
  115. #[Serializer\Groups(['Neighborhood'])]
  116. private $statisticsFilter = false;
  117. #[ORM\Column(name: 'neighborhood_filter', type: 'boolean')]
  118. #[Serializer\Expose]
  119. #[Serializer\Groups(['Neighborhood'])]
  120. private $neighborhoodFilter = false;
  121. #[ORM\Column(name: 'compound_filter', type: 'boolean')]
  122. private $compoundFilter = false;
  123. #[ORM\Column(type: 'boolean')]
  124. #[Serializer\Expose]
  125. #[Serializer\Groups(['List', 'Data', 'Details', 'LocationFlat'])]
  126. private $estimate = false;
  127. #[ORM\Column(type: 'boolean')]
  128. #[Serializer\Expose]
  129. #[Serializer\Groups(['DefaultV4'])]
  130. private $disabled = false;
  131. #[ORM\Column(name: 'level', type: 'integer')]
  132. #[Gedmo\TreeLevel]
  133. #[Serializer\Expose]
  134. #[Serializer\Groups(['List', 'Data', 'LocationFlat', 'DefaultV4', 'SlugResolver'])]
  135. private $level;
  136. #[ORM\Column(name: '_left', type: 'integer')]
  137. #[Gedmo\TreeLeft]
  138. private $left;
  139. #[ORM\Column(name: '_right', type: 'integer')]
  140. #[Gedmo\TreeRight]
  141. private $right;
  142. #[ORM\Column(name: 'root', type: 'integer', nullable: true)]
  143. #[Gedmo\TreeRoot]
  144. private $root;
  145. #[ORM\Column(name: 'show_primary_only', type: 'boolean', options: ['default' => false])]
  146. #[Serializer\Expose]
  147. #[Serializer\Groups(['Autocomplete', 'List', 'Data', 'Details', 'LocationFlat', 'AutocompleteV3', 'Compound', 'SlugResolver'])]
  148. private $showPrimaryOnly = false;
  149. #[ORM\ManyToOne(targetEntity: Location::class, inversedBy: 'children')]
  150. #[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
  151. #[Gedmo\TreeParent]
  152. #[Serializer\Expose]
  153. #[Serializer\Groups(['DefaultV4', 'SearchV4', 'SlugResolver', 'RelatedListingsV2', 'listingDetails'])]
  154. #[Serializer\MaxDepth(1)]
  155. private $parent;
  156. #[ORM\OneToMany(targetEntity: Location::class, mappedBy: 'parent')]
  157. #[ORM\OrderBy(['left' => 'ASC'])]
  158. #[Serializer\Expose]
  159. #[Serializer\Groups(['List'])]
  160. #[Serializer\MaxDepth(2)]
  161. #[Serializer\Accessor(getter: 'getChildren')]
  162. private $children;
  163. #[ORM\ManyToMany(targetEntity: Location::class, cascade: ['persist'])]
  164. #[ORM\JoinTable(name: 'locations_nearestby', joinColumns: [new ORM\JoinColumn(name: 'nearest_location_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'location_id', referencedColumnName: 'id')])]
  165. protected $nearestLocations;
  166. #[ORM\OneToMany(targetEntity: LocationTranslation::class, mappedBy: 'object', cascade: ['persist', 'remove'])]
  167. private $translations;
  168. #[ORM\OneToMany(targetEntity: Listing::class, mappedBy: 'location')]
  169. protected $listings;
  170. #[ORM\ManyToMany(targetEntity: PropertyType::class)]
  171. protected $propertyTypes;
  172. #[ORM\OneToMany(targetEntity: \Aqarmap\Bundle\CRMBundle\Entity\Company::class, mappedBy: 'location')]
  173. protected $companies;
  174. #[ORM\OneToMany(targetEntity: LocationSupplyDemand::class, mappedBy: 'location')]
  175. protected $locationSupplyDemand;
  176. #[ORM\OneToMany(targetEntity: Notifier::class, mappedBy: 'location')]
  177. protected $notifiers;
  178. #[ORM\OneToMany(targetEntity: UserInterest::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
  179. protected $interests;
  180. #[ORM\OneToMany(targetEntity: Rule::class, mappedBy: 'location')]
  181. protected $rules;
  182. #[ORM\OneToMany(targetEntity: LocationPhoto::class, mappedBy: 'location', cascade: ['persist', 'remove'])]
  183. #[Serializer\Expose]
  184. #[Serializer\Groups(['Neighborhood', 'topAreasV2'])]
  185. protected $photos;
  186. #[ORM\OneToMany(targetEntity: LocationStatistics::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
  187. #[Serializer\Expose]
  188. #[Serializer\Groups(['Neighborhood'])]
  189. protected $locationStatistics;
  190. #[ORM\OneToOne(targetEntity: LocationCompound::class, cascade: ['persist', 'remove'], mappedBy: 'location')]
  191. #[ORM\JoinColumn(name: 'location_compound_id', referencedColumnName: 'id')]
  192. protected $locationCompound;
  193. #[ORM\OneToMany(targetEntity: Discussion::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
  194. protected $discussions;
  195. #[ORM\OneToMany(targetEntity: ExchangeRequest::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
  196. protected $exchangeRequests;
  197. #[ORM\OneToOne(targetEntity: LocationRating::class, cascade: ['persist', 'remove'])]
  198. #[Serializer\Expose]
  199. #[Serializer\Groups(['Neighborhood'])]
  200. protected $rating;
  201. #[ORM\ManyToOne(targetEntity: Listing::class, cascade: ['persist', 'remove'])]
  202. #[ORM\JoinColumn(name: 'listing_id', referencedColumnName: 'id', nullable: true)]
  203. #[Serializer\Expose]
  204. #[Serializer\Groups(['Autocomplete'])]
  205. protected $listing;
  206. #[ORM\OneToMany(targetEntity: SearchTerm::class, mappedBy: 'location')]
  207. protected $searchTerms;
  208. #[ORM\ManyToMany(targetEntity: LocationTier::class, mappedBy: 'locations')]
  209. private Collection $tiers;
  210. #[Gedmo\Locale] // Used locale to override Translation listener`s locale
  211. private $locale;
  212. /**
  213. * @var int
  214. * Count number of leads for live listings
  215. */
  216. #[ORM\Column(name: 'leads_counter', type: 'integer', options: ['default' => 0])]
  217. #[Serializer\Groups(['Api'])]
  218. #[Serializer\Expose]
  219. private $leadsCounter = 0;
  220. /**
  221. * @var int
  222. * Count number of live listings
  223. */
  224. #[ORM\Column(name: 'listings_counter', type: 'integer', options: ['default' => 0])]
  225. #[Serializer\Groups(['Api', 'RelatedResults', 'MiniList'])]
  226. #[Serializer\Expose]
  227. private $listingsCounter = 0;
  228. /**
  229. * Project File.
  230. */
  231. protected $file;
  232. #[ORM\Column(name: 'synonyms', type: 'text', nullable: true)]
  233. private $synonyms;
  234. private $location;
  235. /**
  236. * @var string
  237. */
  238. #[ORM\Column(name: 'full_path', type: 'text', nullable: true)]
  239. private $fullPath;
  240. #[ORM\Column(name: 'reference_id', type: 'integer', nullable: true)]
  241. private $referenceId;
  242. /**
  243. * @var string
  244. */
  245. #[ORM\Column(name: 'type', type: 'string', length: 50)]
  246. #[Serializer\Groups(['listingDetails', 'listingDetailsWithLocationCompound'])]
  247. #[Serializer\Expose]
  248. private $type;
  249. /**
  250. * @var array
  251. */
  252. private $locationTranslations = [];
  253. /**
  254. * @var array
  255. */
  256. private $v4Translations = [];
  257. #[ORM\Column(name: 'eligible_for_mortgage', type: 'boolean')]
  258. #[Serializer\Groups(['listingDetails', 'listingDetailsWithLocationCompound'])]
  259. #[Serializer\Expose]
  260. protected $eligibleForMortgage = false;
  261. #[ORM\Column(name: 'is_compound_location', type: 'boolean')]
  262. #[Serializer\Expose]
  263. #[Serializer\Groups(['Autocomplete', 'List', 'Data', 'Details', 'LocationFlat', 'AutocompleteV3', 'Compound', 'SlugResolver'])]
  264. private $isCompoundLocation = false;
  265. #[ORM\OneToMany(targetEntity: Location::class, mappedBy: 'parent')]
  266. #[ORM\OrderBy(['id' => 'ASC'])]
  267. #[Serializer\Expose]
  268. #[Serializer\Groups(['Data'])]
  269. #[Serializer\MaxDepth(2)]
  270. #[Serializer\Accessor(getter: 'getChildrenSortedById')]
  271. #[Serializer\SerializedName('children')]
  272. private $childrenSortedById;
  273. #[Serializer\VirtualProperty]
  274. public function getLocation()
  275. {
  276. return $this->location;
  277. }
  278. public function getSynonyms()
  279. {
  280. return $this->synonyms;
  281. }
  282. /**
  283. * @param mixed $synonym
  284. */
  285. public function addSynonym(string $synonym): self
  286. {
  287. $synonyms = $this->getSynonyms() ? explode(',', (string) $this->getSynonyms()) : [];
  288. if (!empty($synonym) && !in_array($synonym, $synonyms, true)) {
  289. $synonyms[] = $synonym;
  290. }
  291. $this->synonyms = implode(',', $synonyms) ?: null;
  292. return $this;
  293. }
  294. public function removeSynonym(string $synonym): self
  295. {
  296. $newSynonyms = array_diff(explode(',', (string) $this->getSynonyms()), [$synonym]);
  297. $this->synonyms = implode(',', $newSynonyms) ?: null;
  298. return $this;
  299. }
  300. public function getFile()
  301. {
  302. return $this->file;
  303. }
  304. public function setFile($file): void
  305. {
  306. $this->file = $file;
  307. }
  308. /**
  309. * Constructor.
  310. */
  311. public function __construct()
  312. {
  313. $this->children = new ArrayCollection();
  314. $this->translations = new ArrayCollection();
  315. $this->listings = new ArrayCollection();
  316. $this->notifiers = new ArrayCollection();
  317. $this->rules = new ArrayCollection();
  318. $this->locationStatistics = new ArrayCollection();
  319. $this->photos = new ArrayCollection();
  320. $this->discussions = new ArrayCollection();
  321. $this->propertyTypes = new ArrayCollection();
  322. $this->nearestLocations = new ArrayCollection();
  323. $this->interests = new ArrayCollection();
  324. $this->exchangeRequests = new ArrayCollection();
  325. $this->tiers = new ArrayCollection();
  326. }
  327. // ---------------------------------------------------------------------
  328. /**
  329. * Get id.
  330. *
  331. * @return int
  332. */
  333. public function getId()
  334. {
  335. return $this->id;
  336. }
  337. // ---------------------------------------------------------------------
  338. /**
  339. * Set title.
  340. *
  341. * @param string $title
  342. *
  343. * @return Location
  344. */
  345. public function setTitle($title)
  346. {
  347. $this->title = $title;
  348. return $this;
  349. }
  350. /**
  351. * Get title.
  352. *
  353. * @return string
  354. */
  355. public function getTitle()
  356. {
  357. return $this->title;
  358. }
  359. /**
  360. * Get a short path title (ie: New Cairo - 90th Street).
  361. */
  362. #[Groups(['valuation:list', 'valuation:read'])]
  363. public function getTitleShortPath(): string
  364. {
  365. $neighbourhood = $this->getParentByType(LocationTypes::NEIGHBORHOOD, true);
  366. if ($neighbourhood) {
  367. return $this->getTitle().' - '.$neighbourhood->getTitle();
  368. }
  369. return $this->getTitle();
  370. }
  371. /**
  372. * @return string
  373. */
  374. public function getIndentedTitle()
  375. {
  376. return str_repeat('--', $this->getLevel()).' '.$this->getTitle();
  377. }
  378. // ---------------------------------------------------------------------
  379. /**
  380. * Set description.
  381. *
  382. * @param string $description
  383. *
  384. * @return Location
  385. */
  386. public function setDescription($description)
  387. {
  388. $this->description = $description;
  389. return $this;
  390. }
  391. /**
  392. * Get description.
  393. *
  394. * @return string
  395. */
  396. public function getDescription()
  397. {
  398. return $this->description;
  399. }
  400. // ---------------------------------------------------------------------
  401. /**
  402. * Set slug.
  403. *
  404. * @param string $slug
  405. *
  406. * @return Location
  407. */
  408. public function setSlug($slug)
  409. {
  410. $this->slug = $slug;
  411. return $this;
  412. }
  413. /**
  414. * Get slug.
  415. */
  416. public function getSlug(): string
  417. {
  418. return $this->slug;
  419. }
  420. // ---------------------------------------------------------------------
  421. /**
  422. * Set centerLat.
  423. *
  424. * @param float $centerLat
  425. *
  426. * @return Location
  427. */
  428. public function setCenterLat($centerLat)
  429. {
  430. return $this->setLat($centerLat);
  431. }
  432. /**
  433. * @return float
  434. */
  435. #[Serializer\VirtualProperty]
  436. #[Serializer\Groups(['Map', 'Details', 'Neighborhood', 'LocationFlat', 'Autocomplete'])]
  437. #[Serializer\SerializedName('center_lat')]
  438. #[Serializer\Until('v2.13')]
  439. #[Serializer\Expose]
  440. public function getCenterLat()
  441. {
  442. return $this->getLat();
  443. }
  444. /**
  445. * @param float $latitude
  446. *
  447. * @return Location
  448. */
  449. public function setLat($latitude)
  450. {
  451. $this->lat = $latitude;
  452. return $this;
  453. }
  454. /**
  455. * @return float|null
  456. */
  457. public function getLat()
  458. {
  459. if (!$this->lat) {
  460. return null;
  461. }
  462. return (float) $this->lat;
  463. }
  464. // ---------------------------------------------------------------------
  465. /**
  466. * Set lon.
  467. *
  468. * @deprecated
  469. *
  470. * @param float $lon
  471. *
  472. * @return Location
  473. */
  474. public function setCenterLng($lon)
  475. {
  476. return $this->setLon($lon);
  477. }
  478. /**
  479. * @deprecated
  480. *
  481. * @return float|null
  482. */
  483. #[Serializer\VirtualProperty]
  484. #[Serializer\Groups(['Map', 'Details', 'Neighborhood', 'LocationFlat', 'Autocomplete'])]
  485. #[Serializer\SerializedName('center_lng')]
  486. #[Serializer\Until('v2.13')]
  487. #[Serializer\Expose]
  488. public function getCenterLng()
  489. {
  490. return $this->getLon();
  491. }
  492. /**
  493. * @param float $longitude
  494. *
  495. * @return Location
  496. */
  497. public function setLon($longitude)
  498. {
  499. $this->lon = $longitude;
  500. return $this;
  501. }
  502. /**
  503. * @return float|null
  504. */
  505. public function getLon()
  506. {
  507. if (!$this->lon) {
  508. return null;
  509. }
  510. return (float) $this->lon;
  511. }
  512. // ---------------------------------------------------------------------
  513. /**
  514. * Set zoom.
  515. *
  516. * @deprecated
  517. *
  518. * @param int $zoom
  519. *
  520. * @return Location
  521. */
  522. public function setZoomLevel($zoom)
  523. {
  524. return $this->setZoom($zoom);
  525. }
  526. /**
  527. * @deprecated
  528. *
  529. * @return int
  530. */
  531. #[Serializer\VirtualProperty]
  532. #[Serializer\Groups(['Map', 'Details', 'Neighborhood', 'LocationFlat', 'Autocomplete', 'AutocompleteV3', 'DefaultV4'])]
  533. #[Serializer\SerializedName('zoom_level')]
  534. #[Serializer\Until('v2.13')]
  535. #[Serializer\Expose]
  536. public function getZoomLevel()
  537. {
  538. return $this->getZoom();
  539. }
  540. public function setZoom(?int $level): self
  541. {
  542. $this->zoom = $level;
  543. return $this;
  544. }
  545. /**
  546. * @return int|null
  547. */
  548. #[Serializer\VirtualProperty]
  549. #[Serializer\SerializedName('zoom')]
  550. #[Serializer\Groups(['DataJS'])]
  551. public function getZoom()
  552. {
  553. return $this->zoom;
  554. }
  555. // ---------------------------------------------------------------------
  556. /**
  557. * Set coordinates.
  558. *
  559. * @param array $coordinates
  560. *
  561. * @return Location
  562. */
  563. public function setCoordinates($coordinates)
  564. {
  565. $this->coordinates = $coordinates;
  566. return $this;
  567. }
  568. /**
  569. * Get coordinates.
  570. *
  571. * @return array
  572. */
  573. public function getCoordinates()
  574. {
  575. return $this->coordinates;
  576. }
  577. // ---------------------------------------------------------------------
  578. /**
  579. * Set searchable.
  580. *
  581. * @param bool $searchable
  582. *
  583. * @return Location
  584. */
  585. public function setSearchable($searchable)
  586. {
  587. $this->searchable = $searchable;
  588. return $this;
  589. }
  590. /**
  591. * Get searchable.
  592. *
  593. * @return bool
  594. */
  595. public function getSearchable()
  596. {
  597. return $this->searchable;
  598. }
  599. // ---------------------------------------------------------------------
  600. /**
  601. * Set homeFilter.
  602. *
  603. * @param bool $homeFilter
  604. *
  605. * @return Location
  606. */
  607. public function setHomeFilter($homeFilter)
  608. {
  609. $this->homeFilter = $homeFilter;
  610. return $this;
  611. }
  612. /**
  613. * Get homeFilter.
  614. *
  615. * @return bool
  616. */
  617. public function getHomeFilter()
  618. {
  619. return $this->homeFilter;
  620. }
  621. // ---------------------------------------------------------------------
  622. /**
  623. * Set estimate.
  624. *
  625. * @param bool $estimate
  626. *
  627. * @return Location
  628. */
  629. public function setEstimate($estimate)
  630. {
  631. $this->estimate = $estimate;
  632. return $this;
  633. }
  634. /**
  635. * Get estimate.
  636. *
  637. * @return bool
  638. */
  639. public function getEstimate()
  640. {
  641. return $this->estimate;
  642. }
  643. // ---------------------------------------------------------------------
  644. /**
  645. * Set disabled.
  646. *
  647. * @param bool $disabled
  648. *
  649. * @return Location
  650. */
  651. public function setDisabled($disabled)
  652. {
  653. $this->disabled = $disabled;
  654. return $this;
  655. }
  656. /**
  657. * Get disabled.
  658. *
  659. * @return bool
  660. */
  661. public function getDisabled()
  662. {
  663. return $this->disabled;
  664. }
  665. // ---------------------------------------------------------------------
  666. /**
  667. * Set parent.
  668. *
  669. * @return Location
  670. */
  671. public function setParent(?self $parent = null)
  672. {
  673. $this->parent = $parent;
  674. return $this;
  675. }
  676. /**
  677. * Get parent.
  678. *
  679. * @return Location
  680. */
  681. public function getParent()
  682. {
  683. return $this->parent;
  684. }
  685. // ---------------------------------------------------------------------
  686. /**
  687. * Add children.
  688. *
  689. * @return Location
  690. */
  691. public function addChild(self $children)
  692. {
  693. $this->children[] = $children;
  694. return $this;
  695. }
  696. /**
  697. * Remove children.
  698. */
  699. public function removeChild(self $children): void
  700. {
  701. $this->children->removeElement($children);
  702. }
  703. /**
  704. * Get children.
  705. *
  706. * @return Collection
  707. */
  708. public function getChildren()
  709. {
  710. $criteria = Criteria::create()
  711. ->where(Criteria::expr()->eq('disabled', false));
  712. return $this->children->matching($criteria);
  713. }
  714. /**
  715. * Get children sorted by id.
  716. *
  717. * @return Collection
  718. */
  719. public function getChildrenSortedById($filters = [])
  720. {
  721. $criteria = Criteria::create()
  722. ->where(Criteria::expr()->eq('disabled', false));
  723. if (isset($filters['neighborhoodFilter'])) {
  724. $criteria->andWhere(Criteria::expr()->eq('neighborhoodFilter', $filters['neighborhoodFilter']));
  725. }
  726. return $this->childrenSortedById->matching($criteria);
  727. }
  728. /**
  729. * Get children.
  730. *
  731. * @return Collection
  732. */
  733. public function getChildrenArray()
  734. {
  735. $criteria = Criteria::create()
  736. ->where(Criteria::expr()->eq('disabled', false));
  737. return $this->children->matching($criteria)->toArray();
  738. }
  739. /**
  740. * Get neighborhoodchildren.
  741. *
  742. * @return Collection
  743. */
  744. public function getNeighborhoodChildren()
  745. {
  746. $criteria = Criteria::create()
  747. ->andWhere(Criteria::expr()->eq('disabled', false))
  748. ->andWhere(Criteria::expr()->eq('neighborhoodFilter', true));
  749. return $this->children->matching($criteria);
  750. }
  751. /**
  752. * Get leveled children.
  753. *
  754. * @return Collection
  755. */
  756. public function getLeveledChildren()
  757. {
  758. $criteria = Criteria::create()
  759. ->where(Criteria::expr()->eq('disabled', false))
  760. ->where(Criteria::expr()->lte('level', 2));
  761. return $this->children->matching($criteria);
  762. }
  763. /**
  764. * Set type.
  765. *
  766. * @param string $type
  767. *
  768. * @return Location
  769. */
  770. public function setType($type)
  771. {
  772. $this->type = $type;
  773. return $this;
  774. }
  775. /**
  776. * Get type.
  777. *
  778. * @return string
  779. */
  780. public function getType()
  781. {
  782. return $this->type;
  783. }
  784. public function getTypeLabel(): ?string
  785. {
  786. return LocationTypes::getLabel($this->getType());
  787. }
  788. // ---------------------------------------------------------------------
  789. /**
  790. * Get translations.
  791. *
  792. * @return ArrayCollection
  793. */
  794. public function getTranslations()
  795. {
  796. return $this->translations;
  797. }
  798. /**
  799. * Add translation.
  800. *
  801. * @return Location
  802. */
  803. public function addTranslation(LocationTranslation $translation)
  804. {
  805. if (!$this->translations->contains($translation)) {
  806. $this->translations->add($translation);
  807. $translation->setObject($this);
  808. }
  809. return $this;
  810. }
  811. /**
  812. * Remove translation.
  813. *
  814. * @return Location
  815. */
  816. public function removeTranslation(LocationTranslation $translation)
  817. {
  818. if ($this->translations->contains($translation)) {
  819. $this->translations->removeElement($translation);
  820. }
  821. return $this;
  822. }
  823. // ---------------------------------------------------------------------
  824. /**
  825. * Add listings.
  826. *
  827. * @return Location
  828. */
  829. public function addListing(Listing $listings)
  830. {
  831. $this->listings[] = $listings;
  832. return $this;
  833. }
  834. /**
  835. * Remove listings.
  836. */
  837. public function removeListing(Listing $listings): void
  838. {
  839. $this->listings->removeElement($listings);
  840. }
  841. /**
  842. * Get listings.
  843. *
  844. * @return Collection
  845. */
  846. public function getListings()
  847. {
  848. return $this->listings;
  849. }
  850. // ---------------------------------------------------------------------
  851. /**
  852. * Add notifiers.
  853. *
  854. * @return Location
  855. */
  856. public function addNotifier(Notifier $notifiers)
  857. {
  858. $this->notifiers[] = $notifiers;
  859. return $this;
  860. }
  861. /**
  862. * Remove notifiers.
  863. */
  864. public function removeNotifier(Notifier $notifiers): void
  865. {
  866. $this->notifiers->removeElement($notifiers);
  867. }
  868. /**
  869. * Get notifiers.
  870. *
  871. * @return Collection
  872. */
  873. public function getNotifiers()
  874. {
  875. return $this->notifiers;
  876. }
  877. // ---------------------------------------------------------------------
  878. /**
  879. * Add rules.
  880. *
  881. * @return Location
  882. */
  883. public function addRule(Rule $rules)
  884. {
  885. $this->rules[] = $rules;
  886. return $this;
  887. }
  888. /**
  889. * Remove rules.
  890. */
  891. public function removeRule(Rule $rules): void
  892. {
  893. $this->rules->removeElement($rules);
  894. }
  895. /**
  896. * Get rules.
  897. *
  898. * @return Collection
  899. */
  900. public function getRules()
  901. {
  902. return $this->rules;
  903. }
  904. // ---------------------------------------------------------------------
  905. /**
  906. * Get Nearest Searchable Location.
  907. */
  908. public function getNearestSearchable()
  909. {
  910. $location = $this;
  911. while ($location && !$location->getSearchable()) {
  912. $location = $location->getParent();
  913. }
  914. if (!$location) {
  915. return $this;
  916. }
  917. return $location;
  918. }
  919. // -----------------------------------------------------------------------------
  920. /**
  921. * Get Nearest Neighborhood Parent.
  922. */
  923. public function getNearestNeighborhood()
  924. {
  925. $location = $this;
  926. while (
  927. !$location->getNeighborhoodFilter()
  928. && $location->getParent()
  929. && 0 != $location->getParent()->getLevel()
  930. ) {
  931. $location = $location->getParent();
  932. }
  933. if (!$location->getNeighborhoodFilter() || 0 == $location->getLevel()) {
  934. return;
  935. }
  936. return $location;
  937. }
  938. /**
  939. * Get Nearest Location Custom Level .
  940. *
  941. * @param int $level
  942. *
  943. * @return Location
  944. */
  945. public function getNearestLeveledLocation($level = 1)
  946. {
  947. $location = $this;
  948. if (\in_array($location->getLevel(), [0, $level])) {
  949. return $location;
  950. }
  951. while ($location->getParent() && 0 != $location->getParent()->getLevel()) {
  952. $location = $location->getParent();
  953. }
  954. return $location;
  955. }
  956. /**
  957. * Get the nearest parent with the provided location type.
  958. */
  959. public function getParentByType(string $locationType, bool $rootFallback = false): ?self
  960. {
  961. $location = $this->getParent();
  962. $root = null;
  963. while ($location) {
  964. if ($location->getType() === $locationType) {
  965. return $location;
  966. }
  967. $root = $location;
  968. $location = $location->getParent();
  969. }
  970. return $rootFallback ? $root : null;
  971. }
  972. #[Serializer\VirtualProperty]
  973. #[Serializer\SerializedName('parent')]
  974. #[Serializer\Expose]
  975. #[Serializer\Groups(['LocationFlat'])]
  976. public function getVirtualParent()
  977. {
  978. $parent = $this->getParent();
  979. if ($parent) {
  980. return [
  981. 'id' => $parent->getId(),
  982. 'title' => $parent->getTitle(),
  983. ];
  984. }
  985. return null;
  986. }
  987. /**
  988. * Gets parent by level.
  989. *
  990. * @param int $level
  991. *
  992. * @return Location|null
  993. */
  994. public function getLeveledParent($level = 1)
  995. {
  996. $location = $this;
  997. while ($location = $location->getParent()) {
  998. if ($location->getLevel() == $level) {
  999. return $location;
  1000. }
  1001. }
  1002. return null;
  1003. }
  1004. /**
  1005. * Get Nearest Location Custom Level .
  1006. *
  1007. * @return Location
  1008. */
  1009. public function getFirstParent()
  1010. {
  1011. $location = $this;
  1012. if (0 == $location->getLevel()) {
  1013. return $location;
  1014. }
  1015. while ($location = $location->getParent()) {
  1016. if (0 == $location->getLevel()) {
  1017. return $location;
  1018. }
  1019. }
  1020. return $location;
  1021. }
  1022. /**
  1023. * Set level.
  1024. *
  1025. * @param int $level
  1026. *
  1027. * @return Location
  1028. */
  1029. public function setLevel($level)
  1030. {
  1031. $this->level = $level;
  1032. return $this;
  1033. }
  1034. /**
  1035. * Get level.
  1036. *
  1037. * @return int
  1038. */
  1039. public function getLevel()
  1040. {
  1041. return $this->level;
  1042. }
  1043. /**
  1044. * Set left.
  1045. *
  1046. * @param int $left
  1047. *
  1048. * @return Location
  1049. */
  1050. public function setLeft($left)
  1051. {
  1052. $this->left = $left;
  1053. return $this;
  1054. }
  1055. /**
  1056. * Get left.
  1057. *
  1058. * @return int
  1059. */
  1060. public function getLeft()
  1061. {
  1062. return $this->left;
  1063. }
  1064. /**
  1065. * Set right.
  1066. *
  1067. * @param int $right
  1068. *
  1069. * @return Location
  1070. */
  1071. public function setRight($right)
  1072. {
  1073. $this->right = $right;
  1074. return $this;
  1075. }
  1076. /**
  1077. * Get right.
  1078. *
  1079. * @return int
  1080. */
  1081. public function getRight()
  1082. {
  1083. return $this->right;
  1084. }
  1085. /**
  1086. * Set root.
  1087. *
  1088. * @param int $root
  1089. *
  1090. * @return Location
  1091. */
  1092. public function setRoot($root)
  1093. {
  1094. $this->root = $root;
  1095. return $this;
  1096. }
  1097. /**
  1098. * Get root.
  1099. *
  1100. * @return int
  1101. */
  1102. public function getRoot()
  1103. {
  1104. return $this->root;
  1105. }
  1106. /**
  1107. * Add locationSupplyDemand.
  1108. *
  1109. * @return Location
  1110. */
  1111. public function addLocationSupplyDemand(LocationSupplyDemand $locationSupplyDemand)
  1112. {
  1113. $this->locationSupplyDemand[] = $locationSupplyDemand;
  1114. return $this;
  1115. }
  1116. /**
  1117. * Remove locationSupplyDemand.
  1118. */
  1119. public function removeLocationSupplyDemand(LocationSupplyDemand $locationSupplyDemand): void
  1120. {
  1121. $this->locationSupplyDemand->removeElement($locationSupplyDemand);
  1122. }
  1123. /**
  1124. * Get locationSupplyDemand.
  1125. *
  1126. * @return Collection
  1127. */
  1128. public function getLocationSupplyDemand()
  1129. {
  1130. return $this->locationSupplyDemand;
  1131. }
  1132. // ---------------------------------------------------------------------
  1133. /**
  1134. * Add photos.
  1135. *
  1136. * @return Location
  1137. */
  1138. public function addPhoto(LocationPhoto $photo)
  1139. {
  1140. $photo->setLocation($this);
  1141. $this->photos[] = $photo;
  1142. return $this;
  1143. }
  1144. /**
  1145. * Set photos.
  1146. *
  1147. * @return Location
  1148. */
  1149. public function setPhotos($photos)
  1150. {
  1151. foreach ($photos as $photo) {
  1152. $this->addPhoto($photo);
  1153. }
  1154. return $this;
  1155. }
  1156. /**
  1157. * Remove photos.
  1158. */
  1159. public function removePhoto(LocationPhoto $photo): void
  1160. {
  1161. $this->photos->removeElement($photo);
  1162. }
  1163. /**
  1164. * @return ArrayCollection
  1165. */
  1166. public function getPhotos()
  1167. {
  1168. return $this->photos;
  1169. }
  1170. #[Serializer\VirtualProperty]
  1171. #[Serializer\Groups(['topAreasV2'])]
  1172. #[Serializer\SerializedName('avg_price_per_meter')]
  1173. public function getAvgPricePerMeter(): ?float
  1174. {
  1175. $statistics = $this->getSingleStatistics();
  1176. return $statistics ? (float) $statistics->getAvgPrice() : null;
  1177. }
  1178. #[Serializer\VirtualProperty]
  1179. #[Serializer\Groups(['Default', 'LocationFlat', 'topAreasV2'])]
  1180. public function getMainPhoto(): ?LocationPhoto
  1181. {
  1182. // Important for API
  1183. if ($this->getPhotos()->count() <= 0) {
  1184. return null;
  1185. }
  1186. /* @var LocationPhoto $photo */
  1187. $mainPhoto = $this->photos->filter(fn ($photo) => PhotoTypes::MAIN_PHOTO == $photo->getType());
  1188. return $mainPhoto->first() ?: $this->getPhotos()->first();
  1189. }
  1190. // ---------------------------------------------------------------------
  1191. public function __clone()
  1192. {
  1193. $this->id = null;
  1194. }
  1195. public function __toString(): string
  1196. {
  1197. return $this->title;
  1198. }
  1199. /**
  1200. * Set rating.
  1201. *
  1202. * @return Location
  1203. */
  1204. public function setRating(?LocationRating $rating = null)
  1205. {
  1206. $this->rating = $rating;
  1207. $this->rating->setLocation($this);
  1208. return $this;
  1209. }
  1210. /**
  1211. * Get rating.
  1212. *
  1213. * @return LocationRating
  1214. */
  1215. public function getRating()
  1216. {
  1217. return $this->rating;
  1218. }
  1219. /**
  1220. * Get rating of the nearest parent location that has one.
  1221. */
  1222. public function getNearestRating()
  1223. {
  1224. $location = $this;
  1225. while ($location) {
  1226. $rating = $location->getRating();
  1227. if (
  1228. $rating
  1229. && null !== $rating->getOverall()
  1230. && LocationTypes::CITY !== $location->getType()
  1231. ) {
  1232. return $rating;
  1233. }
  1234. $location = $location->getParent();
  1235. }
  1236. return null;
  1237. }
  1238. /**
  1239. * Set neighborhoodFilter.
  1240. *
  1241. * @param bool $neighborhoodFilter
  1242. *
  1243. * @return Location
  1244. */
  1245. public function setNeighborhoodFilter($neighborhoodFilter)
  1246. {
  1247. $this->neighborhoodFilter = $neighborhoodFilter;
  1248. return $this;
  1249. }
  1250. /**
  1251. * Get neighborhoodFilter.
  1252. *
  1253. * @return bool
  1254. */
  1255. public function getNeighborhoodFilter()
  1256. {
  1257. return $this->neighborhoodFilter;
  1258. }
  1259. /**
  1260. * Add locationStatistic.
  1261. *
  1262. * @return Location
  1263. */
  1264. public function addLocationStatistic(LocationStatistics $locationStatistic)
  1265. {
  1266. $this->locationStatistics[] = $locationStatistic;
  1267. return $this;
  1268. }
  1269. /**
  1270. * Remove locationStatistic.
  1271. */
  1272. public function removeLocationStatistic(LocationStatistics $locationStatistic): void
  1273. {
  1274. $this->locationStatistics->removeElement($locationStatistic);
  1275. }
  1276. /**
  1277. * Get locationStatistics.
  1278. *
  1279. * @return Collection
  1280. */
  1281. public function getLocationStatistics()
  1282. {
  1283. return $this->locationStatistics;
  1284. }
  1285. /**
  1286. * Get lowest Average Price.
  1287. *
  1288. * @return LocationStatistics $locationStatistic
  1289. */
  1290. public function getSingleStatistics(?PropertyType $propertyType = null)
  1291. {
  1292. $criteria = Criteria::create()
  1293. ->andWhere(Criteria::expr()->neq('avgPrice', null))
  1294. ->andWhere(Criteria::expr()->gt('avgPrice', 0))
  1295. ->orderBy(['avgPrice' => Criteria::ASC]);
  1296. if ($propertyType) {
  1297. $criteria
  1298. ->andWhere(Criteria::expr()->eq('propertyType', $propertyType));
  1299. }
  1300. return $this->locationStatistics->matching($criteria)->first();
  1301. }
  1302. /**
  1303. * Set statisticsFilter.
  1304. *
  1305. * @param bool $statisticsFilter
  1306. *
  1307. * @return Location
  1308. */
  1309. public function setStatisticsFilter($statisticsFilter)
  1310. {
  1311. $this->statisticsFilter = $statisticsFilter;
  1312. return $this;
  1313. }
  1314. /**
  1315. * Get statisticsFilter.
  1316. *
  1317. * @return bool
  1318. */
  1319. public function getStatisticsFilter()
  1320. {
  1321. return $this->statisticsFilter;
  1322. }
  1323. /**
  1324. * Add company.
  1325. *
  1326. * @return Location
  1327. */
  1328. public function addCompany(\Aqarmap\Bundle\CRMBundle\Entity\Company $company)
  1329. {
  1330. $this->companies[] = $company;
  1331. return $this;
  1332. }
  1333. /**
  1334. * Remove company.
  1335. */
  1336. public function removeCompany(\Aqarmap\Bundle\CRMBundle\Entity\Company $company): void
  1337. {
  1338. $this->companies->removeElement($company);
  1339. }
  1340. /**
  1341. * Get companies.
  1342. *
  1343. * @return Collection
  1344. */
  1345. public function getCompanies()
  1346. {
  1347. return $this->companies;
  1348. }
  1349. /**
  1350. * Add discussion.
  1351. *
  1352. * @return Location
  1353. */
  1354. public function addDiscussion(Discussion $discussion)
  1355. {
  1356. $this->discussions[] = $discussion;
  1357. return $this;
  1358. }
  1359. /**
  1360. * Remove discussion.
  1361. */
  1362. public function removeDiscussion(Discussion $discussion): void
  1363. {
  1364. $this->discussions->removeElement($discussion);
  1365. }
  1366. /**
  1367. * Get discussions.
  1368. *
  1369. * @return Collection
  1370. */
  1371. public function getDiscussions()
  1372. {
  1373. return $this->discussions;
  1374. }
  1375. /**
  1376. * Set compoundFilter.
  1377. *
  1378. * @param bool $compoundFilter
  1379. *
  1380. * @return Location
  1381. */
  1382. public function setCompoundFilter($compoundFilter)
  1383. {
  1384. $this->compoundFilter = $compoundFilter;
  1385. return $this;
  1386. }
  1387. /**
  1388. * Get compoundFilter.
  1389. *
  1390. * @return bool
  1391. */
  1392. public function getCompoundFilter()
  1393. {
  1394. return $this->compoundFilter;
  1395. }
  1396. /**
  1397. * Add propertyType.
  1398. *
  1399. * @return Location
  1400. */
  1401. public function addPropertyType(PropertyType $propertyType)
  1402. {
  1403. $this->propertyTypes[] = $propertyType;
  1404. return $this;
  1405. }
  1406. /**
  1407. * Remove propertyType.
  1408. */
  1409. public function removePropertyType(PropertyType $propertyType): void
  1410. {
  1411. $this->propertyTypes->removeElement($propertyType);
  1412. }
  1413. /**
  1414. * Get propertyTypes.
  1415. *
  1416. * @return Collection
  1417. */
  1418. public function getPropertyTypes()
  1419. {
  1420. return $this->propertyTypes;
  1421. }
  1422. /**
  1423. * Set listing.
  1424. *
  1425. * @return Location
  1426. */
  1427. public function setListing(?Listing $listing = null)
  1428. {
  1429. $this->listing = $listing;
  1430. return $this;
  1431. }
  1432. /**
  1433. * Set listing.
  1434. *
  1435. * @return Location
  1436. */
  1437. public function setListings(array $listings = [])
  1438. {
  1439. $this->listings = $listings;
  1440. return $this;
  1441. }
  1442. /**
  1443. * Get listing.
  1444. *
  1445. * @return Listing
  1446. */
  1447. public function getListing()
  1448. {
  1449. return $this->listing;
  1450. }
  1451. /**
  1452. * Set locationCompound.
  1453. *
  1454. * @return Location
  1455. */
  1456. public function setLocationCompound(?LocationCompound $locationCompound = null)
  1457. {
  1458. $this->locationCompound = $locationCompound;
  1459. $this->locationCompound->setLocation($this);
  1460. return $this;
  1461. }
  1462. /**
  1463. * Get locationCompound.
  1464. *
  1465. * @return LocationCompound
  1466. */
  1467. public function getLocationCompound()
  1468. {
  1469. return $this->locationCompound;
  1470. }
  1471. /**
  1472. * Add nearestLocation.
  1473. *
  1474. * @return Location
  1475. */
  1476. public function addNearestLocation(self $nearestLocation)
  1477. {
  1478. if (!$this->nearestLocations->contains($nearestLocation)) {
  1479. $this->nearestLocations->add($nearestLocation);
  1480. }
  1481. return $this;
  1482. }
  1483. /**
  1484. * Remove nearestLocation.
  1485. *
  1486. * @return Location
  1487. */
  1488. public function removeNearestLocation(self $nearestLocation)
  1489. {
  1490. if ($this->nearestLocations->contains($nearestLocation)) {
  1491. $this->nearestLocations->removeElement($nearestLocation);
  1492. }
  1493. return $this;
  1494. }
  1495. /**
  1496. * Get nearestLocations.
  1497. *
  1498. * @return Collection
  1499. */
  1500. public function getNearestLocations()
  1501. {
  1502. return $this->nearestLocations;
  1503. }
  1504. /**
  1505. * Add interest.
  1506. *
  1507. * @return Location
  1508. */
  1509. public function addInterest(UserInterest $interest)
  1510. {
  1511. $this->interests[] = $interest;
  1512. return $this;
  1513. }
  1514. /**
  1515. * Remove interest.
  1516. */
  1517. public function removeInterest(UserInterest $interest): void
  1518. {
  1519. $this->interests->removeElement($interest);
  1520. }
  1521. /**
  1522. * Get interests.
  1523. *
  1524. * @return Collection
  1525. */
  1526. public function getInterests()
  1527. {
  1528. return $this->interests;
  1529. }
  1530. /**
  1531. * Get interests.
  1532. *
  1533. * @return UserInterest
  1534. */
  1535. public function getLiveInterests()
  1536. {
  1537. $criteria = Criteria::create()
  1538. ->andwhere(Criteria::expr()->eq('status', UserInterestStatus::LIVE));
  1539. return $this->interests->matching($criteria);
  1540. }
  1541. public function setTranslatableLocale($locale): void
  1542. {
  1543. $this->locale = $locale;
  1544. }
  1545. /**
  1546. * Add exchangeRequest.
  1547. *
  1548. * @return Location
  1549. */
  1550. public function addExchangeRequest(ExchangeRequest $exchangeRequest)
  1551. {
  1552. $this->exchangeRequests[] = $exchangeRequest;
  1553. return $this;
  1554. }
  1555. /**
  1556. * Remove exchangeRequest.
  1557. */
  1558. public function removeExchangeRequest(ExchangeRequest $exchangeRequest): void
  1559. {
  1560. $this->exchangeRequests->removeElement($exchangeRequest);
  1561. }
  1562. /**
  1563. * Get exchangeRequests.
  1564. *
  1565. * @return Collection
  1566. */
  1567. public function getExchangeRequests()
  1568. {
  1569. return $this->exchangeRequests;
  1570. }
  1571. public function setSearchTerms($searchTerms): void
  1572. {
  1573. $this->searchTerms = $searchTerms;
  1574. }
  1575. public function getSearchTerms()
  1576. {
  1577. return $this->searchTerms;
  1578. }
  1579. /**
  1580. * @return int
  1581. */
  1582. public function getLeadsCounter()
  1583. {
  1584. return $this->leadsCounter;
  1585. }
  1586. /**
  1587. * @param int $leadsCounter
  1588. */
  1589. public function setLeadsCounter($leadsCounter): void
  1590. {
  1591. $this->leadsCounter = $leadsCounter;
  1592. }
  1593. /**
  1594. * @return int
  1595. */
  1596. public function getListingsCounter()
  1597. {
  1598. return $this->listingsCounter;
  1599. }
  1600. /**
  1601. * @param int $listingsCounter
  1602. *
  1603. * @return Location
  1604. */
  1605. public function setListingsCounter($listingsCounter)
  1606. {
  1607. $this->listingsCounter = $listingsCounter;
  1608. return $this;
  1609. }
  1610. /**
  1611. * @return int
  1612. */
  1613. public function getLocationParentLabel()
  1614. {
  1615. $parent = $this->getParent() ? $this->getParent()->getTitle().' / ' : null;
  1616. return $parent.$this->getTitle();
  1617. }
  1618. /**
  1619. * @return int
  1620. */
  1621. public function getLastSlug()
  1622. {
  1623. $segments = explode('/', $this->slug);
  1624. return end($segments);
  1625. }
  1626. /**
  1627. * @return bool
  1628. */
  1629. #[Serializer\VirtualProperty]
  1630. #[Serializer\SerializedName('has_children')]
  1631. #[Serializer\Expose]
  1632. #[Serializer\Groups(['LocationFlat', 'AutocompleteV3', 'DefaultV4'])]
  1633. public function getHasChildren()
  1634. {
  1635. return $this->getChildren()->isEmpty() ? false : true;
  1636. }
  1637. /**
  1638. * @return string
  1639. */
  1640. #[Serializer\VirtualProperty]
  1641. #[Serializer\SerializedName('text')]
  1642. #[Serializer\Groups(['Autocomplete'])]
  1643. #[Serializer\Expose]
  1644. public function getText()
  1645. {
  1646. return $this->getTitle();
  1647. }
  1648. /**
  1649. * Get Title FullPath
  1650. * e.g. takes 90th street and returns Greater Cairo / New Cairo / 90th Street.
  1651. */
  1652. #[Serializer\VirtualProperty]
  1653. #[Serializer\SerializedName('title_full_path')]
  1654. #[Serializer\Groups(['Autocomplete', 'listingDetails', 'AutocompleteV3', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'SlugResolver', 'RelatedListingsV2', 'topAreasV2'])]
  1655. #[Serializer\Expose]
  1656. public function getTitleFullPath(): string
  1657. {
  1658. $location = $this;
  1659. $titlesFullPath[] = $this->getTitle();
  1660. while ($location = $location->getParent()) {
  1661. $titlesFullPath[] = $location->getTitle();
  1662. }
  1663. return implode(' / ', array_reverse($titlesFullPath ?? []));
  1664. }
  1665. /**
  1666. * Get searchable title keywords
  1667. * e.g. takes 90th street and returns Greater Cairo / New Cairo / 90th Street.
  1668. */
  1669. public function getSearchableTitle(): string
  1670. {
  1671. $location = $this;
  1672. $titlesFullPath = [];
  1673. $this->handleTitle($location, $titlesFullPath);
  1674. while ($location = $location->getParent()) {
  1675. $this->handleTitle($location, $titlesFullPath);
  1676. }
  1677. return implode(' / ', array_reverse($titlesFullPath ?? []));
  1678. }
  1679. /**
  1680. * Get Title FullPath started from children
  1681. * e.g. takes 90th street and returns Greater 90th Street - New Cairo - Cairo.
  1682. */
  1683. public function getTitleFullPathStartedFromChildren(): string
  1684. {
  1685. $location = $this;
  1686. $titlesFullPath[] = $this->getTitle();
  1687. while ($location = $location->getParent()) {
  1688. $titlesFullPath[] = $location->getTitle();
  1689. }
  1690. return implode(' - ', $titlesFullPath);
  1691. }
  1692. #[Serializer\VirtualProperty]
  1693. #[Serializer\Groups(['Autocomplete'])]
  1694. #[Serializer\Expose]
  1695. public function getTranslation(): array
  1696. {
  1697. $translations = [];
  1698. foreach ($this->getTranslations()->toArray() as $trans) {
  1699. $translations[$trans->getLocale()] = $trans->getContent();
  1700. }
  1701. return $translations;
  1702. }
  1703. /**
  1704. * @return string|null
  1705. */
  1706. public function getFullPath()
  1707. {
  1708. return $this->fullPath;
  1709. }
  1710. public function setFullPath(?string $fullPath = null): self
  1711. {
  1712. $this->fullPath = $fullPath;
  1713. return $this;
  1714. }
  1715. /**
  1716. * @return string
  1717. */
  1718. #[Serializer\VirtualProperty]
  1719. #[Serializer\SerializedName('name')]
  1720. #[Serializer\Groups(['AutocompleteV3', 'DefaultV4', 'SearchV4', 'UserFavoriteListings'])]
  1721. #[Serializer\Expose]
  1722. public function getName()
  1723. {
  1724. return $this->getTitle();
  1725. }
  1726. /**
  1727. * @return string
  1728. */
  1729. #[Serializer\VirtualProperty]
  1730. #[Serializer\SerializedName('latitude')]
  1731. #[Serializer\Groups(['AutocompleteV3', 'DefaultV4', 'ProjectDetailsV4'])]
  1732. #[Serializer\Expose]
  1733. public function getLatitude()
  1734. {
  1735. return $this->getLat();
  1736. }
  1737. /**
  1738. * @return string
  1739. */
  1740. #[Serializer\VirtualProperty]
  1741. #[Serializer\SerializedName('longitude')]
  1742. #[Serializer\Groups(['AutocompleteV3', 'DefaultV4', 'ProjectDetailsV4'])]
  1743. #[Serializer\Expose]
  1744. public function getLongitude()
  1745. {
  1746. return $this->getLon();
  1747. }
  1748. #[Serializer\VirtualProperty]
  1749. #[Serializer\Groups(['AutocompleteV3'])]
  1750. #[Serializer\SerializedName('translations')]
  1751. #[Serializer\Expose]
  1752. public function getLocationTranslations(): array
  1753. {
  1754. return $this->locationTranslations;
  1755. }
  1756. public function setLocationTranslations(array $translation): self
  1757. {
  1758. $this->locationTranslations = $translation;
  1759. return $this;
  1760. }
  1761. /**
  1762. * @return int|null
  1763. */
  1764. public function getReferenceId()
  1765. {
  1766. return $this->id;
  1767. }
  1768. /**
  1769. * @return self
  1770. */
  1771. public function setReferenceId(?int $referenceId)
  1772. {
  1773. $this->referenceId = $referenceId;
  1774. return $this;
  1775. }
  1776. /**
  1777. * @return int
  1778. */
  1779. #[Serializer\VirtualProperty]
  1780. #[Serializer\Groups(['DefaultV4'])]
  1781. #[Serializer\SerializedName('listingsCount')]
  1782. #[Serializer\Expose]
  1783. public function getListingsCount()
  1784. {
  1785. return $this->listingsCounter;
  1786. }
  1787. /**
  1788. * @return $this
  1789. */
  1790. public function setListingsCount(int $listingsCount): self
  1791. {
  1792. $this->listingsCounter = $listingsCount;
  1793. return $this;
  1794. }
  1795. #[Serializer\VirtualProperty]
  1796. #[Serializer\SerializedName('referenceId')]
  1797. #[Serializer\Expose]
  1798. #[Serializer\Groups(['DefaultV4', 'AutocompleteV3', 'SearchV4'])]
  1799. public function getReferencedV4Id()
  1800. {
  1801. return $this->getId();
  1802. }
  1803. /**
  1804. * @param array $translations
  1805. *
  1806. * @return self
  1807. */
  1808. public function setV4Translations($translations = [])
  1809. {
  1810. $this->v4Translations = $translations;
  1811. return $this;
  1812. }
  1813. /**
  1814. * Get translations.
  1815. *
  1816. * @return array
  1817. */
  1818. #[Serializer\VirtualProperty]
  1819. #[Serializer\Groups(['DefaultV4', 'MyListing', 'SearchV4'])]
  1820. #[Serializer\SerializedName('translations')]
  1821. #[Serializer\Expose]
  1822. public function getV4Translations()
  1823. {
  1824. return $this->v4Translations;
  1825. }
  1826. /**
  1827. * @return Location
  1828. */
  1829. public function setEligibleForMortgage(bool $eligibleForMortgage)
  1830. {
  1831. $this->eligibleForMortgage = $eligibleForMortgage;
  1832. return $this;
  1833. }
  1834. /**
  1835. * Get Eligible For Mortgage.
  1836. *
  1837. * @return bool
  1838. */
  1839. public function getEligibleForMortgage()
  1840. {
  1841. return $this->eligibleForMortgage;
  1842. }
  1843. /**
  1844. * Set isCompoundLocation.
  1845. *
  1846. * @param bool $isCompoundLocation
  1847. *
  1848. * @return Location
  1849. */
  1850. public function setIsCompoundLocation($isCompoundLocation)
  1851. {
  1852. $this->isCompoundLocation = $isCompoundLocation;
  1853. return $this;
  1854. }
  1855. /**
  1856. * Get isCompoundLocation.
  1857. *
  1858. * @return bool
  1859. */
  1860. public function getIsCompoundLocation()
  1861. {
  1862. return $this->isCompoundLocation;
  1863. }
  1864. /**
  1865. * Set showPrimaryOnly.
  1866. */
  1867. public function setShowPrimaryOnly(bool $showPrimaryOnly): self
  1868. {
  1869. $this->showPrimaryOnly = $showPrimaryOnly;
  1870. return $this;
  1871. }
  1872. /**
  1873. * Get showPrimaryOnly.
  1874. */
  1875. public function getShowPrimaryOnly(): bool
  1876. {
  1877. return $this->showPrimaryOnly;
  1878. }
  1879. /**
  1880. * @param self $location
  1881. * @param array &$titlesFullPath
  1882. */
  1883. private function handleTitle($location, &$titlesFullPath): void
  1884. {
  1885. $translations = $location->getTranslations() ? $location->getTranslations()->toArray() : [];
  1886. foreach ($translations as $trans) {
  1887. if ('en' == $trans->getLocale() && 'title' == $trans->getField()) {
  1888. $titlesFullPath[] = ucfirst((string) $trans->getContent());
  1889. }
  1890. }
  1891. $titlesFullPath[] = $location->getTitle();
  1892. }
  1893. private $listingOrNull;
  1894. #[Serializer\VirtualProperty]
  1895. #[Serializer\Groups(['SlugResolver', 'Compound', 'locationListingV2', 'homeCompoundV2', 'listingDetailsWithLocationCompound'])]
  1896. #[Serializer\SerializedName('compound_listing')]
  1897. #[Serializer\Expose]
  1898. public function getListingOrNull(): ?Listing
  1899. {
  1900. return $this->listingOrNull;
  1901. }
  1902. public function setListingOrNull(?Listing $listingOrNull): void
  1903. {
  1904. $this->listingOrNull = $listingOrNull;
  1905. }
  1906. public function getAlias(): string
  1907. {
  1908. return $this->alias;
  1909. }
  1910. public function setAlias(string $alias): void
  1911. {
  1912. $this->alias = $alias;
  1913. }
  1914. /**
  1915. * @return Collection|LocationTier[]
  1916. */
  1917. public function getLocationTiers(): Collection
  1918. {
  1919. return $this->tiers;
  1920. }
  1921. public function addLocationTier(LocationTier $tier): self
  1922. {
  1923. if (!$this->tiers->contains($tier)) {
  1924. $this->tiers[] = $tier;
  1925. }
  1926. return $this;
  1927. }
  1928. public function removeLocationTier(LocationTier $tier): self
  1929. {
  1930. $this->tiers->removeElement($tier);
  1931. return $this;
  1932. }
  1933. }