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