<?php
namespace App\Entity\Shop\Product;
use App\Entity\BaseEntity;
use App\Entity\Shop\Cart\CartItem;
use App\Entity\Shop\Order\Discount;
use App\Entity\Shop\Order\OrderItem;
use App\Entity\Shop\Shop\Review;
use App\Entity\Shop\Shop\Shop;
use App\Repository\Shop\Product\ProductRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product extends BaseEntity
{
#[ORM\Id]
#[ORM\Column(type: 'guid', unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
private ?string $id;
#[ORM\Column(type: Types::BIGINT, nullable: true)]
private ?string $stock = null;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: ProductPrice::class, cascade: ['persist'], orphanRemoval: true)]
private Collection $productPrices;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: ProductAttribute::class, cascade: ['persist'], orphanRemoval: true)]
private Collection $productAttributes;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $description = null;
#[ORM\Column(type: Types::BIGINT)]
private ?string $price = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $imageUrl = null;
#[ORM\ManyToOne(inversedBy: 'products')]
#[ORM\JoinColumn(nullable: false)]
private ?Shop $shop = null;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: Discount::class)]
private Collection $discounts;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: ProductImage::class, cascade: ['persist'], orphanRemoval: true)]
private Collection $productImages;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: OrderItem::class)]
private Collection $orderItems;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: CartItem::class)]
private Collection $cartItems;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: Review::class)]
private Collection $reviews;
#[ORM\Column(length: 255, nullable: true)]
private ?string $subName = null;
#[ORM\ManyToMany(targetEntity: ProductCategory::class, mappedBy: 'products', cascade: ['persist'])]
private Collection $productCategories;
#[ORM\ManyToMany(targetEntity: ProductTag::class, mappedBy: 'products', cascade: ['persist'])]
private Collection $productTags;
#[ORM\OneToMany(mappedBy: 'product', targetEntity: ProductReview::class)]
private Collection $productReviews;
#[ORM\Column(nullable: true)]
private ?bool $isSelling = null;
public function __construct()
{
parent::__construct();
$this->setPrice(0);
$this->productAttributes = new ArrayCollection();
$this->discounts = new ArrayCollection();
$this->productImages = new ArrayCollection();
$this->orderItems = new ArrayCollection();
$this->cartItems = new ArrayCollection();
$this->reviews = new ArrayCollection();
$this->productPrices = new ArrayCollection();
$this->productCategories = new ArrayCollection();
$this->productTags = new ArrayCollection();
$this->productReviews = new ArrayCollection();
}
public function __toString()
{
return $this->getName();
}
public function getMinPrice(): ?int
{
if (!$this->isVariablePriced()) {
return $this->getPrice(); // قیمت ساده
}
$prices = $this->getProductPrices()->map(fn($p) => $p->getPrice())->toArray();
return !empty($prices) ? min($prices) : null;
}
public function isVariablePriced(): bool
{
return !$this->productPrices->isEmpty();
}
public function getDisplayPrice(): ?int
{
return $this->isVariablePriced()
? $this->getMinPrice()
: $this->getPrice();
}
public function getId(): ?string
{
return $this->id;
}
/**
* @return Collection<int, ProductAttribute>
*/
public function getProductAttributes(): Collection
{
return $this->productAttributes;
}
public function addProductAttribute(ProductAttribute $productAttribute): static
{
if (!$this->productAttributes->contains($productAttribute)) {
$this->productAttributes->add($productAttribute);
$productAttribute->setProduct($this);
}
return $this;
}
public function removeProductAttribute(ProductAttribute $productAttribute): static
{
if ($this->productAttributes->removeElement($productAttribute)) {
// set the owning side to null (unless already changed)
if ($productAttribute->getProduct() === $this) {
$productAttribute->setProduct(null);
}
}
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): static
{
$this->description = $description;
return $this;
}
public function getPrice(): ?string
{
return $this->price;
}
public function setPrice(string $price): static
{
$this->price = $price;
return $this;
}
public function getStock(): ?string
{
return $this->stock;
}
public function setStock(string $stock): static
{
$this->stock = $stock;
return $this;
}
public function getImageUrl(): ?string
{
return $this->imageUrl;
}
public function setImageUrl(?string $imageUrl): static
{
$this->imageUrl = $imageUrl;
return $this;
}
public function getShop(): ?Shop
{
return $this->shop;
}
public function setShop(?Shop $shop): static
{
$this->shop = $shop;
return $this;
}
/**
* @return Collection<int, Discount>
*/
public function getDiscounts(): Collection
{
return $this->discounts;
}
public function addDiscount(Discount $discount): static
{
if (!$this->discounts->contains($discount)) {
$this->discounts->add($discount);
$discount->setProduct($this);
}
return $this;
}
public function removeDiscount(Discount $discount): static
{
if ($this->discounts->removeElement($discount)) {
// set the owning side to null (unless already changed)
if ($discount->getProduct() === $this) {
$discount->setProduct(null);
}
}
return $this;
}
public function getCategory()
{
return $this->productCategories->first();
}
public function setCategory(?ProductCategory $category): static
{
$this->category = $category;
return $this;
}
/**
* @return Collection<int, ProductImage>
*/
public function getProductImages(): Collection
{
return $this->productImages;
}
public function addProductImage(ProductImage $productImage): static
{
if (!$this->productImages->contains($productImage)) {
$this->productImages->add($productImage);
$productImage->setProduct($this);
}
return $this;
}
public function removeProductImage(ProductImage $productImage): static
{
if ($this->productImages->removeElement($productImage)) {
// set the owning side to null (unless already changed)
if ($productImage->getProduct() === $this) {
$productImage->setProduct(null);
}
}
return $this;
}
/**
* @return Collection<int, OrderItem>
*/
public function getOrderItems(): Collection
{
return $this->orderItems;
}
public function addOrderItem(OrderItem $orderItem): static
{
if (!$this->orderItems->contains($orderItem)) {
$this->orderItems->add($orderItem);
$orderItem->setProduct($this);
}
return $this;
}
public function removeOrderItem(OrderItem $orderItem): static
{
if ($this->orderItems->removeElement($orderItem)) {
// set the owning side to null (unless already changed)
if ($orderItem->getProduct() === $this) {
$orderItem->setProduct(null);
}
}
return $this;
}
/**
* @return Collection<int, CartItem>
*/
public function getCartItems(): Collection
{
return $this->cartItems;
}
public function addCartItem(CartItem $cartItem): static
{
if (!$this->cartItems->contains($cartItem)) {
$this->cartItems->add($cartItem);
$cartItem->setProduct($this);
}
return $this;
}
public function removeCartItem(CartItem $cartItem): static
{
if ($this->cartItems->removeElement($cartItem)) {
// set the owning side to null (unless already changed)
if ($cartItem->getProduct() === $this) {
$cartItem->setProduct(null);
}
}
return $this;
}
/**
* @return Collection<int, Review>
*/
public function getReviews(): Collection
{
return $this->reviews;
}
public function addReview(Review $review): static
{
if (!$this->reviews->contains($review)) {
$this->reviews->add($review);
$review->setProduct($this);
}
return $this;
}
public function removeReview(Review $review): static
{
if ($this->reviews->removeElement($review)) {
// set the owning side to null (unless already changed)
if ($review->getProduct() === $this) {
$review->setProduct(null);
}
}
return $this;
}
/**
* @return Collection<int, ProductPrice>
*/
public function getProductPrices(): Collection
{
return $this->productPrices;
}
public function addProductPrice(ProductPrice $productPrice): static
{
if (!$this->productPrices->contains($productPrice)) {
$this->productPrices->add($productPrice);
$productPrice->setProduct($this);
}
return $this;
}
public function removeProductPrice(ProductPrice $productPrice): static
{
if ($this->productPrices->removeElement($productPrice)) {
// set the owning side to null (unless already changed)
if ($productPrice->getProduct() === $this) {
$productPrice->setProduct(null);
}
}
return $this;
}
public function getSubName(): ?string
{
return $this->subName;
}
public function setSubName(?string $subName): static
{
$this->subName = $subName;
return $this;
}
/**
* @return Collection<int, ProductCategory>
*/
public function getProductCategories(): Collection
{
return $this->productCategories;
}
public function addProductCategory(ProductCategory $productCategory): static
{
if (!$this->productCategories->contains($productCategory)) {
$this->productCategories->add($productCategory);
$productCategory->addProduct($this);
}
return $this;
}
public function removeProductCategory(ProductCategory $productCategory): static
{
if ($this->productCategories->removeElement($productCategory)) {
$productCategory->removeProduct($this);
}
return $this;
}
/**
* @return Collection<int, ProductTag>
*/
public function getProductTags(): Collection
{
return $this->productTags;
}
public function addProductTag(ProductTag $productTag): static
{
if (!$this->productTags->contains($productTag)) {
$this->productTags->add($productTag);
$productTag->addProduct($this);
}
return $this;
}
public function removeProductTag(ProductTag $productTag): static
{
if ($this->productTags->removeElement($productTag)) {
$productTag->removeProduct($this);
}
return $this;
}
/**
* @return Collection<int, ProductReview>
*/
public function getProductReviews(): Collection
{
return $this->productReviews;
}
public function addProductReview(ProductReview $productReview): static
{
if (!$this->productReviews->contains($productReview)) {
$this->productReviews->add($productReview);
$productReview->setProduct($this);
}
return $this;
}
public function removeProductReview(ProductReview $productReview): static
{
if ($this->productReviews->removeElement($productReview)) {
// set the owning side to null (unless already changed)
if ($productReview->getProduct() === $this) {
$productReview->setProduct(null);
}
}
return $this;
}
public function isIsSelling(): ?bool
{
return $this->isSelling;
}
public function setIsSelling(?bool $isSelling): static
{
$this->isSelling = $isSelling;
return $this;
}
}