src/Aqarmap/Bundle/ListingBundle/Entity/Location.php line 50
<?php
namespace Aqarmap\Bundle\ListingBundle\Entity;
use Aqarmap\Bundle\DiscussionBundle\Entity\Discussion;
use Aqarmap\Bundle\ExchangeBundle\Entity\ExchangeRequest;
use Aqarmap\Bundle\ListingBundle\Constant\LocationTypes;
use Aqarmap\Bundle\ListingBundle\Constant\PhotoTypes;
use Aqarmap\Bundle\ListingBundle\Repository\LocationRepository;
use Aqarmap\Bundle\NeighborhoodBundle\Entity\LocationCompound;
use Aqarmap\Bundle\NeighborhoodBundle\Entity\LocationStatistics;
use Aqarmap\Bundle\NotifierBundle\Entity\Notifier;
use Aqarmap\Bundle\UserBundle\Constant\UserInterestStatus;
use Aqarmap\Bundle\UserBundle\Entity\UserInterest;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Sluggable\Handler\TreeSlugHandler;
use Gedmo\Translatable\Translatable;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Location.
*/
#[UniqueEntity('slug')]
#[ORM\Table(name: 'locations')]
#[ORM\Index(columns: ['disabled'])]
#[ORM\Index(columns: ['listings_counter'])]
#[ORM\Index(columns: ['searchable'])]
#[ORM\Index(columns: ['synced'])]
#[ORM\Index(columns: ['lat'])]
#[ORM\Index(columns: ['lon'])]
#[ORM\Index(columns: ['root'])]
#[ORM\Index(columns: ['root', '_left', '_right'])]
#[ORM\Index(columns: ['home_filter', 'is_compound_location', 'listing_id'])]
#[ORM\Entity(repositoryClass: LocationRepository::class)]
#[ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'write_rare')]
#[Gedmo\TranslationEntity(class: LocationTranslation::class)]
#[Gedmo\Tree(type: 'nested')]
#[Serializer\ExclusionPolicy('all')]
class Location implements Translatable, \Stringable
{
/**
* @var int
*/
#[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')]
#[Serializer\Groups(['Default', 'listingDetails', 'List', 'MiniList', 'Data', 'Autocomplete', 'Details', 'Neighborhood', 'NeighborhoodStatistics', 'Discussion', 'Exchange', 'LocationFlat', 'Search', 'AutocompleteV3', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'Translation', 'SlugResolver', 'RelatedListingsV2', 'locationListingV2', 'leadsBank'])]
#[Serializer\Expose]
private $id;
#[ORM\Column(name: 'title', type: 'string', length: 50)]
#[Gedmo\Translatable]
#[Serializer\Groups(['Default', 'listingDetails', 'List', 'MiniList', 'Data', 'Details', 'Neighborhood', 'NeighborhoodStatistics', 'Discussion', 'Exchange', 'LocationFlat', 'Search', 'Translation', 'SlugResolver', 'Autocomplete', 'MyLeads', 'leadsBank', 'LocationStatistics'])]
#[Serializer\Expose]
private string $title;
/**
* @var string
*/
#[ORM\Column(name: 'alias', type: 'string', length: 512, nullable: true)]
#[Gedmo\Translatable]
#[Serializer\Groups(['SlugResolver'])]
#[Serializer\Expose]
private $alias;
/**
* @var string
*/
#[ORM\Column(name: 'description', type: 'text', length: 512, nullable: true)]
#[Gedmo\Translatable]
#[Serializer\Groups(['Neighborhood'])]
#[Serializer\Expose]
private $description;
#[ORM\Column(length: 128, unique: true)]
#[Gedmo\Slug(fields: ['title'])]
#[Gedmo\SlugHandler(class: TreeSlugHandler::class, options: [
'parentRelationField' => 'parent',
'separator' => '/',
])]
private string $slug;
/**
* @var float
*/
#[ORM\Column(name: 'lat', type: 'float', nullable: true)]
#[Serializer\Groups(['DataJS'])]
#[Serializer\Since('v2.14')]
#[Serializer\Expose]
private $lat;
/**
* @var float
*/
#[ORM\Column(name: 'lon', type: 'float', nullable: true)]
#[Serializer\Groups(['DataJS'])]
#[Serializer\Since('v2.14')]
#[Serializer\Expose]
private $lon;
/**
* @var int
*/
#[ORM\Column(name: 'zoom', type: 'smallint', nullable: true)]
#[Serializer\Groups(['DataJS'])]
#[Serializer\Since('v2.14')]
#[Serializer\Expose]
private $zoom;
/**
* @var array
*/
#[ORM\Column(name: 'coordinates', type: 'array', nullable: true)]
private $coordinates;
#[ORM\Column(type: 'boolean')]
#[Serializer\Expose]
#[Serializer\Groups(['List', 'Data', 'Details', 'LocationFlat'])]
private $searchable;
#[ORM\Column(name: 'home_filter', type: 'boolean')]
#[Serializer\Expose]
#[Serializer\Groups(['Neighborhood'])]
private $homeFilter = false;
#[ORM\Column(name: 'statistics_filter', type: 'boolean')]
#[Serializer\Expose]
#[Serializer\Groups(['Neighborhood'])]
private $statisticsFilter = false;
#[ORM\Column(name: 'neighborhood_filter', type: 'boolean')]
#[Serializer\Expose]
#[Serializer\Groups(['Neighborhood'])]
private $neighborhoodFilter = false;
#[ORM\Column(name: 'compound_filter', type: 'boolean')]
private $compoundFilter = false;
#[ORM\Column(type: 'boolean')]
#[Serializer\Expose]
#[Serializer\Groups(['List', 'Data', 'Details', 'LocationFlat'])]
private $estimate = false;
#[ORM\Column(type: 'boolean')]
#[Serializer\Expose]
#[Serializer\Groups(['DefaultV4'])]
private $disabled = false;
#[ORM\Column(name: 'synced', type: 'boolean')]
private $synced = false;
#[ORM\Column(name: 'level', type: 'integer')]
#[Gedmo\TreeLevel]
#[Serializer\Expose]
#[Serializer\Groups(['List', 'Data', 'LocationFlat', 'DefaultV4', 'SlugResolver'])]
private $level;
#[ORM\Column(name: '_left', type: 'integer')]
#[Gedmo\TreeLeft]
private $left;
#[ORM\Column(name: '_right', type: 'integer')]
#[Gedmo\TreeRight]
private $right;
#[ORM\Column(name: 'root', type: 'integer', nullable: true)]
#[Gedmo\TreeRoot]
private $root;
#[ORM\ManyToOne(targetEntity: Location::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
#[Gedmo\TreeParent]
#[Serializer\Expose]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'SlugResolver', 'RelatedListingsV2', 'listingDetails'])]
#[Serializer\MaxDepth(1)]
private $parent;
#[ORM\OneToMany(targetEntity: Location::class, mappedBy: 'parent')]
#[ORM\OrderBy(['left' => 'ASC'])]
#[Serializer\Expose]
#[Serializer\Groups(['List'])]
#[Serializer\MaxDepth(2)]
#[Serializer\Accessor(getter: 'getChildren')]
private $children;
#[ORM\ManyToMany(targetEntity: Location::class, cascade: ['persist'])]
#[ORM\JoinTable(name: 'locations_nearestby', joinColumns: [new ORM\JoinColumn(name: 'nearest_location_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'location_id', referencedColumnName: 'id')])]
protected $nearestLocations;
#[ORM\OneToMany(targetEntity: LocationTranslation::class, mappedBy: 'object', cascade: ['persist', 'remove'])]
private $translations;
#[ORM\OneToMany(targetEntity: Listing::class, mappedBy: 'location')]
protected $listings;
#[ORM\ManyToMany(targetEntity: PropertyType::class)]
protected $propertyTypes;
#[ORM\OneToMany(targetEntity: \Aqarmap\Bundle\CRMBundle\Entity\Company::class, mappedBy: 'location')]
protected $companies;
#[ORM\OneToMany(targetEntity: LocationSupplyDemand::class, mappedBy: 'location')]
protected $locationSupplyDemand;
#[ORM\OneToMany(targetEntity: Notifier::class, mappedBy: 'location')]
protected $notifiers;
#[ORM\OneToMany(targetEntity: UserInterest::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
protected $interests;
#[ORM\OneToMany(targetEntity: Rule::class, mappedBy: 'location')]
protected $rules;
#[ORM\OneToMany(targetEntity: LocationPhoto::class, mappedBy: 'location', cascade: ['persist', 'remove'])]
#[Serializer\Expose]
#[Serializer\Groups(['Neighborhood'])]
protected $photos;
#[ORM\OneToMany(targetEntity: LocationStatistics::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
#[Serializer\Expose]
#[Serializer\Groups(['Neighborhood'])]
protected $locationStatistics;
#[ORM\OneToOne(targetEntity: LocationCompound::class, cascade: ['persist', 'remove'], mappedBy: 'location')]
#[ORM\JoinColumn(name: 'location_compound_id', referencedColumnName: 'id')]
protected $locationCompound;
#[ORM\OneToMany(targetEntity: Discussion::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
protected $discussions;
#[ORM\OneToMany(targetEntity: ExchangeRequest::class, mappedBy: 'location', fetch: 'EXTRA_LAZY')]
protected $exchangeRequests;
#[ORM\OneToOne(targetEntity: LocationRating::class, cascade: ['persist', 'remove'])]
#[Serializer\Expose]
#[Serializer\Groups(['Neighborhood'])]
protected $rating;
#[ORM\ManyToOne(targetEntity: Listing::class, cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(name: 'listing_id', referencedColumnName: 'id', nullable: true)]
#[Serializer\Expose]
#[Serializer\Groups(['Autocomplete'])]
protected $listing;
#[ORM\OneToMany(targetEntity: SearchTerm::class, mappedBy: 'location')]
protected $searchTerms;
#[Gedmo\Locale] // Used locale to override Translation listener`s locale
private $locale;
/**
* @var int
* Count number of leads for live listings
*/
#[ORM\Column(name: 'leads_counter', type: 'integer', options: ['default' => 0])]
#[Serializer\Groups(['Api'])]
#[Serializer\Expose]
private $leadsCounter = 0;
/**
* @var int
* Count number of live listings
*/
#[ORM\Column(name: 'listings_counter', type: 'integer', options: ['default' => 0])]
#[Serializer\Groups(['Api', 'RelatedResults', 'MiniList'])]
#[Serializer\Expose]
private $listingsCounter = 0;
/**
* Project File.
*/
protected $file;
#[ORM\Column(name: 'keyword', type: 'text', nullable: true)]
private $keyword;
private $location;
#[ORM\OneToMany(targetEntity: \Aqarmap\Bundle\ValueEngineBundle\Entity\ListingInsight::class, mappedBy: 'location')]
protected $listingInsights;
/**
* @var string
*/
#[ORM\Column(name: 'full_path', type: 'text', nullable: true)]
private $fullPath;
#[ORM\Column(name: 'reference_id', type: 'integer', nullable: true)]
private $referenceId;
/**
* @var string
*/
#[ORM\Column(name: 'type', type: 'string', length: 50)]
#[Serializer\Groups(['listingDetails', 'listingDetailsWithLocationCompound'])]
#[Serializer\Expose]
private $type;
/**
* @var array
*/
private $locationTranslations = [];
/**
* @var array
*/
private $v4Translations = [];
#[ORM\Column(name: 'eligible_for_mortgage', type: 'boolean')]
#[Serializer\Groups(['listingDetails', 'listingDetailsWithLocationCompound'])]
#[Serializer\Expose]
protected $eligibleForMortgage = false;
#[ORM\Column(name: 'is_compound_location', type: 'boolean')]
#[Serializer\Expose]
#[Serializer\Groups(['Autocomplete', 'List', 'Data', 'Details', 'LocationFlat', 'AutocompleteV3', 'Compound', 'SlugResolver'])]
private $isCompoundLocation = false;
#[ORM\OneToMany(targetEntity: Location::class, mappedBy: 'parent')]
#[ORM\OrderBy(['id' => 'ASC'])]
#[Serializer\Expose]
#[Serializer\Groups(['Data'])]
#[Serializer\MaxDepth(2)]
#[Serializer\Accessor(getter: 'getChildrenSortedById')]
#[Serializer\SerializedName('children')]
private $childrenSortedById;
#[Serializer\VirtualProperty]
public function getLocation()
{
return $this->location;
}
public function getKeyword()
{
return $this->keyword;
}
/**
* @param mixed $keyword
*/
public function setKeyword(string $keyword): self
{
$this->keyword = $this->getKeyword() ? $this->getKeyword().','.$keyword : $keyword;
return $this;
}
public function removeKeyword(string $keyword): self
{
$newKeyword = array_diff(explode(',', (string) $this->getKeyword()), [$keyword]);
$this->keyword = implode(',', $newKeyword) ?? null;
return $this;
}
public function getFile()
{
return $this->file;
}
public function setFile($file): void
{
$this->file = $file;
}
/**
* Constructor.
*/
public function __construct()
{
$this->children = new ArrayCollection();
$this->translations = new ArrayCollection();
$this->listings = new ArrayCollection();
$this->notifiers = new ArrayCollection();
$this->rules = new ArrayCollection();
$this->locationStatistics = new ArrayCollection();
$this->photos = new ArrayCollection();
$this->discussions = new ArrayCollection();
$this->propertyTypes = new ArrayCollection();
$this->nearestLocations = new ArrayCollection();
$this->interests = new ArrayCollection();
$this->exchangeRequests = new ArrayCollection();
}
// ---------------------------------------------------------------------
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
// ---------------------------------------------------------------------
/**
* Set title.
*
* @param string $title
*
* @return Location
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title.
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Get short path title (ie: New Cairo - 90th Street).
*/
public function getTitleShortPath(): string
{
$neighbourhood = $this->getParentByType(LocationTypes::NEIGHBORHOOD, true);
if ($neighbourhood) {
return $this->getTitle().' - '.$neighbourhood->getTitle();
}
return $this->getTitle();
}
/**
* @return string
*/
public function getIndentedTitle()
{
return str_repeat('--', $this->getLevel()).' '.$this->getTitle();
}
// ---------------------------------------------------------------------
/**
* Set description.
*
* @param string $description
*
* @return Location
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description.
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
// ---------------------------------------------------------------------
/**
* Set slug.
*
* @param string $slug
*
* @return Location
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug.
*
* @return string
*/
public function getSlug()
{
return $this->slug;
}
// ---------------------------------------------------------------------
/**
* Set centerLat.
*
* @param float $centerLat
*
* @return Location
*/
public function setCenterLat($centerLat)
{
return $this->setLat($centerLat);
}
/**
* @return float
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Map', 'Details', 'Neighborhood', 'LocationFlat', 'Autocomplete'])]
#[Serializer\SerializedName('center_lat')]
#[Serializer\Until('v2.13')]
#[Serializer\Expose]
public function getCenterLat()
{
return $this->getLat();
}
/**
* @param float $latitude
*
* @return Location
*/
public function setLat($latitude)
{
$this->lat = $latitude;
return $this;
}
/**
* @return float|null
*/
public function getLat()
{
if (!$this->lat) {
return null;
}
return (float) $this->lat;
}
// ---------------------------------------------------------------------
/**
* Set lon.
*
* @deprecated
*
* @param float $lon
*
* @return Location
*/
public function setCenterLng($lon)
{
return $this->setLon($lon);
}
/**
* @deprecated
*
* @return float|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Map', 'Details', 'Neighborhood', 'LocationFlat', 'Autocomplete'])]
#[Serializer\SerializedName('center_lng')]
#[Serializer\Until('v2.13')]
#[Serializer\Expose]
public function getCenterLng()
{
return $this->getLon();
}
/**
* @param float $longitude
*
* @return Location
*/
public function setLon($longitude)
{
$this->lon = $longitude;
return $this;
}
/**
* @return float|null
*/
public function getLon()
{
if (!$this->lon) {
return null;
}
return (float) $this->lon;
}
// ---------------------------------------------------------------------
/**
* Set zoom.
*
* @deprecated
*
* @param int $zoom
*
* @return Location
*/
public function setZoomLevel($zoom)
{
return $this->setZoom($zoom);
}
/**
* @deprecated
*
* @return int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Map', 'Details', 'Neighborhood', 'LocationFlat', 'Autocomplete', 'AutocompleteV3', 'DefaultV4'])]
#[Serializer\SerializedName('zoom_level')]
#[Serializer\Until('v2.13')]
#[Serializer\Expose]
public function getZoomLevel()
{
return $this->getZoom();
}
public function setZoom(?int $level): self
{
$this->zoom = $level;
return $this;
}
/**
* @return int|null
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('zoom')]
#[Serializer\Groups(['DataJS'])]
public function getZoom()
{
return $this->zoom;
}
// ---------------------------------------------------------------------
/**
* Set coordinates.
*
* @param array $coordinates
*
* @return Location
*/
public function setCoordinates($coordinates)
{
$this->coordinates = $coordinates;
return $this;
}
/**
* Get coordinates.
*
* @return array
*/
public function getCoordinates()
{
return $this->coordinates;
}
// ---------------------------------------------------------------------
/**
* Set searchable.
*
* @param bool $searchable
*
* @return Location
*/
public function setSearchable($searchable)
{
$this->searchable = $searchable;
return $this;
}
/**
* Get searchable.
*
* @return bool
*/
public function getSearchable()
{
return $this->searchable;
}
// ---------------------------------------------------------------------
/**
* Set homeFilter.
*
* @param bool $homeFilter
*
* @return Location
*/
public function setHomeFilter($homeFilter)
{
$this->homeFilter = $homeFilter;
return $this;
}
/**
* Get homeFilter.
*
* @return bool
*/
public function getHomeFilter()
{
return $this->homeFilter;
}
// ---------------------------------------------------------------------
/**
* Set estimate.
*
* @param bool $estimate
*
* @return Location
*/
public function setEstimate($estimate)
{
$this->estimate = $estimate;
return $this;
}
/**
* Get estimate.
*
* @return bool
*/
public function getEstimate()
{
return $this->estimate;
}
// ---------------------------------------------------------------------
/**
* Set disabled.
*
* @param bool $disabled
*
* @return Location
*/
public function setDisabled($disabled)
{
$this->disabled = $disabled;
return $this;
}
/**
* Get disabled.
*
* @return bool
*/
public function getDisabled()
{
return $this->disabled;
}
// ---------------------------------------------------------------------
/**
* Set parent.
*
* @return Location
*/
public function setParent(?self $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Get parent.
*
* @return Location
*/
public function getParent()
{
return $this->parent;
}
// ---------------------------------------------------------------------
/**
* Add children.
*
* @return Location
*/
public function addChild(self $children)
{
$this->children[] = $children;
return $this;
}
/**
* Remove children.
*/
public function removeChild(self $children): void
{
$this->children->removeElement($children);
}
/**
* Get children.
*
* @return Collection
*/
public function getChildren()
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('disabled', false));
return $this->children->matching($criteria);
}
/**
* Get children sorted by id.
*
* @return Collection
*/
public function getChildrenSortedById($filters = [])
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('disabled', false));
if (isset($filters['neighborhoodFilter'])) {
$criteria->andWhere(Criteria::expr()->eq('neighborhoodFilter', $filters['neighborhoodFilter']));
}
return $this->childrenSortedById->matching($criteria);
}
/**
* Get children.
*
* @return Collection
*/
public function getChildrenArray()
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('disabled', false));
return $this->children->matching($criteria)->toArray();
}
/**
* Get neighborhoodchildren.
*
* @return Collection
*/
public function getNeighborhoodChildren()
{
$criteria = Criteria::create()
->andWhere(Criteria::expr()->eq('disabled', false))
->andWhere(Criteria::expr()->eq('neighborhoodFilter', true));
return $this->children->matching($criteria);
}
/**
* Get leveled children.
*
* @return Collection
*/
public function getLeveledChildren()
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('disabled', false))
->where(Criteria::expr()->lte('level', 2));
return $this->children->matching($criteria);
}
/**
* Set type.
*
* @param string $type
*
* @return Location
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Get type.
*
* @return string
*/
public function getType()
{
return $this->type;
}
public function getTypeLabel(): ?string
{
return LocationTypes::getLabel($this->getType());
}
// ---------------------------------------------------------------------
/**
* Get translations.
*
* @return ArrayCollection
*/
public function getTranslations()
{
return $this->translations;
}
/**
* Add translation.
*
* @return Location
*/
public function addTranslation(LocationTranslation $translation)
{
if (!$this->translations->contains($translation)) {
$this->translations->add($translation);
$translation->setObject($this);
}
return $this;
}
/**
* Remove translation.
*
* @return Location
*/
public function removeTranslation(LocationTranslation $translation)
{
if ($this->translations->contains($translation)) {
$this->translations->removeElement($translation);
}
return $this;
}
// ---------------------------------------------------------------------
/**
* Add listings.
*
* @return Location
*/
public function addListing(Listing $listings)
{
$this->listings[] = $listings;
return $this;
}
/**
* Remove listings.
*/
public function removeListing(Listing $listings): void
{
$this->listings->removeElement($listings);
}
/**
* Get listings.
*
* @return Collection
*/
public function getListings()
{
return $this->listings;
}
// ---------------------------------------------------------------------
/**
* Add notifiers.
*
* @return Location
*/
public function addNotifier(Notifier $notifiers)
{
$this->notifiers[] = $notifiers;
return $this;
}
/**
* Remove notifiers.
*/
public function removeNotifier(Notifier $notifiers): void
{
$this->notifiers->removeElement($notifiers);
}
/**
* Get notifiers.
*
* @return Collection
*/
public function getNotifiers()
{
return $this->notifiers;
}
// ---------------------------------------------------------------------
/**
* Add rules.
*
* @return Location
*/
public function addRule(Rule $rules)
{
$this->rules[] = $rules;
return $this;
}
/**
* Remove rules.
*/
public function removeRule(Rule $rules): void
{
$this->rules->removeElement($rules);
}
/**
* Get rules.
*
* @return Collection
*/
public function getRules()
{
return $this->rules;
}
// ---------------------------------------------------------------------
/**
* Get Nearest Searchable Location.
*/
public function getNearestSearchable()
{
$location = $this;
while ($location && !$location->getSearchable()) {
$location = $location->getParent();
}
if (!$location) {
return $this;
}
return $location;
}
// -----------------------------------------------------------------------------
/**
* Get Nearest Neighborhood Parent.
*/
public function getNearestNeighborhood()
{
$location = $this;
while (
!$location->getNeighborhoodFilter()
&& $location->getParent()
&& 0 != $location->getParent()->getLevel()
) {
$location = $location->getParent();
}
if (!$location->getNeighborhoodFilter() || 0 == $location->getLevel()) {
return;
}
return $location;
}
/**
* Get Nearest Location Custom Level .
*
* @param int $level
*
* @return Location
*/
public function getNearestLeveledLocation($level = 1)
{
$location = $this;
if (\in_array($location->getLevel(), [0, $level])) {
return $location;
}
while ($location->getParent() && 0 != $location->getParent()->getLevel()) {
$location = $location->getParent();
}
return $location;
}
/**
* Get the nearest parent with the provided location type.
*/
public function getParentByType(string $locationType, bool $rootFallback = false): ?self
{
$location = $this->getParent();
$root = null;
while ($location) {
if ($location->getType() === $locationType) {
return $location;
}
$root = $location;
$location = $location->getParent();
}
return $rootFallback ? $root : null;
}
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('parent')]
#[Serializer\Expose]
#[Serializer\Groups(['LocationFlat'])]
public function getVirtualParent()
{
$parent = $this->getParent();
if ($parent) {
return [
'id' => $parent->getId(),
'title' => $parent->getTitle(),
];
}
return null;
}
/**
* Gets parent by level.
*
* @param int $level
*
* @return Location|null
*/
public function getLeveledParent($level = 1)
{
$location = $this;
while ($location = $location->getParent()) {
if ($location->getLevel() == $level) {
return $location;
}
}
return null;
}
/**
* Get Nearest Location Custom Level .
*
* @return Location
*/
public function getFirstParent()
{
$location = $this;
if (0 == $location->getLevel()) {
return $location;
}
while ($location = $location->getParent()) {
if (0 == $location->getLevel()) {
return $location;
}
}
return $location;
}
/**
* Set level.
*
* @param int $level
*
* @return Location
*/
public function setLevel($level)
{
$this->level = $level;
return $this;
}
/**
* Get level.
*
* @return int
*/
public function getLevel()
{
return $this->level;
}
/**
* Set left.
*
* @param int $left
*
* @return Location
*/
public function setLeft($left)
{
$this->left = $left;
return $this;
}
/**
* Get left.
*
* @return int
*/
public function getLeft()
{
return $this->left;
}
/**
* Set right.
*
* @param int $right
*
* @return Location
*/
public function setRight($right)
{
$this->right = $right;
return $this;
}
/**
* Get right.
*
* @return int
*/
public function getRight()
{
return $this->right;
}
/**
* Set root.
*
* @param int $root
*
* @return Location
*/
public function setRoot($root)
{
$this->root = $root;
return $this;
}
/**
* Get root.
*
* @return int
*/
public function getRoot()
{
return $this->root;
}
/**
* Add locationSupplyDemand.
*
* @return Location
*/
public function addLocationSupplyDemand(LocationSupplyDemand $locationSupplyDemand)
{
$this->locationSupplyDemand[] = $locationSupplyDemand;
return $this;
}
/**
* Remove locationSupplyDemand.
*/
public function removeLocationSupplyDemand(LocationSupplyDemand $locationSupplyDemand): void
{
$this->locationSupplyDemand->removeElement($locationSupplyDemand);
}
/**
* Get locationSupplyDemand.
*
* @return Collection
*/
public function getLocationSupplyDemand()
{
return $this->locationSupplyDemand;
}
// ---------------------------------------------------------------------
/**
* Add photos.
*
* @return Location
*/
public function addPhoto(LocationPhoto $photo)
{
$photo->setLocation($this);
$this->photos[] = $photo;
return $this;
}
/**
* Set photos.
*
* @return Location
*/
public function setPhotos($photos)
{
foreach ($photos as $photo) {
$this->addPhoto($photo);
}
return $this;
}
/**
* Remove photos.
*/
public function removePhoto(LocationPhoto $photo): void
{
$this->photos->removeElement($photo);
}
/**
* @return ArrayCollection
*/
public function getPhotos()
{
return $this->photos;
}
/**
* @return mixed|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Default', 'LocationFlat'])]
public function getMainPhoto()
{
// Important for API
if ($this->getPhotos()->count() <= 0) {
return;
}
/* @var Photo $photo */
$mainPhoto = $this->photos->filter(fn ($photo) => PhotoTypes::MAIN_PHOTO == $photo->getType());
return $mainPhoto->first() ?: $this->getPhotos()->first();
}
// ---------------------------------------------------------------------
public function __clone()
{
$this->id = null;
}
public function __toString(): string
{
return $this->title;
}
/**
* Set rating.
*
* @return Location
*/
public function setRating(?LocationRating $rating = null)
{
$this->rating = $rating;
$this->rating->setLocation($this);
return $this;
}
/**
* Get rating.
*
* @return LocationRating
*/
public function getRating()
{
return $this->rating;
}
/**
* Get rating of the nearest parent location that has one.
*/
public function getNearestRating()
{
$location = $this;
while ($location) {
$rating = $location->getRating();
if (
$rating
&& null !== $rating->getOverall()
&& LocationTypes::CITY !== $location->getType()
) {
return $rating;
}
$location = $location->getParent();
}
return null;
}
/**
* Set neighborhoodFilter.
*
* @param bool $neighborhoodFilter
*
* @return Location
*/
public function setNeighborhoodFilter($neighborhoodFilter)
{
$this->neighborhoodFilter = $neighborhoodFilter;
return $this;
}
/**
* Get neighborhoodFilter.
*
* @return bool
*/
public function getNeighborhoodFilter()
{
return $this->neighborhoodFilter;
}
/**
* Add locationStatistic.
*
* @return Location
*/
public function addLocationStatistic(LocationStatistics $locationStatistic)
{
$this->locationStatistics[] = $locationStatistic;
return $this;
}
/**
* Remove locationStatistic.
*/
public function removeLocationStatistic(LocationStatistics $locationStatistic): void
{
$this->locationStatistics->removeElement($locationStatistic);
}
/**
* Get locationStatistics.
*
* @return Collection
*/
public function getLocationStatistics()
{
return $this->locationStatistics;
}
/**
* Get lowest Average Price.
*
* @return LocationStatistics $locationStatistic
*/
public function getSingleStatistics(?PropertyType $propertyType = null)
{
$criteria = Criteria::create()
->andWhere(Criteria::expr()->neq('avgPrice', null))
->andWhere(Criteria::expr()->gt('avgPrice', 0))
->orderBy(['avgPrice' => Criteria::ASC]);
if ($propertyType) {
$criteria
->andWhere(Criteria::expr()->eq('propertyType', $propertyType));
}
return $this->locationStatistics->matching($criteria)->first();
}
/**
* Set statisticsFilter.
*
* @param bool $statisticsFilter
*
* @return Location
*/
public function setStatisticsFilter($statisticsFilter)
{
$this->statisticsFilter = $statisticsFilter;
return $this;
}
/**
* Get statisticsFilter.
*
* @return bool
*/
public function getStatisticsFilter()
{
return $this->statisticsFilter;
}
/**
* Add company.
*
* @return Location
*/
public function addCompany(\Aqarmap\Bundle\CRMBundle\Entity\Company $company)
{
$this->companies[] = $company;
return $this;
}
/**
* Remove company.
*/
public function removeCompany(\Aqarmap\Bundle\CRMBundle\Entity\Company $company): void
{
$this->companies->removeElement($company);
}
/**
* Get companies.
*
* @return Collection
*/
public function getCompanies()
{
return $this->companies;
}
/**
* Add discussion.
*
* @return Location
*/
public function addDiscussion(Discussion $discussion)
{
$this->discussions[] = $discussion;
return $this;
}
/**
* Remove discussion.
*/
public function removeDiscussion(Discussion $discussion): void
{
$this->discussions->removeElement($discussion);
}
/**
* Get discussions.
*
* @return Collection
*/
public function getDiscussions()
{
return $this->discussions;
}
/**
* Set compoundFilter.
*
* @param bool $compoundFilter
*
* @return Location
*/
public function setCompoundFilter($compoundFilter)
{
$this->compoundFilter = $compoundFilter;
return $this;
}
/**
* Get compoundFilter.
*
* @return bool
*/
public function getCompoundFilter()
{
return $this->compoundFilter;
}
/**
* Add propertyType.
*
* @return Location
*/
public function addPropertyType(PropertyType $propertyType)
{
$this->propertyTypes[] = $propertyType;
return $this;
}
/**
* Remove propertyType.
*/
public function removePropertyType(PropertyType $propertyType): void
{
$this->propertyTypes->removeElement($propertyType);
}
/**
* Get propertyTypes.
*
* @return Collection
*/
public function getPropertyTypes()
{
return $this->propertyTypes;
}
/**
* Set listing.
*
* @return Location
*/
public function setListing(?Listing $listing = null)
{
$this->listing = $listing;
return $this;
}
/**
* Set listing.
*
* @return Location
*/
public function setListings(array $listings = [])
{
$this->listings = $listings;
return $this;
}
/**
* Get listing.
*
* @return Listing
*/
public function getListing()
{
return $this->listing;
}
/**
* Set locationCompound.
*
* @return Location
*/
public function setLocationCompound(?LocationCompound $locationCompound = null)
{
$this->locationCompound = $locationCompound;
$this->locationCompound->setLocation($this);
return $this;
}
/**
* Get locationCompound.
*
* @return LocationCompound
*/
public function getLocationCompound()
{
return $this->locationCompound;
}
/**
* Add nearestLocation.
*
* @return Location
*/
public function addNearestLocation(self $nearestLocation)
{
if (!$this->nearestLocations->contains($nearestLocation)) {
$this->nearestLocations->add($nearestLocation);
}
return $this;
}
/**
* Remove nearestLocation.
*
* @return Location
*/
public function removeNearestLocation(self $nearestLocation)
{
if ($this->nearestLocations->contains($nearestLocation)) {
$this->nearestLocations->removeElement($nearestLocation);
}
return $this;
}
/**
* Get nearestLocations.
*
* @return Collection
*/
public function getNearestLocations()
{
return $this->nearestLocations;
}
/**
* Add interest.
*
* @return Location
*/
public function addInterest(UserInterest $interest)
{
$this->interests[] = $interest;
return $this;
}
/**
* Remove interest.
*/
public function removeInterest(UserInterest $interest): void
{
$this->interests->removeElement($interest);
}
/**
* Get interests.
*
* @return Collection
*/
public function getInterests()
{
return $this->interests;
}
/**
* Get interests.
*
* @return UserInterest
*/
public function getLiveInterests()
{
$criteria = Criteria::create()
->andwhere(Criteria::expr()->eq('status', UserInterestStatus::LIVE));
return $this->interests->matching($criteria);
}
public function setTranslatableLocale($locale): void
{
$this->locale = $locale;
}
/**
* Add exchangeRequest.
*
* @return Location
*/
public function addExchangeRequest(ExchangeRequest $exchangeRequest)
{
$this->exchangeRequests[] = $exchangeRequest;
return $this;
}
/**
* Remove exchangeRequest.
*/
public function removeExchangeRequest(ExchangeRequest $exchangeRequest): void
{
$this->exchangeRequests->removeElement($exchangeRequest);
}
/**
* Get exchangeRequests.
*
* @return Collection
*/
public function getExchangeRequests()
{
return $this->exchangeRequests;
}
public function setSearchTerms($searchTerms): void
{
$this->searchTerms = $searchTerms;
}
public function getSearchTerms()
{
return $this->searchTerms;
}
/**
* @return int
*/
public function getLeadsCounter()
{
return $this->leadsCounter;
}
/**
* @param int $leadsCounter
*/
public function setLeadsCounter($leadsCounter): void
{
$this->leadsCounter = $leadsCounter;
}
/**
* @return int
*/
public function getListingsCounter()
{
return $this->listingsCounter;
}
/**
* @param int $listingsCounter
*
* @return Location
*/
public function setListingsCounter($listingsCounter)
{
$this->listingsCounter = $listingsCounter;
return $this;
}
/**
* @return int
*/
public function getLocationParentLabel()
{
$parent = $this->getParent() ? $this->getParent()->getTitle().' / ' : null;
return $parent.$this->getTitle();
}
/**
* @return int
*/
public function getLastSlug()
{
$segments = explode('/', $this->slug);
return end($segments);
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('has_children')]
#[Serializer\Expose]
#[Serializer\Groups(['LocationFlat', 'AutocompleteV3', 'DefaultV4'])]
public function getHasChildren()
{
return $this->getChildren()->isEmpty() ? false : true;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('text')]
#[Serializer\Groups(['Autocomplete'])]
#[Serializer\Expose]
public function getText()
{
return $this->getTitle();
}
/**
* Get Title FullPath
* e.g. takes 90th street and returns Greater Cairo / New Cairo / 90th Street.
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('title_full_path')]
#[Serializer\Groups(['Autocomplete', 'listingDetails', 'AutocompleteV3', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'SlugResolver', 'RelatedListingsV2'])]
#[Serializer\Expose]
public function getTitleFullPath(): string
{
$location = $this;
$titlesFullPath[] = $this->getTitle();
while ($location = $location->getParent()) {
$titlesFullPath[] = $location->getTitle();
}
return implode(' / ', array_reverse($titlesFullPath ?? []));
}
/**
* Get searchable title keywords
* e.g. takes 90th street and returns Greater Cairo / New Cairo / 90th Street.
*/
public function getSearchableTitle(): string
{
$location = $this;
$titlesFullPath = [];
$this->handleTitle($location, $titlesFullPath);
while ($location = $location->getParent()) {
$this->handleTitle($location, $titlesFullPath);
}
return implode(' / ', array_reverse($titlesFullPath ?? []));
}
/**
* Get Title FullPath started from children
* e.g. takes 90th street and returns Greater 90th Street - New Cairo - Cairo.
*/
public function getTitleFullPathStartedFromChildren(): string
{
$location = $this;
$titlesFullPath[] = $this->getTitle();
while ($location = $location->getParent()) {
$titlesFullPath[] = $location->getTitle();
}
return implode(' - ', $titlesFullPath);
}
/**
* @return Location
*/
public function setSynced($synced)
{
$this->synced = $synced;
return $this;
}
public function getSynced()
{
return $this->synced;
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Autocomplete'])]
#[Serializer\Expose]
public function getTranslation(): array
{
$translations = [];
foreach ($this->getTranslations()->toArray() as $trans) {
$translations[$trans->getLocale()] = $trans->getContent();
}
return $translations;
}
/**
* @return string|null
*/
public function getFullPath()
{
return $this->fullPath;
}
public function setFullPath(?string $fullPath = null): self
{
$this->fullPath = $fullPath;
return $this;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('name')]
#[Serializer\Groups(['AutocompleteV3', 'DefaultV4', 'SearchV4'])]
#[Serializer\Expose]
public function getName()
{
return $this->getTitle();
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('latitude')]
#[Serializer\Groups(['AutocompleteV3', 'DefaultV4', 'ProjectDetailsV4'])]
#[Serializer\Expose]
public function getLatitude()
{
return $this->getLat();
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('longitude')]
#[Serializer\Groups(['AutocompleteV3', 'DefaultV4', 'ProjectDetailsV4'])]
#[Serializer\Expose]
public function getLongitude()
{
return $this->getLon();
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['AutocompleteV3'])]
#[Serializer\SerializedName('translations')]
#[Serializer\Expose]
public function getLocationTranslations(): array
{
return $this->locationTranslations;
}
public function setLocationTranslations(array $translation): self
{
$this->locationTranslations = $translation;
return $this;
}
/**
* @return int|null
*/
public function getReferenceId()
{
return $this->id;
}
/**
* @return self
*/
public function setReferenceId(?int $referenceId)
{
$this->referenceId = $referenceId;
return $this;
}
/**
* @return int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4'])]
#[Serializer\SerializedName('listingsCount')]
#[Serializer\Expose]
public function getListingsCount()
{
return $this->listingsCounter;
}
/**
* @return $this
*/
public function setListingsCount(int $listingsCount): self
{
$this->listingsCounter = $listingsCount;
return $this;
}
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('referenceId')]
#[Serializer\Expose]
#[Serializer\Groups(['DefaultV4', 'AutocompleteV3', 'SearchV4'])]
public function getReferencedV4Id()
{
return $this->getId();
}
/**
* @param array $translations
*
* @return self
*/
public function setV4Translations($translations = [])
{
$this->v4Translations = $translations;
return $this;
}
/**
* Get translations.
*
* @return array
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'MyListing', 'SearchV4'])]
#[Serializer\SerializedName('translations')]
#[Serializer\Expose]
public function getV4Translations()
{
return $this->v4Translations;
}
/**
* @return Location
*/
public function setEligibleForMortgage(bool $eligibleForMortgage)
{
$this->eligibleForMortgage = $eligibleForMortgage;
return $this;
}
/**
* Get Eligible For Mortgage.
*
* @return bool
*/
public function getEligibleForMortgage()
{
return $this->eligibleForMortgage;
}
/**
* Set isCompoundLocation.
*
* @param bool $isCompoundLocation
*
* @return Location
*/
public function setIsCompoundLocation($isCompoundLocation)
{
$this->isCompoundLocation = $isCompoundLocation;
return $this;
}
/**
* Get isCompoundLocation.
*
* @return bool
*/
public function getIsCompoundLocation()
{
return $this->isCompoundLocation;
}
/**
* @param self $location
* @param array &$titlesFullPath
*/
private function handleTitle($location, &$titlesFullPath): void
{
$translations = $location->getTranslations() ? $location->getTranslations()->toArray() : [];
foreach ($translations as $trans) {
if ('en' == $trans->getLocale() && 'title' == $trans->getField()) {
$titlesFullPath[] = ucfirst((string) $trans->getContent());
}
}
$titlesFullPath[] = $location->getTitle();
}
private $listingOrNull;
#[Serializer\VirtualProperty]
#[Serializer\Groups(['SlugResolver', 'Compound', 'locationListingV2', 'homeCompoundV2', 'listingDetailsWithLocationCompound'])]
#[Serializer\SerializedName('compound_listing')]
#[Serializer\Expose]
public function getListingOrNull(): ?Listing
{
return $this->listingOrNull;
}
public function setListingOrNull(?Listing $listingOrNull): void
{
$this->listingOrNull = $listingOrNull;
}
public function getAlias(): string
{
return $this->alias;
}
public function setAlias(string $alias): void
{
$this->alias = $alias;
}
}