src/Entity/Driver.php line 19

  1. <?php
  2. namespace App\Entity;
  3. use App\Repository\DriverRepository;
  4. use Doctrine\ORM\Mapping as ORM;
  5. /**
  6.  * A driver's profile. Authentication stays on User (ROLE_DRIVER); this entity
  7.  * only carries the driving-specific data.
  8.  *
  9.  * A driver has no coordinates of their own: their position IS the position of
  10.  * the tuk they drive, so getLatitude()/getLongitude() read through to the Tuk.
  11.  *
  12.  * @ORM\Entity(repositoryClass=DriverRepository::class)
  13.  * @ORM\Table(name="driver")
  14.  * @ORM\HasLifecycleCallbacks()
  15.  */
  16. class Driver
  17. {
  18.     /**
  19.      * @ORM\Id
  20.      * @ORM\GeneratedValue
  21.      * @ORM\Column(type="integer")
  22.      */
  23.     private ?int $id null;
  24.     /**
  25.      * @ORM\OneToOne(targetEntity=User::class)
  26.      * @ORM\JoinColumn(nullable=false, unique=true)
  27.      */
  28.     private User $user;
  29.     /**
  30.      * The tuk this driver drives. Inverse side — Tuk owns the join column.
  31.      * @ORM\OneToOne(targetEntity=Tuk::class, mappedBy="driver")
  32.      */
  33.     private ?Tuk $tuk null;
  34.     /**
  35.      * Public-facing photo path, shown to the passenger when choosing a tuk.
  36.      * @ORM\Column(type="string", length=500, nullable=true)
  37.      */
  38.     private ?string $photo null;
  39.     /**
  40.      * @ORM\Column(type="string", length=50, nullable=true)
  41.      */
  42.     private ?string $licenseNumber null;
  43.     /**
  44.      * Languages the driver speaks, as ISO 639-1 codes, e.g. ["en", "hy"].
  45.      * @ORM\Column(type="json")
  46.      */
  47.     private array $languages = [];
  48.     /**
  49.      * Average rating, 0.0–5.0.
  50.      * @ORM\Column(type="decimal", precision=2, scale=1, options={"default": "5.0"})
  51.      */
  52.     private string $rating '5.0';
  53.     /**
  54.      * How many ratings $rating is averaged over.
  55.      * @ORM\Column(type="integer", options={"default": 0})
  56.      */
  57.     private int $ratingCount 0;
  58.     /**
  59.      * Completed tours, shown as experience on the driver card.
  60.      * @ORM\Column(type="integer", options={"default": 0})
  61.      */
  62.     private int $tripCount 0;
  63.     /**
  64.      * Running total of the gratuities passengers have added after their tours,
  65.      * in dram. Kept as an aggregate here so the driver's profile can show it
  66.      * without summing the whole booking table on every page view.
  67.      *
  68.      * @ORM\Column(type="integer", options={"default": 0})
  69.      */
  70.     private int $tipsAmd 0;
  71.     /**
  72.      * @ORM\Column(type="boolean", options={"default": true})
  73.      */
  74.     private bool $isActive true;
  75.     /**
  76.      * @ORM\Column(type="datetime_immutable")
  77.      */
  78.     private \DateTimeImmutable $createdAt;
  79.     /**
  80.      * @ORM\Column(type="datetime_immutable", nullable=true)
  81.      */
  82.     private ?\DateTimeImmutable $updatedAt null;
  83.     public function __construct()
  84.     {
  85.         $this->createdAt = new \DateTimeImmutable();
  86.     }
  87.     /**
  88.      * @ORM\PreUpdate()
  89.      */
  90.     public function onPreUpdate(): void
  91.     {
  92.         $this->updatedAt = new \DateTimeImmutable();
  93.     }
  94.     public function getId(): ?int
  95.     {
  96.         return $this->id;
  97.     }
  98.     public function getUser(): User
  99.     {
  100.         return $this->user;
  101.     }
  102.     public function setUser(?User $user): self
  103.     {
  104.         $this->user $user;
  105.         return $this;
  106.     }
  107.     public function getTuk(): ?Tuk
  108.     {
  109.         return $this->tuk;
  110.     }
  111.     public function setTuk(?Tuk $tuk): self
  112.     {
  113.         $this->tuk $tuk;
  114.         return $this;
  115.     }
  116.     public function getPhoto(): ?string
  117.     {
  118.         return $this->photo;
  119.     }
  120.     public function setPhoto(?string $photo): self
  121.     {
  122.         $this->photo $photo;
  123.         return $this;
  124.     }
  125.     public function getLicenseNumber(): ?string
  126.     {
  127.         return $this->licenseNumber;
  128.     }
  129.     public function setLicenseNumber(?string $licenseNumber): self
  130.     {
  131.         $this->licenseNumber $licenseNumber;
  132.         return $this;
  133.     }
  134.     public function getLanguages(): array
  135.     {
  136.         return $this->languages;
  137.     }
  138.     public function setLanguages(array $languages): self
  139.     {
  140.         $this->languages array_values(array_unique($languages));
  141.         return $this;
  142.     }
  143.     public function getRating(): float
  144.     {
  145.         return (float) $this->rating;
  146.     }
  147.     public function setRating(float $rating): self
  148.     {
  149.         $this->rating number_format(max(0.0min(5.0$rating)), 1'.''');
  150.         return $this;
  151.     }
  152.     public function getRatingCount(): int
  153.     {
  154.         return $this->ratingCount;
  155.     }
  156.     public function setRatingCount(int $ratingCount): self
  157.     {
  158.         $this->ratingCount $ratingCount;
  159.         return $this;
  160.     }
  161.     /**
  162.      * Fold a new 1–5 star rating into the running average.
  163.      */
  164.     public function addRating(int $stars): self
  165.     {
  166.         $stars max(1min(5$stars));
  167.         $total $this->getRating() * $this->ratingCount $stars;
  168.         $this->ratingCount++;
  169.         $this->setRating($total $this->ratingCount);
  170.         return $this;
  171.     }
  172.     public function getTripCount(): int
  173.     {
  174.         return $this->tripCount;
  175.     }
  176.     public function setTripCount(int $tripCount): self
  177.     {
  178.         $this->tripCount $tripCount;
  179.         return $this;
  180.     }
  181.     public function getTipsAmd(): int
  182.     {
  183.         return $this->tipsAmd;
  184.     }
  185.     public function setTipsAmd(int $tipsAmd): self
  186.     {
  187.         $this->tipsAmd max(0$tipsAmd);
  188.         return $this;
  189.     }
  190.     /**
  191.      * Fold a gratuity into the running total.
  192.      */
  193.     public function addTip(int $amountAmd): self
  194.     {
  195.         $this->tipsAmd += max(0$amountAmd);
  196.         return $this;
  197.     }
  198.     public function isActive(): bool
  199.     {
  200.         return $this->isActive;
  201.     }
  202.     public function setIsActive(bool $isActive): self
  203.     {
  204.         $this->isActive $isActive;
  205.         return $this;
  206.     }
  207.     public function getCreatedAt(): \DateTimeImmutable
  208.     {
  209.         return $this->createdAt;
  210.     }
  211.     public function getUpdatedAt(): ?\DateTimeImmutable
  212.     {
  213.         return $this->updatedAt;
  214.     }
  215.     // ── Read-through helpers: a driver is wherever their tuk is ──────────
  216.     public function getName(): string
  217.     {
  218.         return $this->user->getName();
  219.     }
  220.     public function getLatitude(): ?float
  221.     {
  222.         return $this->tuk?->getLatitude();
  223.     }
  224.     public function getLongitude(): ?float
  225.     {
  226.         return $this->tuk?->getLongitude();
  227.     }
  228.     public function isOnline(): bool
  229.     {
  230.         return $this->tuk !== null && $this->tuk->isOnline();
  231.     }
  232.     public function __toString(): string
  233.     {
  234.         return $this->user->getName() ?? '';
  235.     }
  236. }