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