<?php
namespace App\Entity;
use App\Entity\Bid;
use App\Entity\User;
use App\Entity\Vehicle;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Single vehicle auction.
*
* @ORM\Entity(repositoryClass="App\Repository\AuctionRepository")
*
* @ORM\Table(name="auction")
*/
class Auction
{
/**
* @ORM\Id
*
* @ORM\Column(type="integer")
*
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\OneToOne(targetEntity="App\Entity\Vehicle", inversedBy="auction", fetch="EAGER", cascade={"persist"})
*
* @ORM\JoinColumn(name="vehicle_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $vehicle;
/**
* Users participating in this auction.
*
* @ORM\ManyToMany(targetEntity="App\Entity\User", inversedBy="auctions", cascade={"persist"})
*
* @ORM\JoinTable(name="auction_bidders",
* joinColumns={@ORM\JoinColumn(name="auction_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
protected $users;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Bid", mappedBy="auction", cascade={"persist"})
*
* @ORM\OrderBy({"amount" = "DESC", "biddedAt" = "ASC", "timestamp" = "ASC"})
*/
protected $bids;
/**
* @Gedmo\Timestampable(on="create")
*
* @ORM\Column(type="datetime", name="created_at")
*/
protected $createdAt;
/**
* @Gedmo\Timestampable(on="update")
*
* @ORM\Column(type="datetime", name="updated_at")
*/
protected $updatedAt;
/**
* @ORM\Column(type="datetime", name="opened_At")
*/
protected $openedAt;
/**
* @ORM\Column(type="datetime", name="closes_at")
*/
protected $closedAt;
/**
* @ORM\Column(type="datetime", name="paused_at", nullable=true)
*/
protected $pausedAt;
/**
* @ORM\Column(type="integer", name="paused_Ms")
*/
protected $pausedMs = 0;
/**
* @ORM\Column(type="boolean")
**/
private $biddedDuringPause = false;
public function __construct(Vehicle $vehicle)
{
$this->setVehicle($vehicle);
$vehicle->setAuction($this);
$this->setWinningBidAmount(0);
$this->users = new ArrayCollection();
$this->bids = new ArrayCollection();
$this->openedAt = $vehicle->getEvent()->getSale()->getStartDate();
$this->closedAt = $vehicle->getEvent()->getSale()->getEndDate();
}
public function getId(): ?int
{
return $this->id;
}
/**
* Returns the vehicle.
*
* @return Vehicle
*/
public function getVehicle()
{
return $this->vehicle;
}
/**
* Sets the vehicle.
*/
public function setVehicle(Vehicle $vehicle): void
{
$this->vehicle = $vehicle;
}
public function getWinner()
{
return $this->getVehicle()->getWinner();
}
public function setWinner($winner = null): void
{
$this->getVehicle()->setWinner($winner);
}
public function isWinner(?User $user = null)
{
if (null !== $this->getWinner()) {
return $this->getWinner() === $user;
}
return false;
}
/**
* Return all users participating in this auction.
*
* @return Collection
*/
public function getUsers()
{
return $this->users;
}
/**
* Sets users participating in this auction.
*/
public function setUsers(Collection $users): void
{
$this->users = $users;
}
/**
* Adds user to this auction.
*/
public function addUser(?User $user = null): void
{
if (null !== $user && !$this->isParticipating($user)) {
$this->users[] = $user;
}
}
/**
* Removes user from this auction.
*/
public function removeUser(User $user): void
{
if ($this->isParticipating($user)) {
$this->users->removeElement($user);
}
}
/**
* Is user participating?
*
* @return bool
*/
public function isParticipating(User $user)
{
return $this->users->contains($user);
}
/**
* Returns all bids made on this auction.
*
* @return Collection
*/
public function getBids()
{
return $this->bids;
}
/**
* Sets bids to this auction.
*/
public function setBids(Collection $bids): void
{
$this->bids = $bids;
}
/**
* Adds bid.
*/
public function addBid(Bid $bid): void
{
if (!$this->hasBid($bid)) {
$bid->setAuction($this);
$this->bids[] = $bid;
}
}
/**
* Removes bid from this auction.
*/
public function removeBid(Bid $bid): void
{
if ($this->hasBid($bid)) {
$bid->setAuction(null);
$this->bids->removeElement($bid);
}
}
/**
* Checks if auction has bid.
*/
public function hasBid(Bid $bid)
{
return $this->bids->contains($bid);
}
/**
* Checks whether there is any bid on auction or not.
*
* @return bool
*/
public function hasFirstBid()
{
return 0 !== $this->getWinningBidAmount();
}
public function hasBidded($user)
{
foreach ($user->getBids() as $bid) {
if ($bid->getAuction() === $this) {
return true;
}
}
return false;
}
public function getWinningBid()
{
return $this->bids->first();
}
public function getHighestRealBid()
{
return $this
->bids
->filter(fn ($bid) => Bid::ORIGIN_ANIMATION !== $bid->getOrigin())
->first()
;
}
public function getWinningBidAmount()
{
if (null === $this->getVehicle()->getFinalAmount()) {
return 0;
}
return $this->getVehicle()->getFinalAmount();
}
public function setWinningBidAmount($amount): void
{
$this->getVehicle()->setFinalAmount($amount);
}
public function getCalculatedWinningBidAmount()
{
$vehicle = $this->getVehicle();
if (0 === intval($this->getWinningBidAmount())) {
return $vehicle->getStartingPrice() + $vehicle->getEvent()->getSale()->getBidIncrement();
}
return $this->getWinningBidAmount() + $vehicle->getEvent()->getSale()->getBidIncrement();
}
/**
* Returns time of creation.
*
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Sets time of creation.
*/
public function setCreatedAt(\DateTime $createdAt): void
{
$this->createdAt = $createdAt;
}
/**
* Returns time of update.
*
* @return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Sets time of update.
*/
public function setUpdatedAt(\DateTime $updatedAt): void
{
$this->updatedAt = $updatedAt;
}
public function isOpen()
{
$now = new \DateTime('now');
return ($now > $this->getOpenedAt() && $now < $this->getClosedAt()) && Vehicle::SALING_STATE_NONE === $this->getVehicle()->getSalingState();
}
public function isClosed()
{
$now = new \DateTime('now');
return $now > $this->getClosedAt();
}
public function isBefore()
{
$now = new \DateTime('now');
return $now < $this->getOpenedAt();
}
public function isBiddable()
{
return $this->isOpen() || ($this->isBefore() && $this->getVehicle()->getStartingPrice() > 0);
}
public function isActive()
{
return $this->isOpen();
}
/**
* Returns auction starting date.
*
* @return \DateTime
*/
public function getOpenedAt()
{
return $this->openedAt;
}
/**
* Sets auction starting date.
*
* @param \DateTime $openedAt
*/
public function setOpenedAt($openedAt): void
{
$this->openedAt = $openedAt;
}
/**
* Returns auction closing time.
*
* @return \DateTime
*/
public function getClosedAt()
{
return $this->closedAt;
}
/**
* Sets auction closing time.
*
* @param \DateTime $closedAt
*/
public function setClosedAt($closedAt): void
{
$this->closedAt = $closedAt;
}
public function getPausedAt()
{
return $this->pausedAt;
}
public function getPausedMs()
{
return $this->pausedMs;
}
public function setPausedMs($ms)
{
$this->pausedMs = $ms;
return $this;
}
public function isPaused()
{
return null !== $this->pausedAt;
}
public function setPaused($paused)
{
$today = new \DateTime();
if ($paused) {
if (!$this->isPaused()) {
$this->pausedAt = $today;
}
} else {
if ($this->isPaused()) {
$this->pausedMs = $this->pausedMs + (($today->format('U') - $this->pausedAt->format('U')) * 1000);
$this->pausedAt = null;
}
}
return $this;
}
public function isBiddedDuringPause()
{
return $this->biddedDuringPause;
}
public function setBiddedDuringPause($bool)
{
$this->biddedDuringPause = $bool;
return $this;
}
}