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

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