src/Entity/Saloon/Saloon.php line 41

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by simpson <simpsonwork@gmail.com>
  4.  * Date: 2019-04-15
  5.  * Time: 19:50
  6.  */
  7. namespace App\Entity\Saloon;
  8. use AngelGamez\TranslatableBundle\Entity\TranslatableValue;
  9. use App\Entity\Account\Advertiser;
  10. use App\Entity\ApartmentsPricing;
  11. use App\Entity\Account\Customer;
  12. use App\Entity\ExpressPricing;
  13. use App\Entity\IProvidedService;
  14. use App\Entity\IProvidesServices;
  15. use App\Entity\Location\City;
  16. use App\Entity\Location\Station;
  17. use App\Entity\Location\MapCoordinate;
  18. use App\Entity\Messengers;
  19. use App\Entity\PhoneCallRestrictions;
  20. use App\Entity\Sales\Saloon\AdBoardPlacement;
  21. use App\Entity\Saloon\Comment\CommentByCustomer;
  22. use App\Entity\Service;
  23. use App\Entity\Sales\Saloon\PlacementHiding;
  24. use App\Entity\ProvidedServiceTrait;
  25. use App\Entity\TakeOutPricing;
  26. use App\Helper\TopCardTrait;
  27. use App\Repository\SaloonRepository;
  28. use Carbon\Carbon;
  29. use Carbon\CarbonImmutable;
  30. use Doctrine\Common\Collections\ArrayCollection;
  31. use Doctrine\Common\Collections\Collection;
  32. use Doctrine\ORM\Mapping as ORM;
  33. use Gedmo\Mapping\Annotation as Gedmo;
  34. use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
  35. #[Gedmo\SoftDeleteable(fieldName"deletedAt"timeAwaretrue)]
  36. #[ORM\Table(name'saloons')]
  37. #[ORM\Entity(repositoryClassSaloonRepository::class)]
  38. class Saloon implements IProvidesServices
  39. {
  40.     use SoftDeleteableEntity;
  41.     use ProvidedServiceTrait;
  42.     use TopCardTrait;
  43.     #[ORM\Id]
  44.     #[ORM\Column(name'id'type'integer')]
  45.     #[ORM\GeneratedValue(strategy'AUTO')]
  46.     protected int $id;
  47.     #[ORM\JoinColumn(name'user_id'referencedColumnName'id'nullabletrue)]
  48.     #[ORM\ManyToOne(targetEntityAdvertiser::class, inversedBy'saloons')]
  49.     protected ?Advertiser $owner;
  50.     #[ORM\OneToOne(targetEntityAdBoardPlacement::class, mappedBy'saloon'cascade: ['all'])]
  51.     protected ?AdBoardPlacement $adBoardPlacement;
  52.     #[ORM\OneToOne(targetEntityPlacementHiding::class, mappedBy'saloon'cascade: ['all'])]
  53.     protected ?PlacementHiding $placementHiding;
  54.     #[ORM\Column(name'uri_identity'type'string'length128)]
  55.     protected string $uriIdentity;
  56.     #[ORM\Column(name'name'type'translatable')]
  57.     protected TranslatableValue $name;
  58.     #[ORM\Column(name'description'type'translatable')]
  59.     protected TranslatableValue $description;
  60.     /** @var SaloonService[] */
  61.     #[ORM\OneToMany(targetEntitySaloonService::class, mappedBy'saloon'cascade: ['all'], orphanRemovaltrue)]
  62.     #[ORM\Cache(usage'NONSTRICT_READ_WRITE')]
  63.     protected Collection $providedServices;
  64.     /** @var int[] */
  65.     #[ORM\Column(name'client_types'type'simple_array'nullabletrue)]
  66.     protected ?array $clientTypes;
  67.     /**
  68.      * Номера телефонов в свободной форме написания
  69.      */
  70.     #[ORM\Column(name'phone_number'type'string'length255)]
  71.     protected string $phoneNumber;
  72.     #[ORM\Embedded(class: Messengers::class, columnPrefixfalse)]
  73.     protected ?Messengers $messengers;
  74.     #[ORM\Embedded(class: PhoneCallRestrictions::class, columnPrefixfalse)]
  75.     protected ?PhoneCallRestrictions $phoneCallRestrictions;
  76.     #[ORM\Embedded(class: WorkingHours::class, columnPrefix'working_hours_')]
  77.     protected ?WorkingHours $workingHours;
  78.     /**
  79.      * Расценки в свободной форме написания
  80.      */
  81.     #[ORM\Column(name'prices'type'text'nullabletrue)]
  82.     protected ?string $prices;
  83.     #[ORM\Embedded(class: ApartmentsPricing::class, columnPrefixfalse)]
  84.     protected ?ApartmentsPricing $apartmentsPricing;
  85.     #[ORM\Embedded(class: TakeOutPricing::class, columnPrefixfalse)]
  86.     protected ?TakeOutPricing $takeOutPricing;
  87.     #[ORM\Embedded(class: ExpressPricing::class, columnPrefixfalse)]
  88.     protected ?ExpressPricing $expressPricing;
  89.     #[ORM\Column(name'extra_charge'type'integer'nullabletrue)]
  90.     protected ?int $extraCharge;
  91.     #[ORM\OneToOne(targetEntityThumbnail::class, mappedBy'saloon'cascade: ['all'], orphanRemovaltrue)]
  92.     protected ?Thumbnail $thumbnail null;
  93.     /** @var Photo[] */
  94.     #[ORM\OneToMany(targetEntityPhoto::class, mappedBy'saloon'cascade: ['all'], orphanRemovaltrue)]
  95.     protected Collection $photos;
  96.     /** @var Video[] */
  97.     #[ORM\OneToMany(targetEntityVideo::class, mappedBy'saloon'cascade: ['all'], orphanRemovaltrue)]
  98.     protected Collection $videos;
  99.     /** @var CommentByCustomer[] */
  100.     #[ORM\OneToMany(targetEntityCommentByCustomer::class, mappedBy'saloon')]
  101.     protected Collection $comments;
  102.     #[ORM\JoinColumn(name'city_id'referencedColumnName'id')]
  103.     #[ORM\ManyToOne(targetEntityCity::class)]
  104.     protected City $city;
  105.     /** @var Station[] */
  106.     #[ORM\JoinTable(name'saloon_stations')]
  107.     #[ORM\JoinColumn(name'saloon_id'referencedColumnName'id')]
  108.     #[ORM\InverseJoinColumn(name'station_id'referencedColumnName'id')]
  109.     #[ORM\ManyToMany(targetEntityStation::class)]
  110.     protected Collection $stations;
  111.     /**
  112.      * Районы в свободной форме написания
  113.      */
  114.     #[ORM\Column(name'districts'type'string'length255nullabletrue)]
  115.     protected ?string $districts;
  116.     #[ORM\Column(name'address'type'translatable'nullabletrue)]
  117.     protected ?TranslatableValue $address;
  118.     #[ORM\Embedded(class: MapCoordinate::class, columnPrefixfalse)]
  119.     protected MapCoordinate $mapCoordinate;
  120.     #[ORM\Column(name'created_at'type'datetimetz_immutable'nullabletrue)]
  121.     protected ?\DateTimeImmutable $createdAt;
  122.     #[Gedmo\Timestampable(on"update")]
  123.     #[ORM\Column(name'updated_at'type'datetimetz_immutable'nullabletrue)]
  124.     protected ?\DateTimeImmutable $updatedAt;
  125.     #[ORM\Column(name'inactivated_at'type'datetimetz_immutable'nullabletrue)]
  126.     protected ?\DateTimeImmutable $inactivatedAt;
  127.     #[ORM\Column(name'email'type'string'length180)]
  128.     protected string $email;
  129.     private bool $draft false;
  130.     #[ORM\Column(name'seo'type'json'nullabletrue)]
  131.     private ?array $seo null;
  132.     #[ORM\ManyToOne(targetEntityStation::class)]
  133.     #[ORM\JoinColumn(name'primary_station_id'referencedColumnName'id'nullabletrueonDelete'SET NULL')]
  134.     private ?Station $primaryStation null;
  135.     #[ORM\Column(type'smallint'options: ['default' => 0])]
  136.     private int $deleteMode 0;
  137.     public function __construct(string $uriIdentity, ?\DateTimeImmutable $createdAt null)
  138.     {
  139.         $this->draft true;
  140.         $this->uriIdentity $uriIdentity;
  141.         $this->createdAt $createdAt ?? CarbonImmutable::now();
  142.         $this->photos = new ArrayCollection();
  143.         $this->videos = new ArrayCollection();
  144.         $this->providedServices = new ArrayCollection();
  145.     }
  146.     public static function draft(?\DateTimeImmutable $createdAt null): self
  147.     {
  148.         $saloon = new static($createdAt);
  149.         return $saloon;
  150.     }
  151.     public function defineUriIdentity(string $uriIdentity): void
  152.     {
  153.         if (!$this->isDraft()) {
  154.             throw new \DomainException('Saloon is already created and can\'t change its URI.');
  155.         }
  156.         $this->uriIdentity $uriIdentity;
  157.         $this->draft false;
  158.     }
  159.     public function isDraft(): bool
  160.     {
  161.         return $this->draft;
  162.     }
  163.     public function hasOwner(): bool
  164.     {
  165.         return null !== $this->owner;
  166.     }
  167.     public function setNameAndDescription(TranslatableValue $nameTranslatableValue $description): void
  168.     {
  169.         if (!empty($name)) {
  170.             $this->name $name;
  171.         }
  172.         if (!empty($description)) {
  173.             $this->description $description;
  174.         }
  175.     }
  176.     public function setLocation(City $city$stations$districts$address, ?MapCoordinate $mapCoordinate): void
  177.     {
  178.         $this->city $city;
  179.         if (null !== $stations) {
  180.             if (is_array($stations)) {
  181.                 $stations = new ArrayCollection($stations);
  182.             } elseif (!$stations instanceof ArrayCollection) {
  183.                 if (is_iterable($stations)) {
  184.                     $stations = new ArrayCollection(iterator_to_array($stations));
  185.                 } else {
  186.                     throw new \InvalidArgumentException('Stations list should be either an array or an ArrayCollection');
  187.                 }
  188.             }
  189.             $this->stations $stations;
  190.         }
  191.         if (!empty($districts)) {
  192.             $this->districts $districts;
  193.         }
  194.         if (!empty($address)) {
  195.             $this->address $address;
  196.         }
  197.         $this->mapCoordinate $mapCoordinate;
  198.         $this->normalizePrimaryStation();
  199.     }
  200.     private function normalizePrimaryStation(): void
  201.     {
  202.         if ($this->stations->isEmpty()) {
  203.             $this->primaryStation null;
  204.             return;
  205.         }
  206.         if ($this->primaryStation === null || !$this->stations->contains($this->primaryStation)) {
  207.             $this->primaryStation $this->stations->first();
  208.         }
  209.     }
  210.     public function setPhoneCallOptions(string $phoneNumber, ?PhoneCallRestrictions $restrictions, ?Messengers $messengers): void
  211.     {
  212.         $this->phoneNumber $phoneNumber;
  213.         $this->phoneCallRestrictions $restrictions;
  214.         $this->messengers $messengers;
  215.     }
  216.     public function setPricing(?ApartmentsPricing $apartmentsPricing, ?TakeOutPricing $takeOutPricing, ?int $extraCharge, ?ExpressPricing $expressPricing null): void
  217.     {
  218. //        $this->prices = $pricing;
  219.         $this->apartmentsPricing $apartmentsPricing;
  220.         $this->takeOutPricing $takeOutPricing;
  221.         $this->extraCharge $extraCharge;
  222.         $this->expressPricing $expressPricing;
  223.     }
  224.     public function isOwnedBy(Advertiser $account): bool
  225.     {
  226.         return $account->getId() === $this->owner->getId();
  227.     }
  228.     public function getId(): int
  229.     {
  230.         return $this->id;
  231.     }
  232.     public function getOwner(): ?Advertiser
  233.     {
  234.         return $this->owner;
  235.     }
  236.     public function setOwner(Advertiser $owner): void
  237.     {
  238.         $this->owner $owner;
  239.     }
  240.     public function getAdBoardPlacement(): ?AdBoardPlacement
  241.     {
  242.         return $this->adBoardPlacement;
  243.     }
  244.     /**
  245.      * Салон оплачен и выводится в общих списках на сайте
  246.      */
  247.     public function isActive(): bool
  248.     {
  249.         return null !== $this->adBoardPlacement;
  250.     }
  251.     public function getUriIdentity(): string
  252.     {
  253.         return $this->uriIdentity;
  254.     }
  255.     public function getName(): TranslatableValue
  256.     {
  257.         return $this->name;
  258.     }
  259.     public function getDescription(): TranslatableValue
  260.     {
  261.         return $this->description;
  262.     }
  263.     public function getPhoneNumber(): string
  264.     {
  265.         return $this->phoneNumber;
  266.     }
  267.     public function getWorkingHours(): ?WorkingHours
  268.     {
  269.         return $this->workingHours;
  270.     }
  271.     public function setWorkingHours(?WorkingHours $workingHours): void
  272.     {
  273. //        $this->phoneNumber = $phoneNumber;
  274.         $this->workingHours $workingHours;
  275.     }
  276.     //TODO return type
  277.     public function getEmail(): ?string
  278.     {
  279.         return $this->email;
  280.     }
  281.     public function setEmail(string $email): void
  282.     {
  283.         $this->email $email;
  284.     }
  285.     public function getPrices(): ?string
  286.     {
  287.         return $this->prices;
  288.     }
  289.     //TODO return type
  290.     public function getApartmentsPricing(): ?ApartmentsPricing
  291.     {
  292.         return $this->apartmentsPricing;
  293.     }
  294.     //TODO return type
  295.     public function getTakeOutPricing(): ?TakeOutPricing
  296.     {
  297.         return $this->takeOutPricing;
  298.     }
  299.     public function getExtraCharge(): ?int
  300.     {
  301.         return $this->extraCharge;
  302.     }
  303.     public function getThumbnail(): ?Thumbnail
  304.     {
  305.         return $this->thumbnail;
  306.     }
  307.     public function setThumbnail(string $path): void
  308.     {
  309.         $this->thumbnail = new Thumbnail($this$path);
  310.     }
  311.     public function getCity(): City
  312.     {
  313.         return $this->city;
  314.     }
  315.     /**
  316.      * @return Station[]
  317.      */
  318.     public function getStations(): Collection
  319.     {
  320.         return $this->stations;
  321.     }
  322.     public function getDistricts(): ?string
  323.     {
  324.         return $this->districts;
  325.     }
  326.     public function getAddress(): TranslatableValue
  327.     {
  328.         return $this->address;
  329.     }
  330.     public function getMapCoordinate(): ?MapCoordinate
  331.     {
  332.         return $this->mapCoordinate;
  333.     }
  334.     public function getUpdatedAt(): ?\DateTimeImmutable
  335.     {
  336.         return $this->updatedAt;
  337.     }
  338.     //TODO return type
  339.     public function setUpdatedAt(\DateTimeImmutable $updatedAt): void
  340.     {
  341.         $this->updatedAt $updatedAt;
  342.     }
  343.     public function addPhoto(string $path): Photo
  344.     {
  345.         $photos $this->getPhotos();
  346.         $found $photos->filter(function (Photo $photo) use ($path): bool {
  347.             return $path === $photo->getPath();
  348.         });
  349.         if (!$found->isEmpty()) {
  350.             return $found->first();
  351.         }
  352.         $photo = new Photo($this$path);
  353.         $this->photos->add($photo);
  354.         return $photo;
  355.     }
  356.     /**
  357.      * @return Photo[]
  358.      */
  359.     public function getPhotos(): Collection
  360.     {
  361.         return $this->photos;
  362.     }
  363.     public function removePhoto(string $path): void
  364.     {
  365.         foreach ($this->getPhotos() as $photo) {
  366.             if ($path === $photo->getPath()) {
  367.                 $this->photos->removeElement($photo);
  368.             }
  369.         }
  370.     }
  371.     public function addVideo(string $path): Video
  372.     {
  373.         $found $this->getVideos()->filter(function (Video $video) use ($path): bool {
  374.             return $path === $video->getPath();
  375.         });
  376.         if (!$found->isEmpty())
  377.             return $found->first();
  378.         $video = new Video($this$path);
  379.         //теперь разрешаем много видео
  380.         //$this->videos->clear();
  381.         $this->videos->add($video);
  382.         return $video;
  383.     }
  384.     /**
  385.      * @return Photo[]
  386.      */
  387.     public function getVideos(): Collection
  388.     {
  389.         return $this->videos;
  390.     }
  391.     public function removeVideo(string $path): void
  392.     {
  393.         foreach ($this->getVideos() as $video) {
  394.             if ($path === $video->getPath()) {
  395.                 $this->videos->removeElement($video);
  396.             }
  397.         }
  398.     }
  399.     public function isMediaProcessed(): bool
  400.     {
  401.         foreach ($this->videos as $video)
  402.             if (null === $video->getPreviewPath())
  403.                 return false;
  404.         return true;
  405.     }
  406.     public function delete(): void
  407.     {
  408.         $this->deletePlacementHiding();
  409.         $this->deleteFromAdBoard();
  410.         $this->setDeletedAt(Carbon::now());
  411.     }
  412.     public function deletePlacementHiding(): void
  413.     {
  414.         $this->placementHiding null;
  415.     }
  416.     public function deleteFromAdBoard(): void
  417.     {
  418.         $this->adBoardPlacement null;
  419.     }
  420.     //TODO return type
  421.     public function undoDelete(): void
  422.     {
  423.         $this->setDeletedAt(); // will pass null by default
  424.     }
  425.     //TODO return type
  426.     public function getPhoneCallRestrictions(): ?PhoneCallRestrictions
  427.     {
  428.         return $this->phoneCallRestrictions;
  429.     }
  430.     public function getExpressPricing(): ?ExpressPricing
  431.     {
  432.         return $this->expressPricing;
  433.     }
  434.     public function getClientTypes(): ?array
  435.     {
  436.         return $this->clientTypes;
  437.     }
  438.     //TODO return type
  439.     /**
  440.      * @param int[] $clientTypes
  441.      */
  442.     public function setClientTypes(?array $clientTypes): void
  443.     {
  444.         $this->clientTypes $clientTypes;
  445.     }
  446.     public function getMessengers(): ?Messengers
  447.     {
  448.         return $this->messengers;
  449.     }
  450.     public function getInactivatedAt(): ?\DateTimeImmutable
  451.     {
  452.         return $this->inactivatedAt;
  453.     }
  454.     public function setInactive(): void
  455.     {
  456.         $this->inactivatedAt CarbonImmutable::now();
  457.     }
  458.     public function undoInactive(): void
  459.     {
  460.         $this->inactivatedAt null;
  461.     }
  462.     public function isHidden(): bool
  463.     {
  464.         return null !== $this->getPlacementHiding();
  465.     }
  466.     public function getPlacementHiding(): ?PlacementHiding
  467.     {
  468.         return $this->placementHiding;
  469.     }
  470.     /**
  471.      * @return CommentByCustomer[]
  472.      */
  473.     public function getComments(): Collection
  474.     {
  475.         return $this->comments->filter(function (CommentByCustomer $comment): bool {
  476.             return null == $comment->getParent();
  477.         });
  478.     }
  479.     /**
  480.      * @return CommentByCustomer[]
  481.      */
  482.     public function getCommentsOrderedByNotReplied(): array
  483.     {
  484.         $comments $this->comments->filter(function (CommentByCustomer $comment): bool {
  485.             return null == $comment->getParent();
  486.         })->toArray();
  487.         usort($comments, function (CommentByCustomer $commentACommentByCustomer $commentB): int {
  488.             if ((null == $commentA->getLastCommentByAdvertiser() && null == $commentB->getLastCommentByAdvertiser())
  489.                 || (null != $commentA->getLastCommentByAdvertiser() && null != $commentB->getLastCommentByAdvertiser())) {
  490.                 if ($commentA->getCreatedAt() == $commentB->getCreatedAt())
  491.                     return $commentA->getId() > $commentB->getId() ? -1;
  492.                 else
  493.                     return $commentA->getCreatedAt() > $commentB->getCreatedAt() ? -1;
  494.             }
  495.             if (null == $commentA->getLastCommentByAdvertiser() && null != $commentB->getLastCommentByAdvertiser())
  496.                 return -1;
  497.             else
  498.                 return 1;
  499.         });
  500.         return $comments;
  501.     }
  502.     public function getCreatedAt(): ?\DateTimeImmutable
  503.     {
  504.         return $this->createdAt;
  505.     }
  506.     /**
  507.      * @return CommentByCustomer[]
  508.      */
  509.     public function getCommentsWithoutReply(): Collection
  510.     {
  511.         return $this->comments->filter(function (CommentByCustomer $comment): bool {
  512.             return null == $comment->getParent() && false == $comment->isCommentedByAdvertiser();
  513.         });
  514.     }
  515.     /**
  516.      * @return CommentByCustomer[]
  517.      */
  518.     public function getCommentsWithReply(): Collection
  519.     {
  520.         return $this->comments->filter(function (CommentByCustomer $comment): bool {
  521.             return null == $comment->getParent() && true == $comment->isCommentedByAdvertiser();
  522.         });
  523.     }
  524.     /**
  525.      * @return CommentByCustomer[]
  526.      */
  527.     public function getNewComments(): Collection
  528.     {
  529.         $weekAgo CarbonImmutable::now()->sub('7 days');
  530.         return $this->comments->filter(function (CommentByCustomer $comment) use ($weekAgo): bool {
  531.             return null == $comment->getParent()
  532.                 && (
  533.                     $comment->getCreatedAt() >= $weekAgo
  534.                     || null == $this->getCommentReply($comment)
  535.                 );
  536.         });
  537.     }
  538.     private function getCommentReply(CommentByCustomer $parent): ?CommentByCustomer
  539.     {
  540.         foreach ($this->comments as $comment)
  541.             if ($comment->getParent() == $parent)
  542.                 return $comment;
  543.         return null;
  544.     }
  545.     public function getOldComments(): Collection
  546.     {
  547.         $weekAgo CarbonImmutable::now()->sub('7 days');
  548.         return $this->comments->filter(function (CommentByCustomer $comment) use ($weekAgo): bool {
  549.             return null == $comment->getParent()
  550.                 && false == (
  551.                     $comment->getCreatedAt() >= $weekAgo
  552.                     || null == $this->getCommentReply($comment)
  553.                 );
  554.         });
  555.     }
  556.     public function getCommentFromUser(Customer $user): ?CommentByCustomer
  557.     {
  558.         foreach ($this->comments as $comment)
  559.             if (null == $comment->getParent() && null != $comment->getUser() && $user->getId() == $comment->getUser()->getId())
  560.                 return $comment;
  561.         return null;
  562.     }
  563.     public function seo(): ?array
  564.     {
  565.         return $this->seo;
  566.     }
  567.     public function seoPhoneNumber(): ?string
  568.     {
  569.         return $this->seo['phone'] ?? null;
  570.     }
  571.     public function setSeoPhoneNumber(string $phoneNumber): void
  572.     {
  573.         if (null === $this->seo) {
  574.             $this->seo = [];
  575.         }
  576.         $this->seo['phone'] = $phoneNumber;
  577.     }
  578.     public function getPrimaryStation(): ?Station
  579.     {
  580.         $station $this->primaryStation ?? $this->getStations()->first();
  581.         if (false === $station) {
  582.             return null;
  583.         }
  584.         return $station;
  585.     }
  586.     public function setPrimaryStation(?Station $station): void
  587.     {
  588.         $this->primaryStation $station;
  589.         $this->normalizePrimaryStation();
  590.     }
  591.     public function getStationsSortedByPrimary(): array
  592.     {
  593.         $stations $this->stations->toArray();
  594.         if (!$this->primaryStation) {
  595.             return $stations;
  596.         }
  597.         usort($stations, function (Station $aStation $b) {
  598.             if ($a->getId() === $this->primaryStation->getId()) return -1;
  599.             if ($b->getId() === $this->primaryStation->getId()) return 1;
  600.             return 0;
  601.         });
  602.         return $stations;
  603.     }
  604.     public function getDeleteMode(): int
  605.     {
  606.         return $this->deleteMode;
  607.     }
  608.     public function setDeleteMode(int $deleteMode): self
  609.     {
  610.         $this->deleteMode $deleteMode;
  611.         return $this;
  612.     }
  613.     public function isHardDeleted(): bool
  614.     {
  615.         return $this->deleteMode === 2;
  616.     }
  617. }