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