src/Aqarmap/Bundle/ListingBundle/Entity/Listing.php line 80
<?php
namespace Aqarmap\Bundle\ListingBundle\Entity;
use Aqarmap\Bundle\FinancialAidsBundle\Entity\FinancialAid;
use Aqarmap\Bundle\ListingBundle\Constant\CompoundStatus;
use Aqarmap\Bundle\ListingBundle\Constant\EligibleForMortgageData;
use Aqarmap\Bundle\ListingBundle\Constant\ListingCategories;
use Aqarmap\Bundle\ListingBundle\Constant\ListingCustomFields;
use Aqarmap\Bundle\ListingBundle\Constant\ListingFeaturedTypes;
use Aqarmap\Bundle\ListingBundle\Constant\ListingFeatures;
use Aqarmap\Bundle\ListingBundle\Constant\ListingPaymentMethod;
use Aqarmap\Bundle\ListingBundle\Constant\ListingPriceLevel;
use Aqarmap\Bundle\ListingBundle\Constant\ListingPropertyView;
use Aqarmap\Bundle\ListingBundle\Constant\ListingRateConstant;
use Aqarmap\Bundle\ListingBundle\Constant\ListingRateReviewStatus;
use Aqarmap\Bundle\ListingBundle\Constant\ListingRateStatus;
use Aqarmap\Bundle\ListingBundle\Constant\ListingSections;
use Aqarmap\Bundle\ListingBundle\Constant\ListingSellerRoles;
use Aqarmap\Bundle\ListingBundle\Constant\ListingStatus;
use Aqarmap\Bundle\ListingBundle\Constant\PhotoTypes;
use Aqarmap\Bundle\ListingBundle\Constant\PluralCustomFields;
use Aqarmap\Bundle\ListingBundle\Constant\PropertyRegistrationStatusOption;
use Aqarmap\Bundle\ListingBundle\Document\ScrapedListing;
use Aqarmap\Bundle\ListingBundle\Entity\Traits\CallLog;
use Aqarmap\Bundle\ListingBundle\Security\Authorization\OwnerInterface;
use Aqarmap\Bundle\ListingBundle\Validator\Constraints as AqarMapAssert;
use Aqarmap\Bundle\UserBundle\Constant\TeamCategories;
use Aqarmap\Bundle\UserBundle\Entity\User;
use Aqarmap\Bundle\UserBundle\Model\UserMainPhones;
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\Translatable\Translatable;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Listing.
*/
#[ORM\HasLifecycleCallbacks]
#[ORM\Entity(repositoryClass: \Aqarmap\Bundle\ListingBundle\Repository\ListingRepository::class)]
#[ORM\Table(name: 'listings')]
#[ORM\Index(columns: ['pending_photos_status'])]
#[ORM\Index(columns: ['pending_payment_status'])]
#[ORM\Index(columns: ['relist_status'])]
#[ORM\Index(columns: ['featured'])]
#[ORM\Index(columns: ['deleted_at'])]
#[ORM\Index(columns: ['created_at'])]
#[ORM\Index(columns: ['published_at'])]
#[ORM\Index(columns: ['user_id', 'deleted_at'])]
#[ORM\Index(columns: ['user_id', 'status'])]
#[ORM\Index(columns: ['user_id', 'status', 'deleted_at'])]
#[ORM\Index(columns: ['user_id', 'status', 'location_id'])]
#[ORM\Index(columns: ['user_id', 'status', 'location_id', 'parent_id', 'category', 'deleted_at'])]
#[ORM\Index(columns: ['user_id', 'status', 'location_id', 'property_type_id', 'section_id', 'parent_id', 'category', 'deleted_at'])]
#[ORM\Index(columns: ['location_id', 'section_id', 'property_type_id', 'status', 'published_at'])]
#[ORM\Index(columns: ['user_id', 'section_id', 'leads_counter'])]
#[ORM\Index(columns: ['category', 'parent_id', 'updated_at'])]
#[ORM\Index(columns: ['category', 'parent_id', 'waiting_time'])]
#[ORM\Index(columns: ['status', 'category', 'parent_id'])]
#[ORM\Index(columns: ['reference_number'])]
#[ORM\Index(columns: ['status', 'leads_counter'])]
#[ORM\Index(columns: ['user_id', 'creation_source', 'deleted_at'])]
#[ORM\Index(columns: ['status', 'location_id', 'parent_id', 'user_id', 'deleted_at'])]
#[ORM\Index(columns: ['is_availability_email_sent'])]
#[ORM\Index(columns: ['status', 'category', 'parent_id', 'updated_at'])]
#[Gedmo\TranslationEntity(class: ListingTranslation::class)]
#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', timeAware: false)]
#[Serializer\ExclusionPolicy('all')]
class Listing implements OwnerInterface, Translatable
{
use CallLog;
/**
* @var int
*/
#[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')]
#[Serializer\Groups(['Default', 'List', 'listingDetails', 'listingDetailsWithLocationCompound', 'Details', 'Activity', 'DataLayer', 'ActivitiesData', 'DefaultV4', 'MyListing', 'MyListings', 'SearchV4', 'ProjectSearchV4', 'ProjectDetailsV4', 'UnitDetails', 'Autocomplete', 'RelatedListingsV2', 'SlugResolver', 'locationListingV2', 'homeCompoundV2', 'MyLeads', 'NewLeadGeneration'])]
#[Serializer\Expose]
private $id;
#[ORM\OneToMany(targetEntity: Listing::class, mappedBy: 'parent')]
#[ORM\OrderBy(['area' => 'ASC'])]
#[Serializer\Groups(['List', 'Details'])]
#[Serializer\Expose]
#[Serializer\Until('v2.1')]
private $children;
#[ORM\ManyToOne(targetEntity: Listing::class, inversedBy: 'children')]
#[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'id')]
#[Serializer\Groups(['List', 'Details', 'DataLayer', 'UnitDetails'])]
#[Serializer\Expose]
#[Serializer\Until('v2.1')]
#[Serializer\MaxDepth(1)]
private $parent;
#[ORM\OneToOne(targetEntity: Listing::class)]
#[ORM\JoinColumn(name: 'relist_id', referencedColumnName: 'id')]
private $relistParent;
#[Assert\NotBlank(message: 'listing.title_required', groups: ['step2'])]
#[ORM\Column(name: 'title', type: 'string', length: 128, nullable: true)]
#[Gedmo\Translatable]
#[Serializer\Groups(['Default', 'List', 'Details', 'listingDetails', 'listingDetailsWithLocationCompound', 'Activity', 'Preview', 'DefaultV4', 'MyListing', 'MyListings', 'SearchV4', 'ProjectSearchV4', 'ProjectDetailsV4', 'Autocomplete', 'RelatedListingsV2', 'SlugResolver', 'locationListingV2', 'homeCompoundV2', 'MyLeads'])]
#[Serializer\Expose]
private ?string $title = null;
#[Assert\NotBlank(message: 'listing.description_required', groups: ['step2'])]
#[ORM\Column(name: 'description', type: 'text', length: 1024, nullable: true)]
#[Gedmo\Translatable]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'Activity', 'DefaultV4', 'MyListing', 'MyListings', 'SearchV4', 'ProjectDetailsV4'])]
#[Serializer\Expose]
private ?string $description = null;
#[Assert\NotBlank(groups: ['API'])]
#[ORM\ManyToOne(targetEntity: Section::class, inversedBy: 'listings')]
#[ORM\JoinColumn(name: 'section_id', referencedColumnName: 'id')]
#[Serializer\Groups(['MyListings', 'List', 'Details', 'listingDetails', 'DataLayer', 'DefaultV4', 'MyListing', 'SearchV4'])]
#[Serializer\Expose]
protected $section;
/**
* @var int
*/
#[ORM\Column(name: 'category', type: 'smallint', nullable: false)]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
#[Serializer\Expose]
private $category;
/**
* @var int
*/
#[ORM\Column(name: 'pending_photos_status', type: 'smallint', nullable: true)]
private $pendingPhotosStatus;
/**
* @var int
*/
#[ORM\Column(name: 'pending_payment_status', type: 'smallint', nullable: true)]
private $pendingPaymentStatus;
/**
* @var int
*/
#[ORM\Column(name: 'relist_status', type: 'smallint', nullable: true)]
private $relistStatus;
#[ORM\Column(name: 'seller_role', type: 'smallint', nullable: true)]
#[Serializer\Expose]
#[Serializer\Groups(['Details', 'listingDetails'])]
#[Serializer\Since('v2.1')]
private ?int $sellerRole = null;
private $sellerRoleLabel;
/**
* @var int
*/
#[Assert\NotBlank(message: 'listing.area_required', groups: ['step2'])]
#[Assert\GreaterThan(value: 1, message: 'listing.area_minimum', groups: ['step2'])]
#[ORM\Column(name: 'area', type: 'integer', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'DefaultV4', 'MyListing', 'MyListings', 'SearchV4', 'UnitDetails', 'RelatedListingsV2', 'listingDetails'])]
#[Serializer\Expose]
private $area;
/**
* CAUTION: type-hint string to avoid unnecessary update on every fetch.
*/
#[Assert\NotBlank(message: 'listing.price_required', groups: ['step2'])]
#[Assert\GreaterThan(value: 100, message: 'listing.price_minimum', groups: ['step2'])]
#[ORM\Column(name: 'price', type: 'bigint', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'Activity', 'Preview', 'DefaultV4', 'MyListing', 'MyListings', 'SearchV4', 'UnitDetails', 'RelatedListingsV2'])]
#[Serializer\Expose]
private ?string $price = null;
/**
* @var string
*/
#[Assert\Length(max: 100)]
#[Assert\NotBlank(message: 'listing.address_required', groups: ['step2'])]
#[ORM\Column(name: 'address', type: 'text', length: 512, nullable: true)]
#[Gedmo\Translatable]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'Activity', 'Preview', 'DefaultV4', 'SearchV4', 'RelatedListingsV2', 'locationListingV2', 'homeCompoundV2', 'MyListings'])]
#[Serializer\Expose]
private $address;
/**
* @var float
*/
#[ORM\Column(name: 'center_lat', type: 'float', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
#[Serializer\Expose]
private $centerLat;
/**
* @var float
*/
#[ORM\Column(name: 'center_lng', type: 'float', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
#[Serializer\Expose]
private $centerLng;
/**
* @var int
*/
#[ORM\Column(name: 'status', type: 'smallint', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'Activity', 'listingDetails'])]
#[Serializer\Expose]
private $status;
private $statusLabel;
/**
* @var int
*/
#[ORM\Column(name: 'property_view', type: 'smallint', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'SearchV4'])]
#[Serializer\Expose]
private $propertyView;
private $propertyViewLabel;
/**
* @var int
*/
#[ORM\Column(name: 'payment_method', type: 'smallint', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
#[Serializer\Expose]
private $paymentMethod;
private $paymentMethodLabel;
/**
* @var bool
*/
#[ORM\Column(name: 'featured', type: 'smallint', nullable: true)]
private $featured;
/**
* @var int
*/
#[ORM\Column(name: 'views', type: 'integer', nullable: true)]
#[Serializer\Groups(['Api', 'MyListing'])]
#[Serializer\Expose]
private $views = 0;
/**
* @var int
*/
#[ORM\Column(name: 'phone_counter', type: 'integer', options: ['default' => 0])]
#[Serializer\Groups(['Api'])]
#[Serializer\Expose]
private $phoneCounter = 0;
/**
* @var int
*/
#[ORM\Column(name: 'messages_counter', type: 'integer', options: ['default' => 0])]
#[Serializer\Groups(['Api'])]
#[Serializer\Expose]
private $messagesCounter = 0;
#[ORM\Column(name: 'leads_counter', type: 'integer', options: ['default' => 0])]
#[Serializer\Groups(['Api'])]
#[Serializer\Expose]
private int $leadsCounter = 0;
/**
* @var int
*/
#[ORM\Column(name: 'sent_notifiers', type: 'integer', nullable: true)]
private $sentNotifiers;
/**
* @var int
*/
#[ORM\Column(name: 'relist_counter', type: 'integer', nullable: true)]
private $relistCounter;
/**
* @var string
*/
#[ORM\Column(name: 'ip', type: 'string', length: 50, nullable: true)]
private $ip;
/**
* @var string
*
* @AqarMapAssert\IsYoutubeUrlOrNull
*/
#[ORM\Column(name: 'video_url', type: 'string', length: 150, nullable: true)]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'Activity', 'DefaultV4', 'ProjectSearchV4', 'ProjectDetailsV4', 'listingDetailsWithLocationCompound'])]
#[Serializer\Expose]
private $videoUrl;
#[ORM\Column(name: 'slug', length: 128, nullable: true)]
#[Serializer\Groups(['locationListingV2', 'SearchV4', 'listingDetails'])]
#[Serializer\Expose]
private $slug;
#[ORM\Column(name: 'custom_slug', length: 50, unique: true, nullable: true)]
#[Serializer\Groups(['DataLayer'])]
#[Serializer\Expose]
private $customSlug;
/**
* @var int
*/
#[ORM\Column(name: 'score', type: 'float', nullable: true)]
private $score;
#[ORM\Column(name: 'created_at', type: 'datetime', nullable: true)]
#[Serializer\Groups(['MyListings'])]
#[Serializer\Expose]
private $createdAt;
/**
* @var \DateTime
*/
#[ORM\Column(name: 'updated_at', type: 'datetime', nullable: true)]
#[Serializer\Groups(['Details', 'DefaultV4', 'List', 'SearchV4', 'listingDetails'])]
#[Serializer\Expose]
private $updatedAt;
/**
* @var \DateTime
*/
#[ORM\Column(name: 'pending_status_created_at', type: 'datetime', nullable: true)]
#[Serializer\Groups(['Details', 'DefaultV4', 'List', 'SearchV4'])]
#[Serializer\Expose]
private $pendingStatusCreatedAt;
/**
* @var \DateTime
*/
#[Assert\Range(max: 'now', maxMessage: 'listing.date_not_allowed')]
#[ORM\Column(name: 'published_at', type: 'datetime', nullable: true)]
#[Serializer\Groups(['List', 'Details', 'DefaultV4', 'SearchV4', 'ProjectSearchV4', 'ProjectDetailsV4', 'MyListings'])]
#[Serializer\Expose]
private $publishedAt;
/**
* @var \DateTime;
*/
private $aggregatedPublishedAt;
/**
* @var \DateTime
*/
#[ORM\Column(name: 'expires_at', type: 'datetime', nullable: true)]
#[Serializer\Groups(['DefaultV4', 'MyListing', 'MyListings'])]
#[Serializer\Expose]
private $expiresAt;
#[ORM\Column(name: 'deleted_at', type: 'datetime', nullable: true)]
#[Serializer\Groups(['listingDetails'])]
#[Serializer\Expose]
private $deletedAt;
#[ORM\Column(name: 'rejected_at', type: 'datetime', nullable: true)]
private $rejectedAt;
#[ORM\OrderBy(['averagePricePerMeter' => 'DESC'])]
#[ORM\OneToMany(targetEntity: CompoundAveragePrice::class, mappedBy: 'parentCompound', cascade: ['all'])]
private $compoundAveragePrices;
#[Assert\NotBlank(groups: ['API'])]
#[ORM\ManyToOne(targetEntity: PropertyType::class, inversedBy: 'listings')]
#[ORM\JoinColumn(name: 'property_type_id', referencedColumnName: 'id')]
#[Serializer\Groups(['MyListings', 'List', 'Details', 'listingDetails', 'Activity', 'DefaultV4', 'SearchV4', 'MyLeads'])]
#[Serializer\Expose]
protected $propertyType;
#[ORM\ManyToOne(targetEntity: Location::class, inversedBy: 'listings')]
#[ORM\JoinColumn(name: 'location_id', referencedColumnName: 'id')]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'Activity', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'RelatedListingsV2'])]
#[Serializer\Expose]
protected $location;
#[ORM\ManyToMany(targetEntity: Location::class)]
#[ORM\JoinTable(name: 'listings_locations', joinColumns: [new ORM\JoinColumn(name: 'listing_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'location_id', referencedColumnName: 'id')])]
protected $locations;
#[ORM\ManyToOne(targetEntity: CompoundLocation::class, inversedBy: 'listings')]
#[ORM\JoinColumn(name: 'compound_location_id', referencedColumnName: 'id', nullable: true)]
#[Serializer\Groups(['Default', 'ProjectSearchV4'])]
#[Serializer\Expose]
protected $compoundLocation;
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'listings')]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', onDelete: 'CASCADE', nullable: false)]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'DefaultV4', 'MyListing', 'SearchV4', 'ProjectDetailsV4', 'ProjectSearchV4', 'RelatedListingsV2', 'MyListings', 'MyLeads'])]
#[Serializer\Expose]
protected $user;
#[ORM\ManyToMany(targetEntity: User::class, fetch: 'EXTRA_LAZY')]
#[ORM\JoinTable(name: 'listings_participants', joinColumns: [new ORM\JoinColumn(name: 'listing_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id')])]
protected $participants;
#[Assert\Valid]
#[ORM\OneToMany(targetEntity: ListingAttribute::class, mappedBy: 'listing', cascade: ['all'], orphanRemoval: true)]
#[Serializer\Groups(['List', 'Details', 'Preview', 'listingDetails'])]
#[Serializer\Expose]
protected $attributes;
#[Assert\Valid]
#[ORM\OneToMany(targetEntity: ListingPhone::class, mappedBy: 'listing', cascade: ['all'], orphanRemoval: true)]
protected $phones;
#[ORM\OneToMany(targetEntity: ListingPhoto::class, mappedBy: 'listing', cascade: ['persist', 'remove'], orphanRemoval: true)]
protected $photos;
#[ORM\OneToMany(targetEntity: ListingTranslation::class, mappedBy: 'object', cascade: ['all'], orphanRemoval: true)]
private $translations;
#[ORM\OneToMany(targetEntity: ListingLead::class, mappedBy: 'listing', fetch: 'EXTRA_LAZY')]
protected $leads;
#[ORM\OneToMany(targetEntity: ListingFeature::class, mappedBy: 'listing')]
protected $listingFeatures;
#[ORM\OneToMany(targetEntity: ListingNotification::class, mappedBy: 'listing')]
protected $ListingNotifications;
#[ORM\ManyToMany(targetEntity: Rejection::class)]
#[ORM\JoinTable(name: 'listings_rejections', joinColumns: [new ORM\JoinColumn(name: 'listing_id', referencedColumnName: 'id')], inverseJoinColumns: [new ORM\JoinColumn(name: 'rejection_id', referencedColumnName: 'id')])]
#[Serializer\Groups(['userListing'])]
#[Serializer\Expose]
protected $rejections;
/**
* @var string
*/
#[ORM\Column(name: 'campaign', type: 'string', length: 50, nullable: true)]
#[Serializer\Groups(['List', 'Details', 'DefaultV4', 'MyListing'])]
#[Serializer\Expose]
private $campaign;
/**
* @var int
*/
#[ORM\Column(name: 'final_price', type: 'integer', nullable: true)]
private $finalPrice;
/**
* @var string
*/
#[ORM\Column(name: 'source_of_sale', type: 'string', nullable: true)]
private $sourceOfSale;
/**
* @var string
*/
#[ORM\Column(name: 'delete_reason', type: 'string', length: 100, nullable: true)]
private $deleteReason;
/**
* @var string
*/
#[ORM\Column(name: 'delete_reason_details', type: 'text', nullable: true)]
private $deleteReasonDetails;
#[ORM\OneToMany(targetEntity: Interaction::class, mappedBy: 'listing')]
private $interactions;
/**
* @var string
*/
private $userLogo;
/**
* @var string
*/
private $listingLogo;
#[Gedmo\Locale]
private $locale;
#[ORM\Column(name: 'source', type: 'string', nullable: true)]
private $source;
private $elasticSearchScore;
/**
* @var float
*/
private $qualityScore;
#[ORM\Column(name: 'impressions', type: 'integer', options: ['default' => 0])]
#[Serializer\SerializedName('impressions_count')]
#[Serializer\Groups(['List', 'Details', 'MyListing', 'MyListings'])]
#[Serializer\Expose]
private int $impressions = 0;
#[ORM\Column(name: 'impressions_monthly_count', type: 'integer', options: ['default' => 0])]
#[Serializer\SerializedName('impressions_monthly_count')]
#[Serializer\Groups(['List', 'Details'])]
#[Serializer\Expose]
private int $impressionsMonthlyCount = 0;
#[ORM\Column(name: 'impressions_weekly_count', type: 'integer', options: ['default' => 0])]
#[Serializer\SerializedName('impressions_weekly_count')]
#[Serializer\Groups(['List', 'Details'])]
#[Serializer\Expose]
private int $impressionsWeeklyCount = 0;
/**
* @var \DateTime
*/
#[ORM\Column(name: 'impression_updated_at', type: 'datetime', nullable: true)]
private $impressionUpdatedAt;
#[ORM\Column(name: 'price_level', type: 'smallint', nullable: true)]
#[Serializer\Expose]
private $priceLevel;
/**
* @var string
*/
private $priceLevelLabel;
#[ORM\Column(name: 'compound_status', type: 'smallint', nullable: true)]
#[Serializer\Expose]
private $compoundStatus;
/**
* @var string
*/
private $compoundStatusLabel;
#[ORM\Column(name: 'price_per_meter', type: 'float', nullable: true)]
#[Serializer\Expose]
#[Serializer\Groups(['listingDetails'])]
private $pricePerMeter;
#[ORM\Column(name: 'is_bumped', type: 'boolean', nullable: true)]
private ?bool $isBumped = false;
#[ORM\Column(name: 'is_send_email', type: 'boolean', options: ['default' => 1])]
#[Serializer\Expose]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'RelatedListingsV2'])]
private $isSendEmail = true;
#[ORM\Column(name: 'is_availability_email_sent', type: 'boolean', options: ['default' => 0])]
private $isAvailabilityEmailSent = false;
#[ORM\Column(name: 'market_property_type', type: 'smallint', nullable: true)]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'Details', 'listingDetails'])]
#[Serializer\Expose]
private ?int $marketPropertyType = null;
/**
* @var int
*/
#[ORM\Column(name: 'creation_source', type: 'smallint', nullable: true)]
private $creationSource;
/**
* @deprecated
*
* @var int
*/
#[ORM\Column(name: 'click_through_rate', type: 'float', options: ['default' => 0])]
private $clickThroughRate = 0;
/**
* @var int
*/
#[ORM\Column(name: 'label', type: 'smallint', nullable: true)]
private $label;
#[ORM\Column(name: 'is_top_picks', type: 'boolean', options: ['default' => 0])]
private $isTopPicks = false;
/**
* @var int
*/
#[ORM\Column(name: 'contact_rate', type: 'float', options: ['default' => 0])]
private $contactRate = 0;
#[ORM\OneToMany(targetEntity: ListingRate::class, mappedBy: 'listing', fetch: 'EXTRA_LAZY')]
private $rates;
/**
* @var int
*/
private $totalRates;
/**
* @var ArrayCollection
*/
private $rateReasonsCollection;
#[ORM\Column(name: 'synced', type: 'boolean')]
private $synced = false;
#[ORM\Column(name: 'reference_id', type: 'integer', nullable: true)]
private $referenceId;
private $featuredTypeLabel;
#[ORM\OneToMany(targetEntity: Favourite::class, mappedBy: 'listing')]
protected $favourite;
#[ORM\OneToMany(targetEntity: \Aqarmap\Bundle\ValueEngineBundle\Entity\ValueEngineListingsLocations::class, mappedBy: 'listing')]
protected $valueEngineListingsLocations;
#[ORM\Column(name: 'is_pending_featuring', type: 'boolean', nullable: true)]
private $isPendingFeaturing = false;
#[ORM\Column(name: 'pending_featuring_type', type: 'integer', nullable: true)]
private $pendingFeaturingType;
#[ORM\OneToMany(targetEntity: ListingNote::class, mappedBy: 'listing')]
protected $notes;
/**
* @var bool
*/
private $isFavourite = false;
/**
* @var string
*/
private $userNote;
#[ORM\Column(name: 'rate_status', type: 'smallint', nullable: true)]
private $rateStatus;
#[ORM\Column(name: 'is_rate_reviewed', type: 'boolean', nullable: true, options: ['default' => 0])]
private $isRateReviewed = false;
#[ORM\Column(name: 'is_call_request', type: 'boolean', options: ['default' => 0])]
#[Serializer\SerializedName('isCallRequest')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'RelatedListingsV2', 'listingDetails'])]
#[Serializer\Expose]
private $isCallRequest = false;
#[ORM\Column(name: 'is_shown_in_homepage', type: 'boolean', options: ['default' => 0])]
#[Serializer\Groups(['List', 'Details', 'DefaultV4'])]
#[Serializer\Expose]
private $isShownInHomepage = false;
/**
* @var DateTime
*/
private $reportedDate;
/**
* @var Listing
*/
private $parentOfSimilarListing;
#[Serializer\SerializedName('attributes')]
#[Serializer\Groups(['NotesDetails'])]
#[Serializer\Expose]
private $listingAttributes = [];
/**
* TODO:This Field Is maily Related To Compounds Will Be removed with new project compounds Valu.
*
* @var int
*/
#[ORM\Column(name: 'is_commercial', type: 'smallint', nullable: true)]
private $isCommercial = false;
/**
* @var array
*/
private $mappedPhotos = [];
/**
* @var array
*/
private $v4Translations = [];
private ?array $mappedMainPhoto = null;
/**
* @var bool
*/
#[ORM\Column(name: 'is_resale', type: 'boolean', options: ['default' => 0])]
#[Serializer\SerializedName('isResale')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4'])]
#[Serializer\Expose]
private $isResale = false;
/**
* @var bool
*/
#[ORM\Column(name: 'is_rent', type: 'boolean', options: ['default' => 0])]
#[Serializer\SerializedName('isRent')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4'])]
#[Serializer\Expose]
private $isRent = false;
/**
* @var bool
*/
#[ORM\Column(name: 'is_primary', type: 'boolean', options: ['default' => 0])]
#[Serializer\SerializedName('isPrimary')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'ProjectDetailsV4'])]
#[Serializer\Expose]
private $isPrimary = false;
/**
* @var bool
*/
#[ORM\Column(name: 'is_mortgage_approved', type: 'boolean', nullable: true)]
#[Serializer\SerializedName('isMortgageApproved')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'listingDetails'])]
#[Serializer\Expose]
private $isMortgageApproved;
#[ORM\OneToMany(targetEntity: ListingsRatesNote::class, mappedBy: 'listing')]
#[Serializer\Groups(['List', 'Details'])]
#[Serializer\Expose]
private $ratesNotes = [];
/**
* @var string
*/
#[ORM\Column(name: 'meta_title', type: 'string', length: 128, nullable: true)]
#[Gedmo\Translatable]
private $metaTitle;
/**
* @var string
*/
#[ORM\Column(name: 'meta_description', type: 'text', length: 1024, nullable: true)]
#[Gedmo\Translatable]
private $metaDescription;
/**
* @var bool
*/
#[ORM\Column(name: 'is_mortgage', type: 'boolean', options: ['default' => 0])]
#[Serializer\SerializedName('isMortgage')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'RelatedListingsV2'])]
#[Serializer\Expose]
private $isMortgage = false;
/**
* @var CompoundField
*/
#[ORM\OneToOne(targetEntity: CompoundField::class)]
#[ORM\JoinColumn(name: 'compound_field_id', referencedColumnName: 'id')]
protected $compoundField;
/** @var array
*/
#[ORM\Column(name: 'eligible_for_mortgage', type: 'array', nullable: true)]
private $eligibleForMortgage;
/**
* @var array
*/
private $propertyRegistrationStatusOptions;
/**
* @var array
*/
private $eligibleForMortgageData;
/**
* property Registration Status , default I'm not know = 4.
*
* @var int
*/
#[ORM\Column(name: 'property_registration_status', type: 'integer', nullable: true, options: ['default' => 4])]
#[Serializer\SerializedName('propertyRegistrationStatus')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'listingDetails', 'listingDetailsWithLocationCompound'])]
#[Serializer\Expose]
private $propertyRegistrationStatus;
/**
* @var array
*/
#[Serializer\SerializedName('propertyTypeChildren')]
#[Serializer\Groups(['ProjectDetailsV4'])]
#[Serializer\Expose]
private $propertyTypeChilden = [];
/**
* @var float
*/
private $compoundElasticScore;
/**
* @var FinancialAid
*/
private $financialAid;
/**
* @deprecated It's bad design, and cause a performance issues
*/
private int $similarListingsCount = 0;
/**
* @deprecated It's bad design, and cause a performance issues
*/
private array $similarListingsIds = [];
/**
* @var string|null
*/
#[ORM\Column(name: 'advertiser_number', type: 'string', nullable: true)]
#[Serializer\SerializedName('advertiserNumber')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4'])]
#[Serializer\Expose]
private $advertiserNumber;
/**
* @var string|null
*/
#[ORM\Column(name: 'authorization_number', type: 'string', nullable: true)]
#[Serializer\SerializedName('authorizationNumber')]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4'])]
#[Serializer\Expose]
private $authorizationNumber;
/**
* @var float
*/
private $costPerLead = 0;
#[Serializer\Groups(['ProjectDetailsV4'])]
#[Serializer\SerializedName('resaleCount')]
#[Serializer\Expose]
private $resaleCount = 0;
#[Serializer\Groups(['ProjectDetailsV4'])]
#[Serializer\SerializedName('rentCount')]
#[Serializer\Expose]
private $rentCount = 0;
/**
* @var \DateTime
*/
#[ORM\Column(name: 'freezed_at', type: 'datetime', nullable: true)]
private $freezedAt;
#[ORM\Column(name: 'eligible_for_bumpup', type: 'boolean', options: ['default' => 0])]
private $eligibleForBumpUp = false;
/**
* @var string
*/
#[ORM\Column(name: 'waiting_time', type: 'string', length: 50, nullable: true)]
private $waitingTime;
#[ORM\Column(name: 'reference_number', type: 'string', length: 128, nullable: true)]
#[Serializer\Groups(['MyListing', 'MyListings', 'listingDetails', 'MyLeads'])]
#[Serializer\Expose]
private ?string $referenceNumber = null;
#[Serializer\Groups(['SearchV4'])]
#[Serializer\Expose]
public $debug;
/**
* @var File|null
*/
#[ORM\OneToOne(targetEntity: File::class, cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(name: 'brochure_id', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
#[Serializer\Groups(['Default', 'DefaultV4', 'ProjectSearchV4', 'ProjectDetailsV4', 'locationListingV2'])]
#[Serializer\Expose]
private $brochure;
#[ORM\Column(name: 'is_hold', type: 'boolean', options: ['default' => 0])]
private $isHold = false;
#[ORM\Column(name: 'is_ai_content', type: 'boolean', options: ['default' => 0])]
private bool $AiContent = false;
/**
* Constructor.
*/
public function __construct()
{
$this->children = new ArrayCollection();
$this->attributes = new ArrayCollection();
$this->phones = new ArrayCollection();
$this->photos = new ArrayCollection();
$this->leads = new ArrayCollection();
$this->rates = new ArrayCollection();
$this->listingFeatures = new ArrayCollection();
$this->ListingNotifications = new ArrayCollection();
$this->translations = new ArrayCollection();
$this->rejections = new ArrayCollection();
$this->participants = new ArrayCollection();
$this->rateReasonsCollection = new ArrayCollection();
$this->favourite = new ArrayCollection();
}
/**
* Clone.
*/
public function __clone()
{
$this->id = null;
$this->slug = null;
$this->children = null;
$this->title = null;
$this->address = null;
$this->description = null;
$this->translations = null;
$this->leads = new ArrayCollection();
$this->participants = null;
$this->featured = 0;
$this->views = 0;
$this->customSlug = null;
$this->relistCounter = 0;
$this->messagesCounter = 0;
$this->phoneCounter = 0;
$this->sentNotifiers = 0;
$this->isBumped = false;
$this->ratesNotes = new ArrayCollection();
$this->compoundField = null;
$this->compoundAveragePrices = null;
}
#[ORM\PrePersist]
public function onPrePersist(): void
{
if (!$this->getCreatedAt()) {
$this->setCreatedAt(new \DateTime());
}
if (!$this->getUpdatedAt()) {
$this->setUpdatedAt(new \DateTime());
}
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set title.
*
* @param string $title
*
* @return Listing
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title.
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set description.
*
* @param string $description
*
* @return Listing
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description.
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set section.
*
* @return Listing
*/
public function setSection(?Section $section = null)
{
$this->section = $section;
return $this;
}
/**
* Get section.
*
* @return Section
*/
public function getSection()
{
return $this->section;
}
/**
* Set category.
*
* @param int $category
*
* @return Listing
*/
public function setCategory($category)
{
$this->category = $category;
return $this;
}
/**
* Get category.
*
* @return int
*/
public function getCategory()
{
return $this->category;
}
/**
* Get category name.
*
* @return string
*/
public function getCategoryName()
{
return ListingCategories::getLabel($this->category);
}
/**
* @return bool
*/
public function isDraft()
{
return ListingStatus::DRAFT == $this->status;
}
/**
* @return bool
*/
public function isLive()
{
return ListingStatus::LIVE == $this->status;
}
/**
* Set pendingPhotosStatus.
*
* @param int $pendingPhotosStatus
*
* @return Listing
*/
public function setPendingPhotosStatus($pendingPhotosStatus)
{
$this->pendingPhotosStatus = $pendingPhotosStatus;
return $this;
}
/**
* Get pendingPhotosStatus.
*
* @return int
*/
public function getPendingPhotosStatus()
{
return $this->pendingPhotosStatus;
}
/**
* Set pendingPaymentStatus.
*
* @param int $pendingPaymentStatus
*
* @return Listing
*/
public function setPendingPaymentStatus($pendingPaymentStatus)
{
$this->pendingPaymentStatus = $pendingPaymentStatus;
return $this;
}
/**
* Get pendingPaymentStatus.
*
* @return int
*/
public function getPendingPaymentStatus()
{
return $this->pendingPaymentStatus;
}
/**
* Set relistStatus.
*
* @param int $relistStatus
*
* @return Listing
*/
public function setRelistStatus($relistStatus)
{
$this->relistStatus = $relistStatus;
return $this;
}
/**
* Get relistStatus.
*
* @return int
*/
public function getRelistStatus()
{
return $this->relistStatus;
}
/**
* Set sellerRole.
*/
public function setSellerRole(?int $sellerRole): self
{
$this->sellerRole = $sellerRole;
return $this;
}
/**
* Get sellerRole.
*/
public function getSellerRole(): ?int
{
return $this->sellerRole;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('seller_role')]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
#[Serializer\Until('v2.0')]
public function getSellerRoleLabel()
{
return ListingSellerRoles::getLabel($this->getSellerRole());
}
public function setSellerRoleLabel($label): void
{
$this->sellerRoleLabel = $label;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('seller_role_label')]
#[Serializer\Groups(['List', 'Details'])]
#[Serializer\Since('v2.1')]
#[Serializer\Until('v2.11')]
public function getSellerRoleAsLabel()
{
return self::getSellerRoleLabel();
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('seller_role_label')]
#[Serializer\Groups(['List', 'Details', 'DefaultV4'])]
#[Serializer\Since('v2.12')]
public function getSellerRoleTranslated()
{
return $this->sellerRoleLabel;
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('accepts_messages')]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
public function isAcceptsMessages()
{
return !$this->getUser()->hasRole('ROLE_TROOP');
}
/**
* Set area.
*
* @param int $area
*
* @return Listing
*/
public function setArea($area)
{
$this->area = $area;
return $this;
}
/**
* Get area.
*
* @return int
*/
public function getArea()
{
return (int) $this->area;
}
/**
* Set price.
*
* @return Listing
*/
public function setPrice(?int $price)
{
$this->price = $price;
return $this;
}
/**
* Get price.
*/
public function getPrice(): ?int
{
return $this->price;
}
/**
* Set address.
*
* @param string $address
*
* @return Listing
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* Get address.
*
* @return string
*/
public function getAddress()
{
return $this->address;
}
/**
* Set centerLat.
*
* @param float $centerLat
*
* @return Listing
*/
public function setCenterLat($centerLat)
{
$this->centerLat = $centerLat;
return $this;
}
/**
* Get centerLat.
*
* @return float
*/
public function getCenterLat()
{
return $this->centerLat;
}
/**
* Set centerLng.
*
* @param float $centerLng
*
* @return Listing
*/
public function setCenterLng($centerLng)
{
$this->centerLng = $centerLng;
return $this;
}
/**
* Get centerLng.
*
* @return float
*/
public function getCenterLng()
{
return $this->centerLng;
}
/**
* Set featured.
*
* @param int $featured
*
* @return Listing
*/
public function setFeatured($featured)
{
$this->featured = $featured;
return $this;
}
/**
* Get featured.
*
* @return int
*/
public function getFeatured()
{
return $this->featured;
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('is_featured')]
#[Serializer\Groups(['List', 'Details', 'DataLayer', 'MyListing', 'MyListings', 'listingDetails'])]
public function isFeatured()
{
return (bool) $this->getFeatured();
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('isFeatured')]
#[Serializer\Groups(['DefaultV4', 'SearchV4'])]
public function getFeaturingStatus()
{
return (bool) $this->getFeatured();
}
/**
* @return string
*/
public function getFeaturedLabel()
{
return ListingFeaturedTypes::getLabel($this->getFeatured());
}
/**
* Set views.
*
* @param int $views
*
* @return Listing
*/
public function setViews($views)
{
$this->views = $views;
return $this;
}
/**
* Get views.
*
* @return int
*/
public function getViews()
{
return $this->views ?: 0;
}
/**
* Get views count.
*
* @return int
*/
public function getTotalViews()
{
$totalViews = $this->getViews();
if ($this->getChildren()) {
foreach ($this->getChildren() as $listing) {
$totalViews += $listing->getViews();
}
}
return $totalViews;
}
/**
* Set relistCounter.
*
* @param int $relistCounter
*
* @return Listing
*/
public function setRelistCounter($relistCounter)
{
$this->relistCounter = $relistCounter;
return $this;
}
/**
* Get relistCounter.
*
* @return int
*/
public function getRelistCounter()
{
return $this->relistCounter;
}
/**
* Set sentNotifiers.
*
* @param int $sentNotifiers
*
* @return Listing
*/
public function setSentNotifiers($sentNotifiers)
{
$this->sentNotifiers = $sentNotifiers;
return $this;
}
/**
* Get sentNotifiers.
*
* @return int
*/
public function getSentNotifiers()
{
return $this->sentNotifiers;
}
/**
* Set status.
*
* @param int $status
*
* @return Listing
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status.
*
* @return int
*/
public function getStatus()
{
return $this->status;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('status_label')]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
#[Serializer\Until('v2.11')]
public function getStatusLabel()
{
return ListingStatus::getLabel($this->getStatus());
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('status_label')]
#[Serializer\Groups(['List', 'Details'])]
#[Serializer\Since('v2.12')]
public function getStatusTranslated()
{
return $this->statusLabel;
}
public function setStatusLabel($label): void
{
$this->statusLabel = $label;
}
/**
* @return string
*/
public function getStatusDescription()
{
return ListingStatus::getDescription($this->getStatus());
}
/**
* Set ip.
*
* @param string $ip
*
* @return Listing
*/
public function setIp($ip)
{
$this->ip = $ip;
return $this;
}
/**
* Get ip.
*
* @return string
*/
public function getIp()
{
return $this->ip;
}
/**
* @param string $videoUrl
*
* @return $this
*/
public function setVideoUrl($videoUrl)
{
$this->videoUrl = $videoUrl;
return $this;
}
/**
* @return string
*/
public function getVideoUrl()
{
return $this->videoUrl;
}
/**
* Set slug.
*
* @param string $slug
*
* @return Listing
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug.
*
* @return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set customSlug.
*
* @param string $customSlug
*
* @return Listing
*/
public function setCustomSlug($customSlug)
{
$this->customSlug = str_replace(' ', '-', strtolower($customSlug));
return $this;
}
/**
* Get customSlug.
*
* @param bool $force
*
* @return string
*/
public function getCustomSlug($force = false)
{
if ($force && empty($this->customSlug)) {
return $this->slug;
}
return $this->customSlug;
}
/**
* Set score.
*
* @param float $score
*
* @return Listing
*/
public function setScore($score)
{
$this->score = $score;
return $this;
}
/**
* Get score.
*
* @return float
*/
public function getScore()
{
return $this->score;
}
/**
* Set maxPrice.
*
* @param int $maxPrice
*
* @return Listing
*/
public function setMaxPrice($maxPrice)
{
$this->maxPrice = $maxPrice;
return $this;
}
/**
* Get maxPrice.
*
* @return int
*/
public function getMaxPrice()
{
return $this->maxPrice;
}
/**
* Set createdAt.
*
* @param \DateTime $createdAt
*
* @return Listing
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt.
*
* @return \DateTime
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['MyListing'])]
#[Serializer\Expose]
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updatedAt.
*
* @param \DateTime $updatedAt
*
* @return Listing
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt.
*
* @return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set pendingStatusCreatedAt.
*
* @param \DateTime $pendingStatusCreatedAt
*
* @return Listing
*/
public function setPendingStatusCreatedAt($pendingStatusCreatedAt)
{
$this->pendingStatusCreatedAt = $pendingStatusCreatedAt;
return $this;
}
/**
* Get pendingStatusCreatedAt.
*
* @return \DateTime
*/
public function getPendingStatusCreatedAt()
{
return $this->pendingStatusCreatedAt;
}
/**
* Set publishedAt.
*
* @return Listing
*/
public function setPublishedAt(?\DateTime $publishedAt = null)
{
$this->publishedAt = $publishedAt;
return $this;
}
/**
* Get publishedAt.
*
* @return \DateTime
*/
public function getPublishedAt()
{
return $this->publishedAt;
}
/**
* @return \DateTime|ArrayCollection|Collection
*/
#[Serializer\VirtualProperty]
public function getAggregatedPublishedAt()
{
$lastBump = $this->getLastAutoBumpUp();
/** @var ListingFeature $lastFeature */
$lastFeature = $this->getLastListingFeature();
$listingFeature = null;
if ($lastBump && $lastFeature) {
$listingFeature = ($lastBump->getLastBumpedAt() > $lastFeature->getCreatedAt()) ? $lastBump : $lastFeature;
} elseif ($lastBump) {
$listingFeature = $lastBump;
} elseif ($lastFeature) {
$listingFeature = $lastFeature;
}
if (!$listingFeature) {
return $this->getPublishedAt();
}
return (ListingFeatures::BUMP_UP == $listingFeature->getType() && $listingFeature->getLastBumpedAt()) ?
$listingFeature->getLastBumpedAt() : $listingFeature->getCreatedAt();
}
/**
* Set expiresAt.
*
* @param \DateTime $expiresAt
*
* @return Listing
*/
public function setExpiresAt($expiresAt)
{
$this->expiresAt = $expiresAt;
return $this;
}
/**
* Get expiresAt.
*
* @return \DateTime
*/
public function getExpiresAt()
{
return $this->expiresAt;
}
public function setDeletedAt(?\DateTime $deletedAt): Listing
{
$this->deletedAt = $deletedAt;
return $this;
}
/**
* Get deletedAt.
*
* @return \DateTime
*/
public function getDeletedAt()
{
return $this->deletedAt;
}
/**
* Set rejectedAt.
*
* @param \DateTime $rejectedAt
*
* @return Listing
*/
public function setRejectedAt($rejectedAt)
{
$this->rejectedAt = $rejectedAt;
return $this;
}
/**
* Get rejectedAt.
*
* @return \DateTime
*/
public function getRejectedAt()
{
return $this->rejectedAt;
}
/**
* Add children.
*
* @return Listing
*/
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()
->orderBy(['id' => Criteria::ASC]);
if (!$this->children) {
return null;
}
return $this->children->matching($criteria);
}
/**
* Get only live listing children (live units) and order by area.
*/
public function getLiveChildren(?PropertyType $propertyType = null)
{
$criteria = Criteria::create()->where(Criteria::expr()->eq('status', ListingStatus::LIVE));
if ($propertyType) {
$criteria->where(Criteria::expr()->eq('propertyType', $propertyType));
}
$criteria->orderBy(['area' => Criteria::ASC]);
if (empty($this->children)) {
return null;
}
return $this->children->matching($criteria);
}
public function getLiveChildrenIDs()
{
$ids = [];
foreach ($this->getLiveChildren() as $listing) {
$ids[] = $listing->getId();
}
return $ids;
}
/**
* Get only pending listing children (live units) and order by area.
*/
public function getPendingChildren()
{
$criteria = Criteria::create()
->where(Criteria::expr()->in('status', ListingStatus::$pendingStatusArray))
->orderBy(['area' => Criteria::ASC]);
return $this->children->matching($criteria);
}
/**
* Set parent.
*
* @return Listing
*/
public function setParent(?self $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Get parent.
*
* @return Listing
*/
public function getParent()
{
return $this->parent;
}
/**
* Get Relist Parent.
*
* @return Listing
*/
public function getRelistParent()
{
return $this->relistParent;
}
public function setRelistParent(self $relistParent): void
{
$this->relistParent = $relistParent;
}
/**
* Set propertyType.
*
* @return Listing
*/
public function setPropertyType(?PropertyType $propertyType = null)
{
$this->propertyType = $propertyType;
return $this;
}
/**
* Get propertyType.
*
* @return PropertyType
*/
public function getPropertyType()
{
return $this->propertyType;
}
/**
* Set location.
*
* @return Listing
*/
public function setLocation(?Location $location = null)
{
$this->location = $location;
return $this;
}
/**
* Get location.
*
* @return Location
*/
public function getLocation()
{
return $this->location;
}
/**
* Add location.
*
* @return Listing
*/
public function addLocation(Location $location)
{
$this->locations[] = $location;
return $this;
}
/**
* Has location.
*
* @return bool
*/
public function hasLocation(Location $location)
{
return $this->locations->contains($location);
}
/**
* Set Locations.
*
* @return Listing
*/
public function setLocations($locations)
{
foreach ($locations as $location) {
$this->addLocation($location);
}
return $this;
}
/**
* Remove location.
*/
public function removeLocation(Location $location): void
{
$this->locations->removeElement($location);
}
/**
* Get locations.
*
* @return Collection
*/
public function getLocations()
{
return $this->locations;
}
/**
* @return $this
*/
public function setCompoundLocation(?CompoundLocation $compoundLocation = null)
{
$this->compoundLocation = $compoundLocation;
return $this;
}
/**
* @return CompoundLocation
*/
public function getCompoundLocation()
{
if (!$this->compoundLocation && $this->hasParent()) {
return $this->getParent()->getCompoundLocation();
}
return $this->compoundLocation;
}
/**
* @return mixed|string
*/
public function getCompoundLocationTitle()
{
$compoundLocation = $this->getCompoundLocation();
if ($compoundLocation instanceof CompoundLocation) {
return $compoundLocation->getTitle();
}
return '';
}
/**
* Set user.
*
* @return Listing
*/
public function setUser(?User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user.
*
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* Add participants.
*
* @return Listing
*/
public function addParticipant(User $participants)
{
$this->participants[] = $participants;
return $this;
}
/**
* Remove participants.
*/
public function removeParticipant(User $participants): void
{
$this->participants->removeElement($participants);
}
/**
* Get participants.
*
* @return Collection
*/
public function getParticipants()
{
return $this->participants;
}
/**
* Has participant.
*
* @return bool
*/
public function hasParticipant(User $participant)
{
$participants = $this->getParticipants();
if (\is_object($participants)) {
return $this->getParticipants()->contains($participant) ? true : false;
}
return false;
}
/**
* @return ArrayCollection
*/
public function getAllParticipants()
{
$participants = new ArrayCollection();
$participants->add($this->getUser());
foreach ($this->getParticipants() as $participant) {
if (!$participants->contains($participant)) {
$participants->add($participant);
}
}
if ($this->getParent()) {
foreach ($this->getParent()->getAllParticipants() as $participant) {
if (!$participants->contains($participant)) {
$participants->add($participant);
}
}
}
return $participants;
}
/**
* @return ArrayCollection
*/
public function getAllLocations()
{
$locations = new ArrayCollection();
$locations->add($this->getLocation());
foreach ($this->getLocations() as $location) {
if (!$locations->contains($location)) {
$locations->add($location);
}
}
return $locations;
}
/**
* @return array
*/
public function getAllLocationsIDs()
{
$locations = new ArrayCollection();
$locations->add($this->getLocation()->getId());
foreach ($this->getLocations() as $location) {
if (!$locations->contains($location->getId())) {
$locations->add($location->getId());
}
}
return $locations->toArray();
}
/**
* Add attribute.
*
* @return Listing
*/
public function addAttribute(ListingAttribute $attribute)
{
if (!$attribute->isValid()) {
return $this;
}
$attribute->setListing($this);
$this->attributes[] = $attribute;
return $this;
}
/**
* Set attributes.
*
* @return Listing
*/
public function setAttributes($attributes)
{
foreach ($attributes as $attribute) {
if (
$attribute instanceof ListingAttribute
&& !$attribute->isValid()
) {
continue;
}
$this->addAttribute($attribute);
}
return $this;
}
/**
* Remove attribute.
*/
public function removeAttribute(ListingAttribute $attribute): void
{
$this->attributes->removeElement($attribute);
}
/**
* Clear attributes.
*/
public function clearAttributes(): void
{
$this->attributes->clear();
}
/**
* Get attributes.
*
* @return Collection
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* Get Attributes in List.
*
* @return array
*/
public function getAttributesList()
{
$attributeList = [];
foreach ($this->attributes as $attribute) {
$value = $attribute->getValue();
if (
PluralCustomFields::MAX_VALUE == $value
&& \in_array($attribute->getCustomField()->getName(), PluralCustomFields::getChoices())
) {
$value = PluralCustomFields::MAX_VALUE_LABEL;
}
$attributeList[$attribute->getCustomField()->getName()] = $value;
if (ListingCustomFields::FINISH_TYPE_NAME == $attribute->getCustomField()->getName()) {
$attributeList[$attribute->getCustomField()->getName()] = $attribute->getValue();
}
}
return $attributeList;
}
/**
* Get attributes.
*
* @return Collection
*/
public function getAttribute($attrName)
{
foreach ($this->attributes as $attribute) {
if ($attrName == $attribute->getCustomField()->getName()) {
return $attribute;
}
}
}
/**
* Add phones.
*
* @param ListingPhone $phone
*
* @return Listing
*/
public function addPhone($phone)
{
$phone->setListing($this); // Synchronously updating inverse side
$criteria = Criteria::create()->where(Criteria::expr()->eq('number', $phone->getNumber()));
if ($this->getPhones()->matching($criteria)->isEmpty()) {
$this->phones[] = $phone;
}
return $this;
}
/**
* Set Phones.
*
* @return Listing
*/
public function setPhones($phones)
{
foreach ($phones as $phone) {
$this->addPhone($phone);
}
return $this;
}
/**
* Remove phone.
*/
public function removePhone(ListingPhone $phone): void
{
$phone->setListing(null);
$this->phones->removeElement($phone);
}
public function removePhones(): void
{
foreach ($this->phones as $phone) {
$this->removePhone($phone);
}
}
/**
* Get phones.
*/
#[Serializer\Groups(['List', 'Details', 'RelatedListingsV2', 'listingDetails'])]
#[Serializer\VirtualProperty]
#[Serializer\Expose]
public function getPhones(): ArrayCollection
{
return $this->listMainListingPhonesFromUser();
}
/**
* Get Mapped Phones For V4.
*/
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'ProjectSearchV4', 'locationListingV2'])]
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('phones')]
#[Serializer\Expose]
public function getMappedPhones(): array
{
$phones = [];
/** @var $phone ListingPhone */
foreach ($this->getPhones() as $phone) {
$phones[] = $phone->getPhone();
}
return $phones;
}
/**
* Get phones for listing from the user phones.
*/
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'SearchV4', 'NewLeadGeneration'])]
#[Serializer\VirtualProperty]
#[Serializer\Expose]
public function getListingPhones(): ArrayCollection
{
$phones = new ArrayCollection();
$i = 0;
/** @var UserPhone $phone */
foreach ($this->getUser()->getPhones() as $phone) {
if ($i > 2) {
break;
}
$criteria = Criteria::create()->where(Criteria::expr()->eq('number', $phone->getNumber()));
if ($phones->matching($criteria)->isEmpty() && $phone->getPhone() instanceof Phone) {
$phones->add($phone->getPhone());
}
++$i;
}
return $phones;
}
/**
* Add photos.
*/
public function addPhoto(ListingPhoto $photo): static
{
$photo->setListing($this);
$this->photos->add($photo);
return $this;
}
/**
* Set photos.
*/
public function setPhotos($photos): static
{
foreach ($photos as $photo) {
$this->addPhoto($photo);
}
return $this;
}
/**
* Remove photos.
*/
public function removePhoto(ListingPhoto $photo): void
{
$this->photos->removeElement($photo);
}
/**
* @return $this
*/
public function clearPhotos(): static
{
$this->photos->clear();
return $this;
}
/**
* @return $this
*/
public function clearPhones()
{
$this->phones->clear();
return $this;
}
/**
* @return CompoundAveragePrice|null
*/
public function getCompoundAveragePrices()
{
return $this->compoundAveragePrices;
}
/**
* @param CompoundAveragePrice|null
*/
public function setCompoundAveragePrices(?CompoundAveragePrice $compoundAveragePrices): void
{
$this->compoundAveragePrices = $compoundAveragePrices;
}
/**
* @return ArrayCollection
*/
public function getPhotos($excludedTypes = [])
{
$criteria = Criteria::create();
if (!empty($excludedTypes)) {
$criteria->andWhere(Criteria::expr()->notIn('type', $excludedTypes));
}
$criteria->orderBy(['order' => Criteria::ASC]);
return $this->photos->matching($criteria);
}
/**
* @return ArrayCollection
*/
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('photos')]
public function getPhotosForSlider()
{
$slider = new ArrayCollection();
// Set the main photo as the first photo in the slider
if ($this->getMainPhoto()) {
$slider->add($this->getMainPhoto());
}
// Add all other photos, except the main photo, because It's already added
/** @var ListingPhoto $photo */
foreach ($this->getPhotos() as $photo) {
if (!$slider->contains($photo) && PhotoTypes::LOGO_PHOTO != $photo->getType()) {
$slider->add($photo);
}
}
return $slider;
}
public function buildMappedMainPhoto(): self
{
// Important for API
if ($this->getPhotos()->count() <= 0) {
return $this;
}
/* @var ListingPhoto $photo */
$mainPhotos = $this->photos->filter(fn ($photo) => PhotoTypes::MAIN_PHOTO == $photo->getType());
$mappedMainPhoto = $mainPhotos->first() ?: $this->getPhotos()->first();
if ($mappedMainPhoto instanceof ListingPhoto) {
$this->mappedMainPhoto = $this->mapPhoto($mappedMainPhoto);
}
return $this;
}
public function setMappedMainPhoto(?array $mainPhoto): self
{
$this->mappedMainPhoto = $mainPhoto;
return $this;
}
#[Serializer\Groups(['DefaultV4', 'MyListing', 'MyListings', 'SearchV4', 'ProjectSearchV4', 'RelatedListingsV2', 'locationListingV2', 'homeCompoundV2'])]
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('mainPhoto')]
public function getMappedMainPhoto(): ?array
{
return $this->mappedMainPhoto;
}
private function mapPhoto(ListingPhoto $listingPhoto): array
{
return [
'id' => $listingPhoto->getId(),
'name' => $listingPhoto->getName(),
'caption' => $listingPhoto->getCaption(),
'order' => $listingPhoto->getOrder(),
'type' => $listingPhoto->getTypeName(),
'photo' => $listingPhoto->getFile(),
'file' => $listingPhoto->getPath(),
'thumbnails' => [],
];
}
public function buildMappedPhotos(): self
{
$mainPhotoId = null;
// Set the main photo as the first photo in the slider
if ($this->getMainPhoto() instanceof ListingPhoto) {
$mainPhoto = $this->getMainPhoto();
$mainPhotoId = $mainPhoto->getId();
$this->mappedPhotos[] = $this->mapPhoto($mainPhoto);
}
/** @var ListingPhoto $photo */
foreach ($this->getPhotos() as $photo) {
if (PhotoTypes::LOGO_PHOTO != $photo->getType()) {
if (($mainPhotoId && $mainPhotoId == $photo->getId()) || !$photo instanceof ListingPhoto) {
continue;
}
$this->mappedPhotos[] = $this->mapPhoto($photo);
}
}
return $this;
}
/**
* @return array
*/
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'RelatedListingsV2'])]
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('photos')]
public function getMappedPhotos()
{
return $this->mappedPhotos;
}
public function setMappedPhotos(array $mappedPhotos): self
{
$this->mappedPhotos = $mappedPhotos;
return $this;
}
#[Serializer\Groups(['List', 'Api', 'Preview'])]
#[Serializer\VirtualProperty]
public function getMainPhoto(): ?ListingPhoto
{
// Important for API
if ($this->getPhotos()->count() <= 0) {
return null;
}
/* @var ListingPhoto $photo */
$mainPhotos = $this->photos->filter(fn ($photo) => PhotoTypes::MAIN_PHOTO == $photo->getType());
return $mainPhotos->first() ?: $this->getPhotos()->first();
}
/**
* @return int
*/
#[Serializer\Groups(['DefaultV4', 'MyListing', 'SearchV4', 'ProjectSearchV4'])]
#[Serializer\VirtualProperty]
public function getPhotosCount()
{
return $this->getPhotos()->count();
}
/**
* @return ListingPhoto|null
*/
public function getLogo()
{
/** @var ArrayCollection $logos */
$logos = $this->photos->filter(fn (ListingPhoto $photo) => PhotoTypes::LOGO_PHOTO == $photo->getType());
return $logos->first() ?: null;
}
/**
* @return ArrayCollection
*/
public function getLeads()
{
return $this->leads;
}
/**
* Count leads.
*
* @return int
*/
public function getLeadsCount()
{
return $this->getLeadsCounter();
}
/**
* Count all leads with children.
*
* @return int
*/
public function getTotalLeadsCount()
{
$leadsCount = $this->getLeadsCounter();
if ($this->getChildren()) {
/** @var self $listing */
foreach ($this->getChildren() as $listing) {
$leadsCount += $listing->getLeadsCounter();
}
}
return $leadsCount;
}
public function setLeads($leads): void
{
$this->leads = $leads;
}
/**
* @return int
*/
#[Serializer\VirtualProperty]
public function getAggregatedLeadsCount()
{
/** @var ListingFeature $lastBump */
$lastBump = $this->getLastAutoBumpUp();
/** @var ListingFeature $lastFeature */
$lastFeature = $this->getLastListingFeature();
$listingFeature = null;
if ($lastBump && $lastFeature) {
$listingFeature = ($lastBump->getLastBumpedAt() > $lastFeature->getCreatedAt()) ? $lastBump : $lastFeature;
} elseif ($lastBump) {
$listingFeature = $lastBump;
} elseif ($lastFeature) {
$listingFeature = $lastFeature;
}
return $listingFeature ?
$this->getLeadsCounter() - $listingFeature->getLeadsCountSnapshot() :
$this->getLeadsCounter();
}
/**
* Add listingFeatures.
*
* @return Listing
*/
public function addListingFeature(ListingFeature $listingFeatures)
{
$this->listingFeatures[] = $listingFeatures;
return $this;
}
/**
* Remove listingFeatures.
*/
public function removeListingFeature(ListingFeature $listingFeatures): void
{
$this->listingFeatures->removeElement($listingFeatures);
}
/**
* Get listingFeatures.
*
* @return Collection
*/
public function getListingFeatures()
{
return $this->listingFeatures;
}
/**
* @return ListingFeature
*/
public function getLastAutoBumpUp()
{
$criteria = new Criteria();
$criteria
->where(Criteria::expr()->eq('type', ListingFeatures::BUMP_UP))
->andWhere(Criteria::expr()->gte('expiresAt', new \DateTime()))
->orWhere(Criteria::expr()->isNull('expiresAt'))
->orderBy([
'id' => Criteria::DESC,
])
;
return $this->listingFeatures->matching($criteria)->first();
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('was_featured')]
#[Serializer\Groups(['List', 'Details', 'listingDetails'])]
public function wasFeatured()
{
return !$this->getCurrentListingFeature() && $this->getLastListingFeature() ? true : false;
}
/**
* Get current listing feature.
*
* @return ListingFeatures
*/
public function getCurrentListingFeature()
{
$criteria = Criteria::create()
->where(Criteria::expr()->gte('expiresAt', new \DateTime('now')))
->andWhere(Criteria::expr()->neq('type', ListingFeatures::PAID))
->andWhere(Criteria::expr()->neq('type', ListingFeatures::BUMP_UP))
->orderBy(['id' => Criteria::DESC])
->setMaxResults(1);
return $this->getListingFeatures()->matching($criteria)->first();
}
/**
* Get current listing feature expiry date.
*
* @return \DateTime|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'MyListing'])]
#[Serializer\SerializedName('feature_expires_at')]
#[Serializer\Expose]
public function getCurrentListingFeatureExpiryDate()
{
/* @var ListingFeature $listingFeature */
if ($this->isFeatured()) {
$listingFeature = $this->getCurrentListingFeature();
return $listingFeature ? $listingFeature->getExpiresAt() : null;
}
return null;
}
/**
* Get all current active listing features.
*
* @return ListingFeatures
*/
public function getCurrentListingFeatures()
{
$criteria = Criteria::create()
->where(Criteria::expr()->orX(
Criteria::expr()->isNull('expiresAt'),
Criteria::expr()->gte('expiresAt', new \DateTime('now'))
))
->orderBy(['id' => Criteria::DESC]);
return $this->getListingFeatures()->matching($criteria);
}
/**
* Get last listing feature.
*/
public function getLastListingFeature()
{
$criteria = Criteria::create()
->andWhere(Criteria::expr()->neq('type', ListingFeatures::PAID))
->andWhere(Criteria::expr()->neq('type', ListingFeatures::BUMP_UP))
->orderBy(['id' => Criteria::DESC])
->setMaxResults(1);
return $this->getListingFeatures()->matching($criteria)->first();
}
/**
* Get the latest featured credit transaction for listing publishing.
*
* @param mixed $type = null
*
* @throws \Exception
*/
public function getFeaturedPublicationCredit(mixed $type = null)
{
if (!$type) {
$lastFeaturedType = $this->getLastListingFeature() ? $this->getLastListingFeature()->getType() : [];
$type = !empty($lastFeaturedType) ? [$lastFeaturedType] : [ListingFeatures::FEATURED, ListingFeatures::SPOTLIGHT, ListingFeatures::PREMIUM, ListingFeatures::SPONSORED];
}
$criteria = Criteria::create()
->where(Criteria::expr()->orX(
Criteria::expr()->isNull('expiresAt'),
Criteria::expr()->gte('expiresAt', new \DateTime('now'))
))
->andWhere(Criteria::expr()->in('type', $type))
->orderBy(['id' => Criteria::DESC])
->setMaxResults(1);
return $this->getListingFeatures()->matching($criteria)->first();
}
/**
* Get the latest credit transaction for listing publishing.
*
* @return ListingFeature
*/
public function getPublicationCredit()
{
$criteria = Criteria::create()
->where(Criteria::expr()->orX(
Criteria::expr()->isNull('expiresAt'),
Criteria::expr()->gte('expiresAt', new \DateTime('now'))
))
->andWhere(Criteria::expr()->eq('type', ListingFeatures::PAID))
->orderBy(['id' => Criteria::DESC])
->setMaxResults(1);
return $this->getListingFeatures()->matching($criteria)->first();
}
/**
* Get the latest credit transaction for special add listing publishing.
*
* @return ListingFeature
*/
public function getSpecialPublicationCredit()
{
$criteria = Criteria::create()
->where(Criteria::expr()->orX(
Criteria::expr()->isNull('expiresAt'),
Criteria::expr()->gte('expiresAt', new \DateTime('now'))
))
->andWhere(Criteria::expr()->in('type', [ListingFeatures::SPONSORED, ListingFeatures::SPOTLIGHT]))
->orderBy(['id' => Criteria::DESC])
->setMaxResults(1);
return $this->getListingFeatures()->matching($criteria)->first();
}
/**
* Get all credit transactions for listing that not expired yet.
*
* @return ListingFeature
*/
public function getNotExpiredCredit()
{
$criteria = Criteria::create()
->where(Criteria::expr()->orX(
Criteria::expr()->isNull('expiresAt'),
Criteria::expr()->gte('expiresAt', new \DateTime('now'))
))
->orderBy(['id' => Criteria::DESC]);
return $this->getListingFeatures()->matching($criteria)->toArray();
}
/**
* Get translations.
*
* @return ArrayCollection
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Default', 'List'])]
#[Serializer\SerializedName('translations')]
#[Serializer\Expose]
public function getTranslations()
{
return $this->translations;
}
public function deleteExistingTranslation($field, $locale): void
{
/** @var ListingTranslation $translation */
foreach ($this->getTranslations() as $translation) {
if ($translation->getField() == $field && $translation->getLocale() == $locale) {
$this->removeTranslation($translation);
}
}
}
/**
* Add translation.
*
* @return Listing
*/
public function addTranslation(ListingTranslation $translation)
{
if (!$this->translations->contains($translation)) {
$this->translations->add($translation);
$translation->setObject($this);
}
return $this;
}
/**
* Set Translations.
*
* @return Listing
*/
public function setTranslations($translations)
{
foreach ($translations as $translation) {
$this->addTranslation($translation);
}
return $this;
}
/**
* Remove translation.
*
* @return Listing
*/
public function removeTranslation(ListingTranslation $translation)
{
if ($this->translations->contains($translation)) {
$this->translations->removeElement($translation);
}
return $this;
}
/**
* @return $this
*/
public function clearTranslations()
{
$this->translations->clear();
return $this;
}
/**
* Set campaign.
*
* @param string $campaign
*
* @return Listing
*/
public function setCampaign($campaign)
{
$this->campaign = $campaign;
return $this;
}
/**
* Get campaign.
*
* @return string
*/
public function getCampaign()
{
return $this->campaign;
}
/**
* Set propertyView.
*
* @param int $propertyView
*
* @return Listing
*/
public function setPropertyView($propertyView)
{
$this->propertyView = $propertyView;
return $this;
}
/**
* Get propertyView.
*
* @return int
*/
public function getPropertyView()
{
return $this->propertyView;
}
#[Serializer\SerializedName('property_view_label')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'listingDetails'])]
#[Serializer\Expose]
public function getPropertyViewLabel()
{
return ListingPropertyView::getLabel($this->getPropertyView());
}
#[Serializer\SerializedName('property_view_label')]
#[Serializer\VirtualProperty]
#[Serializer\Since('v2.12')]
#[Serializer\Expose]
public function getPropertyViewTranslatedLabel()
{
return $this->getTranslatedPropertyViewLabel();
}
#[Serializer\SerializedName('property_view')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4'])]
#[Serializer\Expose]
public function getPropertyViewName()
{
return ListingPropertyView::getNameByConstant($this->getPropertyView());
}
/**
* @return $this
*/
public function setPropertyViewLabel($label)
{
$this->propertyViewLabel = $label;
return $this;
}
/**
* Set paymentMethod.
*
* @param int $paymentMethod
*
* @return Listing
*/
public function setPaymentMethod($paymentMethod)
{
if (
ListingSections::FOR_RENT == $this->getSection()->getId()
) {
$paymentMethod = ListingPaymentMethod::CASH;
}
$this->paymentMethod = $paymentMethod;
return $this;
}
/**
* Set paymentMethod Label.
*
* @param int $paymentMethod
*
* @return Listing
*/
public function setPaymentMethodLabel($paymentMethod)
{
$this->paymentMethodLabel = $paymentMethod;
return $this;
}
#[Serializer\SerializedName('payment_method_label')]
#[Serializer\VirtualProperty]
#[Serializer\Since('v2.12')]
#[Serializer\Expose]
public function getPaymentMethodLabelTranslated()
{
return $this->paymentMethodLabel;
}
/**
* @return int|null
*/
#[Serializer\SerializedName('user')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4'])]
#[Serializer\Expose]
public function getUserId()
{
return $this->getUser() instanceof User ? $this->getUser()->getId() : null;
}
/**
* Get paymentMethod.
*
* @return int
*/
public function getPaymentMethod()
{
if (
ListingSections::FOR_RENT == $this->getSection()->getId()
) {
$this->paymentMethod = ListingPaymentMethod::CASH;
}
return $this->paymentMethod;
}
#[Serializer\SerializedName('paymentMethodLabel')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Default', 'SearchV4', 'listingDetails'])]
#[Serializer\Expose]
public function getPaymentMethodLabel()
{
return ListingPaymentMethod::getLabel($this->getPaymentMethod());
}
/**
* Add listingNotification.
*
* @return Listing
*/
public function addListingNotification(ListingNotification $listingNotification)
{
$this->ListingNotifications[] = $listingNotification;
return $this;
}
/**
* Remove listingNotification.
*/
public function removeListingNotification(ListingNotification $listingNotification): void
{
$this->ListingNotifications->removeElement($listingNotification);
}
/**
* Get listingNotifications.
*
* @return Collection
*/
public function getListingNotifications()
{
return $this->ListingNotifications;
}
/**
* Add rejections.
*
* @return Listing
*/
public function addRejection(Rejection $rejections)
{
$this->rejections[] = $rejections;
return $this;
}
/**
* Add rejections.
*
* @param ArrayCollection $rejections
*
* @return Listing
*/
public function addRejections($rejections)
{
$this->rejections = $rejections;
return $this;
}
/**
* Remove rejections.
*/
public function removeRejections(Rejection $rejections): void
{
$this->rejections->removeElement($rejections);
}
/**
* Get rejections.
*
* @return Collection
*/
public function getRejections()
{
return $this->rejections;
}
public function setRejections($rejections): void
{
$this->rejections = $rejections;
}
/**
* Set phoneCounter.
*
* @param int $phoneCounter
*
* @return Listing
*/
public function setPhoneCounter($phoneCounter)
{
$this->phoneCounter = $phoneCounter;
return $this;
}
/**
* Get phoneCounter.
*
* @return int
*/
public function getPhoneCounter()
{
return $this->phoneCounter;
}
/**
* Set messagesCounter.
*
* @param int $messagesCounter
*
* @return Listing
*/
public function setMessagesCounter($messagesCounter)
{
$this->messagesCounter = $messagesCounter;
return $this;
}
/**
* Get messagesCounter.
*
* @return int
*/
public function getMessagesCounter()
{
return $this->messagesCounter;
}
/**
* @return int
*/
public function getFinalPrice()
{
return $this->finalPrice;
}
/**
* @param int $finalPrice
*/
public function setFinalPrice($finalPrice): void
{
$this->finalPrice = $finalPrice;
}
/**
* @return string
*/
public function getSourceOfSale()
{
return $this->sourceOfSale;
}
/**
* @param string $sourceOfSale
*/
public function setSourceOfSale($sourceOfSale): void
{
$this->sourceOfSale = $sourceOfSale;
}
/**
* @return string
*/
public function getDeleteReason()
{
return $this->deleteReason;
}
/**
* @param string $deleteReason
*/
public function setDeleteReason($deleteReason): void
{
$this->deleteReason = $deleteReason;
}
/**
* @return string
*/
public function getDeleteReasonDetails()
{
return $this->deleteReasonDetails;
}
/**
* @param string $deleteReasonDetails
*/
public function setDeleteReasonDetails($deleteReasonDetails): void
{
$this->deleteReasonDetails = $deleteReasonDetails;
}
public function getInteractions()
{
return $this->interactions;
}
public function setInteractions($interactions): void
{
$this->interactions = $interactions;
}
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('logo')]
#[Serializer\Groups(['ProjectSearchV4', 'ProjectDetailsV4', 'locationListingV2'])]
public function getSerializedLogo()
{
// Giving priority for listing logo then userLogo. value set on ListingPreSerializerListener.
return $this->getListingLogo() ?: ($this->getUserLogo() ?: null);
}
/**
* @return string
*/
public function getUserLogo()
{
return $this->userLogo;
}
/**
* @param string $userLogo
*/
public function setUserLogo($userLogo): void
{
$this->userLogo = $userLogo;
}
public function getValidUserLogo(): ?Photo
{
if ($user = $this->getUser()) {
if ($user->hasValidAccessToLogoExposure()) {
return $user->getLogo();
}
}
return null;
}
/**
* @return string
*/
public function getListingLogo()
{
return $this->listingLogo;
}
/**
* @param string $listingLogo
*/
public function setListingLogo($listingLogo): void
{
$this->listingLogo = $listingLogo;
}
public function setTranslatableLocale($locale): void
{
$this->locale = $locale;
}
/**
* @return bool
*/
public function canChangeScrapedListing()
{
return ListingCategories::SCRAPPED == $this->category
&& ScrapedListing::USER_EMAIL === $this->getUser()->getEmail();
}
/**
* @return bool
*/
public function validateScrapedListingHash($hash = null)
{
$secretHash = md5($this->getPhones()->first()->getNumber().''.$this->getId());
if ($hash === $secretHash) {
return true;
}
return false;
}
public function getSource()
{
return $this->source;
}
public function setSource($source): void
{
$this->source = $source;
}
public function setElasticSearchScore($elasticSearchScore): void
{
$this->elasticSearchScore = $elasticSearchScore;
}
/**
* @return float
*/
public function getElasticSearchScore()
{
return $this->elasticSearchScore;
}
/**
* @param float $qualityScore
*/
public function setQualityScore($qualityScore): void
{
$this->qualityScore = $qualityScore;
}
/**
* @return float
*/
public function getQualityScore()
{
return $this->photos->count();
}
public function getLeadsCounter(): int
{
return $this->leadsCounter;
}
/**
* @param int $leadsCounter
*
* @return Listing
*/
public function setLeadsCounter($leadsCounter)
{
$this->leadsCounter = $leadsCounter;
return $this;
}
/**
* Get price per meter.
*/
public function calculatePricePerMeter(): ?float
{
return $this->getArea() > 0 ? $this->getPrice() / $this->getArea() : null;
}
/**
* @return int
*/
public function getImpressions()
{
return $this->impressions;
}
/**
* @param int $impressions
*
* @return Listing
*/
public function setImpressions($impressions)
{
$this->impressions = $impressions;
return $this;
}
/**
* @return $this
*/
public function setImpressionsMonthlyCount(?int $impressions = null)
{
$this->impressionsMonthlyCount = $impressions;
return $this;
}
/**
* @return int
*/
public function getImpressionsMonthlyCount()
{
return $this->impressionsMonthlyCount;
}
/**
* @return $this
*/
public function setImpressionsWeeklyCount(?int $impressions = null)
{
$this->impressionsWeeklyCount = $impressions;
return $this;
}
public function getImpressionsWeeklyCount()
{
return $this->impressionsWeeklyCount;
}
/**
* Get impressionUpdatedAt.
*
* @return \DateTime
*/
public function getImpressionUpdatedAt()
{
return $this->impressionUpdatedAt;
}
/**
* Set impressionUpdatedAt.
*
* @param \DateTime $impressionUpdatedAt
*
* @return Listing
*/
public function setImpressionUpdatedAt($impressionUpdatedAt)
{
$this->impressionUpdatedAt = $impressionUpdatedAt;
return $this;
}
public function getCompoundStatus()
{
return $this->compoundStatus;
}
public function setCompoundStatus($compoundStatus)
{
$this->compoundStatus = $compoundStatus;
return $this;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('compound_status')]
public function getCompoundStatusLabel()
{
return CompoundStatus::getLabel($this->getCompoundStatus());
}
public function setCompoundStatusLabel($label): void
{
$this->compoundStatusLabel = $label;
}
public function getPriceLevel()
{
return $this->priceLevel;
}
public function setPriceLevel($priceLevel)
{
$this->priceLevel = $priceLevel;
return $this;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('price_level')]
public function getPriceLevelLabel()
{
if (!$this->getPriceLevel() && $this->hasParent()) {
return ListingPriceLevel::getLabel($this->getParent()->getPriceLevel());
}
return ListingPriceLevel::getLabel($this->getPriceLevel());
}
/**
* Check if the Listing desn't have the flag and fall back to the parent.
*
* @return string
*/
public function isParentCommercial()
{
if (!$this->isCommercial() && $this->hasParent()) {
return $this->getParent()->isCommercial();
}
return $this->isCommercial();
}
public function setPriceLevelLabel($label): void
{
$this->priceLevelLabel = $label;
}
public function getPricePerMeter()
{
return $this->pricePerMeter;
}
public function setPricePerMeter($pricePerMeter)
{
$this->pricePerMeter = $pricePerMeter;
return $this;
}
public function getChildrenArea()
{
$result = [];
if (empty($this->getChildren())) {
return;
}
foreach ($this->getChildren() as $child) {
$result['area'] = (int) $child->getArea();
}
return $result;
}
public function getChildrenPrice()
{
$result = [];
if (empty($this->getChildren())) {
return;
}
foreach ($this->getChildren() as $child) {
$result['price'] = (int) $child->getPrice();
}
return $result;
}
public function getChildrenPricePerMeter()
{
$result = [];
if (empty($this->getChildren())) {
return;
}
foreach ($this->getChildren() as $child) {
$result['pricePerMeter'] = (int) $child->getPricePerMeter();
}
return $result;
}
public function getChildrenAttributesList()
{
$result = [];
if (empty($this->getChildren())) {
return;
}
foreach ($this->getChildren() as $child) {
foreach ($child->getAttributes() as $attribute) {
$result[$attribute->getCustomField()->getName()] = $attribute->getValue();
}
}
return $result;
}
/**
* Returns array of children's property types.
*/
public function getChildrenPropertyType()
{
$propertyType = [];
if (empty($this->getLiveChildren())) {
return;
}
foreach ($this->getLiveChildren() as $child) {
$propertyType['id'] = $child->getPropertyType()->getId();
}
return $propertyType;
}
/**
* Returns array of children's property types.
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('childrenPropertyTypes')]
#[Serializer\Groups(['locationListingV2', 'homeCompoundV2'])]
#[Serializer\Expose]
public function getChildrenPropertyTypeTitle(): array
{
$propertyTypes = [];
if (empty($this->getLiveChildren())) {
return [];
}
foreach ($this->getLiveChildren() as $child) {
$propertyTypes[] = $child->getPropertyType()->getTitle();
}
return array_values(array_unique($propertyTypes));
}
public function isBumped(): bool
{
return (bool) $this->isBumped;
}
public function setBumped(bool $status = true): self
{
$this->isBumped = $status;
return $this;
}
/**
* @return bool
*/
public function isSendEmail()
{
return $this->isSendEmail;
}
/**
* @return $this
*/
public function setIsSendEmail(bool $isSendEmail = true)
{
$this->isSendEmail = $isSendEmail;
return $this;
}
public function isAvailabilityEmailSentl(): bool
{
return $this->isAvailabilityEmailSent;
}
/**
* @return $this
*/
public function setIsAvailabilityEmailSent(bool $isAvailabilityEmailSent = false)
{
$this->isAvailabilityEmailSent = $isAvailabilityEmailSent;
return $this;
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DataLayer', 'Details', 'Search', 'DefaultV4', 'SearchV4', 'listingDetails'])]
#[Serializer\Expose]
public function hasParent()
{
return !empty($this->parent);
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'Search', 'DefaultV4', 'SearchV4', 'listingDetails'])]
#[Serializer\Expose]
public function isProjectOrUnit(): bool
{
return $this->hasParent() || $this->isProject();
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DataLayer'])]
#[Serializer\Expose]
public function hasChildren(): bool
{
return $this->isProject();
}
/**
* Gets Geo point.
*/
public function getGeoPoint()
{
if (!$this->getCenterLat() || !$this->getCenterLng()) {
return;
}
return implode(',', [$this->getCenterLat(), $this->getCenterLng()]);
}
/**
* @return ArrayCollection
*/
public function getRates(?\DateTime $startDate = null)
{
$criteria = Criteria::create()
->andWhere(Criteria::expr()->lt(
'createdAt',
new \DateTime()
))
->andWhere(Criteria::expr()->gt(
'createdAt',
$startDate ?? new \DateTime(sprintf('-%d Days', ListingRateConstant::DATE_RANGE_START))
));
return $this->rates->matching($criteria);
}
/**
* @return int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Rates'])]
#[Serializer\Expose]
public function getTotalRates(?\DateTime $startDate = null)
{
$totalRates = $this->getRates($startDate)->count();
if (!$totalRates) {
return null;
}
return round(($this->getPositiveRatesCount($startDate) / $totalRates) * 100);
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'MyListing'])]
#[Serializer\SerializedName('score')]
#[Serializer\Expose]
public function getRateScore()
{
return $this->getTotalRates();
}
public function setTotalRates($totalRates): self
{
$this->totalRates = $totalRates;
return $this;
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Rates'])]
#[Serializer\SerializedName('positive_rates')]
#[Serializer\Expose]
public function getPositiveRatesCount(?\DateTime $startDate = null)
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('rate', ListingRateConstant::SATISFYING));
return $this->getRates($startDate)->matching($criteria)->count();
}
/**
* @return int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Rates'])]
#[Serializer\SerializedName('negative_rates')]
#[Serializer\Expose]
public function getNegativeRatesCount(?\DateTime $startDate = null)
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('rate', ListingRateConstant::UNSATISFYING));
return $this->getRates($startDate)->matching($criteria)->count();
}
/**
* @return array
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Rates'])]
#[Serializer\SerializedName('rates_reasons')]
#[Serializer\Expose]
public function getRateReasonsCollection()
{
return $this->rateReasonsCollection;
}
/**
* @return array
*/
public function setRateReasonsCollection(array $rateReasonsCollection): self
{
$this->rateReasonsCollection = new ArrayCollection($rateReasonsCollection);
return $this;
}
/**
* @return array
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Rates'])]
#[Serializer\SerializedName('rates_comments')]
#[Serializer\Expose]
public function getRatesComments()
{
$criteria = Criteria::create()
->orderBy(['createdAt' => Criteria::DESC]);
$comments = [];
foreach ($this->getRates()->matching($criteria) as $rate) {
$comments[] = $rate->getcomment();
}
return $comments;
}
public function getSynced()
{
return $this->synced;
}
/**
* @return self
*/
public function setSynced(bool $synced)
{
$this->synced = $synced;
return $this;
}
/**
* @deprecated used to migrate to Skull service. Not needed anymore.
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'Default', 'ActivitiesData'])]
#[Serializer\Expose]
public function getReferenceId()
{
return $this->id;
}
/**
* @param int $referenceId
*
* @return self
*/
public function setReferenceId($referenceId)
{
$this->referenceId = $referenceId;
return $this;
}
public function setFeaturedTypeLabel($featuredTypeLabel): void
{
$this->featuredTypeLabel = $featuredTypeLabel;
}
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('featuredType')]
#[Serializer\Groups(['List', 'Details', 'listingDetails', 'RelatedListingsV2'])]
#[Serializer\Expose]
public function getFeaturedType()
{
return ['type' => $this->getFeatured(), 'label' => $this->featuredTypeLabel];
}
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('featuredType')]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'ProjectSearchV4', 'locationListingV2', 'MyListings'])]
public function getFeaturedName()
{
return ListingFeaturedTypes::getFeaturedName($this->getFeatured());
}
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('referenceId')]
#[Serializer\Expose]
#[Serializer\Groups(['DefaultV4', 'SearchV4'])]
public function getReferencedV4Id()
{
return $this->getId();
}
/**
* @return favourite
*/
public function getFavourite()
{
return $this->favourite;
}
public function setFavourite(array $favourites): self
{
foreach ($favourites as $favourite) {
$this->addFavourite($favourites);
}
return $this;
}
/**
* Add favourite.
*
* @return Listing
*/
public function addFavourite(Favourite $favourite)
{
$favourite->setListing($this);
$this->favourite[] = $favourite;
return $this;
}
public function isPendingFeaturing()
{
return $this->isPendingFeaturing;
}
/**
* @return $this
*/
public function setPendingFeaturing($pendingFeaturing)
{
$this->isPendingFeaturing = $pendingFeaturing;
return $this;
}
public function getPendingFeaturingType()
{
return $this->pendingFeaturingType;
}
/**
* @return Listing
*/
public function setPendingFeaturingType($pendingFeaturingType)
{
$this->pendingFeaturingType = $pendingFeaturingType;
return $this;
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('is_favourite')]
#[Serializer\Groups(['List', 'Details'])]
public function getIsFavourite()
{
return $this->isFavourite;
}
/**
* @return Listing
*/
public function setIsFavourite(bool $isFavourite)
{
$this->isFavourite = $isFavourite;
return $this;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('user_note')]
#[Serializer\Groups(['List', 'Details'])]
public function getUserNote()
{
return $this->userNote;
}
/**
* @return Listing
*/
public function setUserNote(?string $userNote)
{
$this->userNote = $userNote;
return $this;
}
public function isProject(): bool
{
return ListingCategories::PROJECTS == $this->getCategory();
}
/**
* @return int
*/
public function getListingFeaturesFromFeaturedType()
{
return match ($this->getFeatured()) {
ListingFeaturedTypes::SPOTLIGHT => ListingFeatures::SPOTLIGHT,
ListingFeaturedTypes::SPONSORED => ListingFeatures::SPONSORED,
ListingFeaturedTypes::PREMIUM => ListingFeatures::PREMIUM,
default => ListingFeatures::FEATURED,
};
}
/**
* @return bool
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('isExcludedFromWhatsApp')]
#[Serializer\Groups(['List', 'Details', 'DefaultV4'])]
public function getIsExcludedFromWhatsApp()
{
if (
!empty($this->getUser()->getTeam())
&& TeamCategories::EXCLUDED_FROM_WHATSAPP == $this->getUser()->getTeam()->getCategory()
&& ListingCategories::PROJECTS == $this->getCategory()
) {
return true;
}
return false;
}
/**
* @return int|null
*/
public function getRateStatus()
{
return $this->rateStatus;
}
/**
* @return Listing
*/
public function setRateStatus(?int $rateStatus)
{
$this->rateStatus = $rateStatus;
return $this;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
public function getRateStatusLabel()
{
return ListingRateStatus::getLabel($this->getRateStatus());
}
/**
* @return boolean||null
*/
public function getIsRateReviewed()
{
return $this->isRateReviewed;
}
/**
* @return Listing
*/
public function setIsRateReviewed(?bool $isRateReviewed)
{
$this->isRateReviewed = $isRateReviewed;
return $this;
}
public function isHold(): bool
{
return (bool) $this->isHold;
}
public function setIsHold(bool $isHold = true): self
{
$this->isHold = $isHold;
return $this;
}
#[Serializer\VirtualProperty]
public function getRateReviewStatusLabel(): string
{
return ListingRateReviewStatus::getLabel($this->getIsRateReviewed() ? ListingRateReviewStatus::REVIEWED : ListingRateReviewStatus::PENDING_REVIEW);
}
/**
* @return array
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Rates'])]
#[Serializer\SerializedName('reported_date')]
#[Serializer\Expose]
public function getReportedDate()
{
return $this->reportedDate;
}
/**
* @param \DateTime|string $reportedDate
*
* @return array
*/
public function setReportedDate($reportedDate): self
{
$this->reportedDate = $reportedDate;
return $this;
}
/**
* @return array
*/
public function getReasonIds()
{
$rateReasonsCollection = $this->getRateReasonsCollection();
if (!isset($rateReasonsCollection['reason_ids'])) {
return [];
}
$reasonsIds = [];
foreach ($rateReasonsCollection['reason_ids'] as $key => $value) {
$reasonsIds[] = [
'key' => $key,
'value' => $value,
];
}
return $reasonsIds;
}
/**
* @return array
*/
public function getReasonLabels()
{
$rateReasonsCollection = $this->getRateReasonsCollection();
if (!isset($rateReasonsCollection['reason_labels'])) {
return [];
}
$reasonLabels = [];
foreach ($rateReasonsCollection['reason_labels'] as $label => $count) {
$reasonLabels[] = [
'label' => $label,
'count' => $count,
];
}
return $reasonLabels;
}
private function listMainListingPhonesFromUser(): ArrayCollection
{
$phones = new ArrayCollection();
if ($this->getUser()) {
foreach ($this->getUser()->getMainPhones(UserMainPhones::BUILD_FORMATTER_USER_PHONES) as $phone) {
if ($phone) {
$phones->add($this->castUserPhonesAsListingPhones($phone));
}
}
}
return $phones;
}
private function castUserPhonesAsListingPhones(UserPhone $userPhone): ListingPhone
{
$phone = $userPhone->getPhone();
$phone->setWhatsApp($userPhone->isWhatsApp());
return new ListingPhone(
convert_arabic_numbers($phone->getNumber()),
$this,
$phone->getCountryCode(),
$phone
);
}
/**
* @param Listing $parentOfSimilarListing
*
* @return Listing
*/
public function setParentOfSimilarListing($parentOfSimilarListing)
{
$this->parentOfSimilarListing = $parentOfSimilarListing;
return $this;
}
/**
* @return Listing
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('parentOfSimilarListing')]
#[Serializer\Groups(['SimilarListings'])]
#[Serializer\Expose]
public function getParentOfSimilarListing()
{
return $this->parentOfSimilarListing;
}
public function isCallRequest(): bool
{
return $this->isCallRequest;
}
public function setIsCallRequest(bool $isCallRequest): self
{
$this->isCallRequest = $isCallRequest;
return $this;
}
public function getNotMigratedFields()
{
return [
'impressionUpdatedAt',
'impressions',
];
}
public function generateCoordinates(): self
{
if ($this->getLocation() && (!$this->centerLat || !$this->centerLng)) {
/** @var Location $location */
$location = $this->location;
$this->setCenterLat($location->getLat());
$this->setCenterLng($location->getLon());
}
return $this;
}
public function buildListingAttributes(): self
{
/** @var ListingAttribute $attribute */
foreach ($this->attributes as $attribute) {
if (!$attribute->getCustomField() instanceof CustomField) {
continue;
}
$attributeName = $attribute->getFormattedAttributeName();
$attributeValue = $attribute->getValue();
if (null != $attributeValue) {
$this->listingAttributes[$attributeName] = $attributeValue;
}
if (ListingCustomFields::FINISH_TYPE_VALUE == $attributeName) {
$this->listingAttributes[ListingCustomFields::FINISH_TYPE_LABEL_VALUE] = $attributeValue;
}
}
return $this;
}
/**
* @return array
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('attributes')]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'RelatedListingsV2', 'MyListings'])]
#[Serializer\Expose]
public function getListingAttributesList()
{
if (empty($this->listingAttributes)) {
return null;
}
return $this->listingAttributes;
}
/**
* @return array
*/
public function setListingAttributesList(array $attributesList)
{
$this->listingAttributes = $attributesList;
return $this->listingAttributes;
}
/**
* @return float
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('latitude')]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'RelatedListingsV2'])]
#[Serializer\Expose]
public function getLatitude()
{
return $this->centerLat;
}
/**
* @return float
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('longitude')]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'RelatedListingsV2'])]
#[Serializer\Expose]
public function getLongitude()
{
return $this->centerLng;
}
/**
* @return string
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('status')]
#[Serializer\Groups(['DefaultV4', 'MyListing', 'MyListings'])]
#[Serializer\Expose]
public function getLabeledStatus()
{
return ListingStatus::getName($this->getStatus());
}
#[Serializer\SerializedName('propertyViewLabel')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'SearchV4'])]
#[Serializer\Expose]
public function getTranslatedPropertyViewLabel()
{
return $this->propertyViewLabel;
}
#[Serializer\SerializedName('paymentMethodLabel')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4'])]
#[Serializer\Expose]
public function getTranslatedPaymentMethodLabel()
{
return $this->getPaymentMethodLabelTranslated();
}
#[Serializer\SerializedName('paymentMethod')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4'])]
#[Serializer\Expose]
public function getPaymentMethodText()
{
return ListingPaymentMethod::getText($this->paymentMethod);
}
#[Serializer\SerializedName('sellerRole')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'DefaultV4', 'SearchV4'])]
#[Serializer\Expose]
public function getSellerRoleText()
{
return ListingSellerRoles::getName($this->getSellerRole());
}
public function generateAddress(): self
{
if ($this->address || !$this->location) {
return $this;
}
$this->setAddress($this->getLocation()->getTitleFullPath());
return $this;
}
public function setIsPriceNegotiable(bool $isPriceNegotiable, ?CustomField $isPriceNegotiableAttribute = null): self
{
if (!$isPriceNegotiableAttribute) {
return $this;
}
/** @var ListingAttribute $attribute */
foreach ($this->attributes as $attribute) {
if ($attribute->getCustomField()->getId() === $isPriceNegotiableAttribute->getId()) {
$attribute->setValue($isPriceNegotiable);
return $this;
}
}
$listingAttribute = new ListingAttribute();
$listingAttribute->setCustomField($isPriceNegotiableAttribute);
$listingAttribute->setValue($isPriceNegotiable);
$this->addAttribute($listingAttribute);
return $this;
}
#[Serializer\SerializedName('isPriceNegotiable')]
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'SearchV4'])]
#[Serializer\Expose]
public function getIsPriceNegotiable(): bool
{
/** @var ListingAttribute $attribute */
foreach ($this->attributes as $attribute) {
if (ListingCustomFields::IS_NEGOTIABLE_NAME === $attribute->getCustomField()->getName()) {
return true;
}
}
return false;
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Statistics'])]
#[Serializer\SerializedName('clickRate')]
#[Serializer\Expose]
public function getClickRate(): float
{
$impressions = $this->getImpressions() > 0 ? $this->getImpressions() : 1;
return round(($this->getViews() / $impressions) * 100, 2);
}
/**
* @return int|null
* @return float|int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Statistics'])]
#[Serializer\SerializedName('contactRate')]
#[Serializer\Expose]
public function getContactRate()
{
return ($this->getLeadsCounter() / ($this->getViewsCount() ?: 1)) * 100;
}
/**
* @return float|int
*/
public function getComputedContactRate()
{
if (empty($this->leadsCounter) || empty($this->views)) {
return 0;
}
return round($this->leadsCounter / $this->views * 100, 2);
}
/**
* @param float
*
* @return self
*/
public function setContactRate(float $contactRate)
{
$this->contactRate = $contactRate;
return $this;
}
/**
* @return float|int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Statistics', 'MyListing'])]
#[Serializer\SerializedName('impressionsCount')]
#[Serializer\Expose]
public function getImpressionsCount()
{
return $this->getImpressions() ?: 0;
}
/**
* @return float|int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Statistics', 'MyListing', 'MyListings'])]
#[Serializer\SerializedName('viewsCount')]
#[Serializer\Expose]
public function getViewsCount()
{
return $this->getViews() ?: 0;
}
/**
* @return float|int
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Statistics', 'MyListing', 'MyListings'])]
#[Serializer\SerializedName('leadsCount')]
#[Serializer\Expose]
public function getLeadCount()
{
return $this->getLeadsCounter() ?: 0;
}
/**
* @return int|null
*/
public function isCommercial()
{
return $this->isCommercial;
}
public function setIsCommercial(int $isCommercial): void
{
$this->isCommercial = $isCommercial;
}
/**
* @return string|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'SearchV4'])]
#[Serializer\SerializedName('category')]
#[Serializer\Expose]
public function getCategoryByName()
{
return ListingCategories::getLabel($this->getCategory());
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Default', 'Details', 'listingDetails'])]
#[Serializer\SerializedName('categoryLabel')]
#[Serializer\Expose]
public function getCategoryLabel(): ?string
{
return $this->getCategoryName();
}
/**
* @return int|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Statistics', 'MyListing'])]
#[Serializer\SerializedName('messagesCount')]
#[Serializer\Expose]
public function getMessagesCount()
{
return $this->getMessagesCounter() ?: 0;
}
/**
* Get WhatsApp Number.
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('whatsAppNumber')]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'ProjectDetailsV4', 'ProjectSearchV4', 'RelatedListingsV2', 'locationListingV2', 'listingDetails'])]
public function getWhatsAppNumber()
{
$user = $this->getUser();
if ($user->getWhatsAppNumber()) {
$whatsAppNumber = $user->getWhatsAppNumber()->getNumber();
if (!preg_match('/^\+\d+$/', (string) $whatsAppNumber)) {
return $user->getCountryCode().$whatsAppNumber;
}
return $whatsAppNumber;
}
return null;
}
public function getTranslatableLocale()
{
return $this->locale;
}
/**
* @return Listing
*/
public function setV4Translations($translations)
{
$this->v4Translations = $translations;
return $this;
}
/**
* Get translations.
*
* @return array
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'MyListing'])]
#[Serializer\SerializedName('translations')]
#[Serializer\Expose]
public function getV4Translations()
{
return is_array($this->v4Translations) ? $this->v4Translations : [$this->v4Translations];
}
/**
* @return ArrayCollection
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'MyListing', 'MyListings'])]
#[Serializer\Expose]
public function getRejectionReasons()
{
return $this->rejections;
}
/**
* @return array
*/
public function getExistingTranslationsLanguages()
{
$existingLanguages = [];
/** @var ListingTranslation $translation */
foreach ($this->getTranslations() as $translation) {
if ((!('title' == $translation->getField() || 'description' == $translation->getField()))
|| \in_array($translation->getLocale(), $existingLanguages) || !$translation->getContent()
) {
continue;
}
$existingLanguages[] = $translation->getLocale();
}
return $existingLanguages;
}
public function isShownInHomepage(): bool
{
return $this->isShownInHomepage;
}
public function setIsShownInHomepage(bool $isShownInHomepage): self
{
$this->isShownInHomepage = $isShownInHomepage;
return $this;
}
public function isResale(): bool
{
return $this->isResale;
}
public function setIsResale(bool $isResale): self
{
$this->isResale = $isResale;
return $this;
}
public function setIsRent(bool $isRent): self
{
$this->isRent = $isRent;
return $this;
}
public function isRent(): bool
{
return $this->isRent;
}
public function setIsPrimary(bool $isPrimary): self
{
$this->isPrimary = $isPrimary;
return $this;
}
public function isPrimary(): bool
{
return $this->isPrimary;
}
/**
* @return boolean||null
*/
public function getIsMortgageApproved()
{
return $this->isMortgageApproved;
}
public function setIsMortgageApproved(?bool $isMortgageApproved): self
{
$this->isMortgageApproved = $isMortgageApproved;
return $this;
}
public function getRatesNotes()
{
return $this->ratesNotes;
}
public function getRatesNote()
{
if ($this->ratesNotes->isEmpty()) {
return null;
}
return $this->ratesNotes->last();
}
public function setRatesNotes($ratesNotes): void
{
$this->ratesNotes = $ratesNotes;
}
public function getMetaTitle(): ?string
{
return $this->metaTitle;
}
public function setMetaTitle(?string $metaTitle): self
{
$this->metaTitle = $metaTitle;
return $this;
}
public function getMetaDescription(): ?string
{
return $this->metaDescription;
}
public function setMetaDescription(?string $metaDescription): self
{
$this->metaDescription = $metaDescription;
return $this;
}
public function getIsMortgage(): bool
{
return $this->isMortgage;
}
public function setIsMortgage(bool $isMortgage): self
{
$this->isMortgage = $isMortgage;
return $this;
}
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('compound_field')]
#[Serializer\Groups(['Default', 'DefaultV4', 'ProjectSearchV4', 'ProjectDetailsV4', 'locationListingV2', 'homeCompoundV2'])]
#[Serializer\Expose]
public function getCompoundField(): ?CompoundField
{
$compoundField = $this->compoundField;
if ($this->hasParent()) {
$compoundField = $this->getParent()->getCompoundField();
}
return $compoundField;
}
public function setCompoundField(?CompoundField $compoundField): void
{
$this->compoundField = $compoundField;
}
/**
* @return array|null
*/
public function getEligibleForMortgage()
{
return $this->eligibleForMortgage;
}
public function setEligibleForMortgage(?array $eligibleForMortgage = null): self
{
$this->eligibleForMortgage = $eligibleForMortgage;
return $this;
}
public function setPropertyRegistrationStatusOptions(?array $propertyRegistrationStatusOptions = null): self
{
$this->propertyRegistrationStatusOptions = $propertyRegistrationStatusOptions;
return $this;
}
/**
* Get Mortgage Options.
*
* @return array|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4'])]
#[Serializer\SerializedName('property_registration_status_options')]
#[Serializer\Expose]
public function getPropertyRegistrationStatusOptions()
{
return $this->propertyRegistrationStatusOptions;
}
/**
* @return bool
*/
public function hasPropertyRegistrationStatusOptions()
{
if (!$this->getSection() || !$this->getLocation()) {
return false;
}
return $this->getLocation()->getEligibleForMortgage()
&& (ListingSections::FOR_SALE == $this->getSection()->getId());
}
/**
* Get Eligible For Mortgage Data.
*
* @return array|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['DefaultV4', 'SearchV4', 'Default', 'listingDetails'])]
#[Serializer\SerializedName('eligibleForMortgageData')]
#[Serializer\Expose]
public function getEligibleForMortgageData()
{
return $this->eligibleForMortgageData;
}
public function setEligibleForMortgageData(?array $eligibleForMortgageData = null): self
{
$this->eligibleForMortgageData = $eligibleForMortgageData;
return $this;
}
/**
* Get Eligible For Mortgage with Label.
*
* @return array
*/
public function getEligibleForMortgageWithLabel()
{
$eligibleForMortgageWithLabel = [];
if (!empty($this->getEligibleForMortgage())) {
foreach ($this->getEligibleForMortgage() as $mortgage) {
$eligibleForMortgageWithLabel[] = [
'id' => $mortgage,
'title' => EligibleForMortgageData::getLabel($mortgage),
];
}
}
return $eligibleForMortgageWithLabel;
}
/**
* @return PropertyTypeChildren
*/
public function setPropertyTypeChildren($propertyTypeChilden)
{
$this->propertyTypeChilden = $propertyTypeChilden;
return $this;
}
/**
* Get PropertyTypeChildren.
*
* @return array
*/
public function getPropertyTypeChildren()
{
return $this->propertyTypeChilden;
}
/**
* @return float
*/
public function getCompoundElasticScore()
{
return $this->compoundElasticScore;
}
/**
* @param float $compoundElasticScore
*
* @return Listing
*/
public function setCompoundElasticScore($compoundElasticScore)
{
$this->compoundElasticScore = $compoundElasticScore;
return $this;
}
/**.
* @return int|null
*/
public function getPropertyRegistrationStatus()
{
return $this->propertyRegistrationStatus;
}
public function setPropertyRegistrationStatus(?int $propertyRegistrationStatus): self
{
$this->propertyRegistrationStatus = $propertyRegistrationStatus;
return $this;
}
/**
* Get property registration status data options.
*
* @return array|null
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['List', 'Details', 'Search', 'DefaultV4', 'SearchV4'])]
#[Serializer\SerializedName('property_registration_status_data')]
#[Serializer\Expose]
public function getPropertyRegistrationStatusData()
{
if (empty($this->propertyRegistrationStatus)) {
return null;
}
return [
'id' => $this->propertyRegistrationStatus,
'title' => PropertyRegistrationStatusOption::getLabel($this->propertyRegistrationStatus),
];
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'DefaultV4', 'SearchV4'])]
#[Serializer\SerializedName('financialAidURL')]
#[Serializer\Expose]
public function getFinancialAidURL(): ?string
{
// Deprecated. Return null for now.
return null;
}
public function setFinancialAid(FinancialAid $financialAid): void
{
$this->financialAid = $financialAid;
}
/**
* @return bool
*/
public function isExcludedFromClientServed()
{
$user = $this->getUser();
if ($user && $user->hasRole('ROLE_HOME_EG')) {
return true;
}
return false;
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'DefaultV4', 'SearchV4'])]
#[Serializer\SerializedName('hasSimilarListings')]
#[Serializer\Expose]
public function hasSimilarListings(): bool
{
return !empty($this->getSimilarListingsCount());
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'DefaultV4', 'SearchV4'])]
#[Serializer\SerializedName('similarListingsCount')]
#[Serializer\Expose]
public function getSimilarListingsCount(): int
{
return $this->similarListingsCount;
}
public function setSimilarListingsCount(int $count): self
{
$this->similarListingsCount = $count;
return $this;
}
/**
* Set similar listings ids.
*/
public function setSimilarListingsIds(array $arrayOfIds): self
{
$this->similarListingsIds = $arrayOfIds;
return $this;
}
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Details', 'DefaultV4', 'SearchV4'])]
#[Serializer\SerializedName('similarListingsIds')]
#[Serializer\Expose]
public function getSimilarListingsIds(): array
{
return $this->similarListingsIds;
}
public function getAdvertiserNumber(): ?string
{
return $this->advertiserNumber;
}
public function setAdvertiserNumber(?string $advertiserNumber): void
{
$this->advertiserNumber = $advertiserNumber;
}
public function getAuthorizationNumber(): ?string
{
return $this->authorizationNumber;
}
public function setAuthorizationNumber(?string $authorizationNumber): void
{
$this->authorizationNumber = $authorizationNumber;
}
/**
* Get the value of marketPropertyType.
*
* @return int|null
*/
public function getMarketPropertyType()
{
return $this->marketPropertyType;
}
/**
* Set the value of marketPropertyType.
*
* @return self
*/
public function setMarketPropertyType(?int $marketPropertyType)
{
$this->marketPropertyType = $marketPropertyType;
return $this;
}
/**
* Get the value of creationSource.
*
* @return int
*/
public function getCreationSource()
{
return $this->creationSource;
}
/**
* Set the value of creationSource.
*
* @return self
*/
public function setCreationSource(int $creationSource)
{
$this->creationSource = $creationSource;
return $this;
}
/**
* @return float
*/
#[Serializer\VirtualProperty]
#[Serializer\Groups(['Statistics', 'MyListings'])]
#[Serializer\SerializedName('costPerLead')]
#[Serializer\Expose]
public function getCostPerLead()
{
return $this->costPerLead;
}
/**
* Set the value of costPerLead.
*
* @return self
*/
public function setCostPerLead(float $costPerLead)
{
$this->costPerLead = $costPerLead;
return $this;
}
/**
* Get the value of resaleCount.
*
* @return int
*/
public function getResaleCount()
{
return $this->resaleCount;
}
/**
* Set the value of resaleCount.
*
* @return self
*/
public function setResaleCount(int $resaleCount)
{
$this->resaleCount = $resaleCount;
return $this;
}
/**
* Get the value of resaleCount.
*
* @return int
*/
public function getRentCount()
{
return $this->rentCount;
}
/**
* Set the value of rentCount.
*
* @return self
*/
public function setRentCount(int $rentCount)
{
$this->rentCount = $rentCount;
return $this;
}
/**
* Get the value of clickThroughRate.
*/
public function getClickThroughRate(): float
{
return $this->getClickRate();
}
/**
* Set the value of clickThroughRate.
*/
public function setClickThroughRate(float $clickThroughRate): self
{
$this->clickThroughRate = $clickThroughRate;
return $this;
}
/**
* Get the value of label.
*
* @return int
*/
public function getLabel()
{
return $this->label;
}
/**
* Set the value of label.
*
* @return self
*/
public function setLabel($label)
{
$this->label = $label;
return $this;
}
/**
* Get the value of isTopPicks.
*/
public function getIsTopPicks()
{
return $this->isTopPicks;
}
/**
* Set the value of isTopPicks.
*
* @return self
*/
public function setIsTopPicks($isTopPicks)
{
$this->isTopPicks = $isTopPicks;
return $this;
}
/**
* Get freezedAt date.
*
* @return \DateTime
*/
public function getFreezedAt()
{
return $this->freezedAt;
}
/**
* Set freezedAt date.
*
* @return Listing
*/
public function setFreezedAt($freezedAt)
{
$this->freezedAt = $freezedAt;
return $this;
}
public function getEligibleForBumpUp(): bool
{
return $this->eligibleForBumpUp;
}
public function setEligibleForBumpUp(bool $eligibleForBumpUp): self
{
$this->eligibleForBumpUp = $eligibleForBumpUp;
return $this;
}
/**
* Get waiting time.
*
* @return string
*/
public function getWaitingTime()
{
return $this->waitingTime;
}
/**
* Set waiting time.
*
* @param string $waitingTime
*
* @return Listing
*/
public function setWaitingTime($waitingTime)
{
$this->waitingTime = $waitingTime;
return $this;
}
/**
* Get reference number.
*/
public function getReferenceNumber(): ?string
{
return $this->referenceNumber;
}
/**
* Set reference number.
*
* @param string $referenceNumber
*/
public function setReferenceNumber($referenceNumber): self
{
$this->referenceNumber = $referenceNumber;
return $this;
}
public function getBrochure(): ?File
{
return $this->brochure;
}
public function setBrochure(?File $file): self
{
$this->brochure = $file;
return $this;
}
public function isAiContent(): ?bool
{
return $this->AiContent;
}
public function setAiContent(bool $AiContent): self
{
$this->AiContent = $AiContent;
return $this;
}
}