src/Aqarmap/Bundle/ListingBundle/Entity/Listing.php line 82
<?phpnamespace Aqarmap\Bundle\ListingBundle\Entity;use App\Entity\Label;use App\Entity\Listing\ListingValuation;use App\Entity\Listing\ListingVirtualSerialization;use App\Entity\ListingLabel;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\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 ListingVirtualSerialization;/*** @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', 'ListingPhotos'])]#[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;/*** @AqarMapAssert\IsYoutubeUrlOrNull*/#[ORM\Column(name: 'video_url', type: 'string', length: 150, nullable: true)]#[Serializer\Groups(['List', 'Details', 'listingDetails', 'Activity', 'DefaultV4', 'ProjectSearchV4', 'ProjectDetailsV4', 'listingDetailsWithLocationCompound', 'SearchV4'])]#[Serializer\Expose]private ?string $videoUrl = null;#[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(mappedBy: 'listing', targetEntity: ListingPhone::class, cascade: ['all'], orphanRemoval: true)]protected $phones;#[ORM\OneToMany(mappedBy: 'listing', targetEntity: ListingPhoto::class, cascade: ['persist', 'remove'], orphanRemoval: true)]#[ORM\OrderBy(['order' => 'ASC'])]protected Collection $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\OneToMany(mappedBy: 'listing', targetEntity: ListingLabel::class, cascade: ['persist', 'remove'], orphanRemoval: true)]private Collection $labels;#[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;#[ORM\Column(name: 'ai_review', type: 'json', nullable: true)]private ?array $aiReview = [];private int $maxPrice;/*** @var Collection<int, ListingValuation>*/#[ORM\OneToMany(mappedBy: 'listing', targetEntity: ListingValuation::class, orphanRemoval: true)]private Collection $listingValuations;#[ORM\OneToOne(cascade: ['persist', 'remove'])]#[ORM\JoinColumn(name: 'valuation_id', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]private ?ListingValuation $valuation = null;/*** 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->labels = 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();$this->listingValuations = 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->labels = 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;}public function setSellerRoleLabel($label): void{$this->sellerRoleLabel = $label;}/*** 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;}public function setVideoUrl(?string $videoUrl): static{$this->videoUrl = $videoUrl;return $this;}public function getVideoUrl(): ?string{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;}public function getPropertyTypeForValuation(): ?PropertyType{$propertyType = $this->getPropertyType();while ($propertyType) {if ($propertyType->getIsEvaluable()) {return $propertyType;}// Guard self-parenting'sif ($propertyType->getParent() === $propertyType) {break;}$propertyType = $propertyType->getParent();}return null;}/*** 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 ListingPhone $phone */foreach ($this->getPhones() as $phone) {$phones[] = $phone->getPhone();}return $phones;}/*** Get phones for listing from the user phones.*/#[Serializer\Groups(['List', 'Details', 'listingDetails', 'SearchV4', 'ListingPhones'])]#[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);}#[Serializer\Groups(['List', 'Details', 'listingDetails', 'ListingPhotos'])]#[Serializer\VirtualProperty]#[Serializer\SerializedName('photos')]public function getPhotosForSlider(): ArrayCollection{$slider = new ArrayCollection();$photos = $this->getPhotos()->toArray();// Manually sort photos, as "Criteria" does not sort them, not sure whyusort($photos, function($a, $b) {return $a->getOrder() <=> $b->getOrder();});$mainPhoto = $this->getMainPhoto();if ($mainPhoto) {$slider->add($mainPhoto);}// Add all other photos, except the main photo, because It's already added/** @var ListingPhoto $photo */foreach ($photos as $photo) {if (!$slider->contains($photo) && PhotoTypes::LOGO_PHOTO !== $photo->getType()) {$slider->add($photo);}}return $slider;}public function buildMappedMainPhoto(): self{// Important for APIif ($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 sliderif ($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 APIif ($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 ArrayCollection*/public function getFavourite(){return $this->favourite;}public function setFavourite(array $favourites): self{foreach ($favourites as $favourite) {$this->addFavourite($favourite);}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;}public function addLabel(Label $label, ?string $comment = null): self{$listingLabel = $this->findListingLabel($label);if (null !== $listingLabel) {$listingLabel->setComment($comment);return $this;}$this->labels->add(new ListingLabel($this, $label, $comment));return $this;}public function removeLabel(Label $label): void{$listingLabel = $this->findListingLabel($label);if (null !== $listingLabel) {$this->labels->removeElement($listingLabel);}}/*** @return Collection<int, Label>*/public function getLabels(): Collection{return $this->labels->map(static fn (ListingLabel $listingLabel) => $listingLabel->getLabel());}/*** @return Collection<int, ListingLabel>*/public function getListingLabels(): Collection{return $this->labels;}public function hasLabel(Label $label): bool{return null !== $this->findListingLabel($label);}public function hasLabelCode(string $code): bool{return $this->labels->exists(static fn (int $key, ListingLabel $listingLabel) => $listingLabel->getLabel()->getCode() === $code);}private function findListingLabel(Label $label): ?ListingLabel{foreach ($this->labels as $listingLabel) {if ($listingLabel->getLabel()->getId() === $label->getId()) {return $listingLabel;}}return null;}/*** 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;}public function getAiReview(): ?array{return $this->aiReview;}public function setAiReview(?array $aiReview): self{$this->aiReview = $aiReview;return $this;}/*** @return Collection<int, ListingValuation>*/public function getListingValuations(): Collection{return $this->listingValuations;}public function addListingValuation(ListingValuation $listingValuation): static{if (!$this->listingValuations->contains($listingValuation)) {$this->listingValuations->add($listingValuation);$listingValuation->setListing($this);}return $this;}public function removeListingValuation(ListingValuation $listingValuation): static{if ($this->listingValuations->removeElement($listingValuation)) {// set the owning side to null (unless already changed)if ($listingValuation->getListing() === $this) {$listingValuation->setListing(null);}}return $this;}public function getValuation(): ?ListingValuation{return $this->valuation;}public function setValuation(?ListingValuation $valuation): static{$this->valuation = $valuation;return $this;}}