src/Subscriber/Payment/ConversationMessageSubscriber.php line 68

Open in your IDE?
  1. <?php
  2. namespace App\Subscriber\Payment;
  3. use App\Dictionary\ConversationMessageSource;
  4. use App\Dictionary\ConversationMessageType;
  5. use App\Dictionary\ImageFilter;
  6. use App\Dictionary\PaymentType;
  7. use App\Entity\MemberMedia;
  8. use App\Entity\MemberOperator;
  9. use App\Entity\Payment;
  10. use App\Event\Messenger\NewMessageEvent;
  11. use App\Event\Payment\PaymentCreatedEvent;
  12. use App\Event\RedisEventManager;
  13. use App\Lib\Payment\Booking;
  14. use App\Lib\Payment\PayMethod\AdminBonusMethod;
  15. use App\Lib\Payment\PayMethod\LiquibyteCashpayMethod;
  16. use App\Lib\Payment\PayMethod\LiquibytePrepayMethod;
  17. use App\Lib\Purchase\ConversationMessagePurchasable;
  18. use App\Service\MemberService;
  19. use App\Service\Messenger\MessengerService;
  20. use App\Service\Payment\PurchaseService;
  21. use Frivol\Common\Service\Notification\MessengerNotification;
  22. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  23. class ConversationMessageSubscriber implements EventSubscriberInterface
  24. {
  25.     protected MessengerService $messenger;
  26.     protected MemberService $memberService;
  27.     protected PurchaseService $purchaseService;
  28.     protected RedisEventManager $redisEvent;
  29.     protected array $methodWhitelistForNotification = [
  30.         LiquibytePrepayMethod::NAME,
  31.         LiquibyteCashpayMethod::NAME,
  32.         AdminBonusMethod::NAME,
  33.     ];
  34.     public function __construct(MemberService $memberServiceMessengerService $messenger,
  35.         PurchaseService $purchaseServiceRedisEventManager $redisEvent)
  36.     {
  37.         $this->memberService $memberService;
  38.         $this->messenger $messenger;
  39.         $this->purchaseService $purchaseService;
  40.         $this->redisEvent $redisEvent;
  41.     }
  42.     public static function getSubscribedEvents(): array
  43.     {
  44.         return [
  45.             PaymentCreatedEvent::class => [
  46.                 ['sendMessageNotification'0],
  47.             ],
  48.             NewMessageEvent::class => [
  49.                 ['onNewMessageHandlePurchase'0],
  50.                 ['onHandwrittenMessageByAmateurCreateProvision'1],
  51.                 ['sendPubSubNotification'2],
  52.                 ['sendPubSubOperatorNotification'3],
  53.             ],
  54.         ];
  55.     }
  56.     /**
  57.      * @throws \App\Exception\Commission\NotAnAmateurException
  58.      * @throws \Doctrine\ORM\ORMException
  59.      * @throws \Doctrine\ORM\OptimisticLockException
  60.      */
  61.     public function onHandwrittenMessageByAmateurCreateProvision(NewMessageEvent $event)
  62.     {
  63.         $entity $event->getEntity();
  64.         $sender $event->getSender();
  65.         if (!$entity->mayBeProvisionedForAmateur()) {
  66.             return;
  67.         }
  68.         $conversation $entity->getConversation();
  69.         $openPurchases $this->purchaseService->getOpenMessagePurchases($sender$conversation);
  70.         foreach ($openPurchases as $purchase) {
  71.             $this->purchaseService->assignAmateurProvisionByPurchase($purchase);
  72.         }
  73.     }
  74.     /**
  75.      * @throws \App\Exception\Purchase\CoinsLockedException
  76.      * @throws \App\Exception\Purchase\InsufficientCoinsException
  77.      * @throws \Doctrine\ORM\ORMException
  78.      * @throws \Doctrine\ORM\OptimisticLockException
  79.      */
  80.     public function onNewMessageHandlePurchase(NewMessageEvent $event)
  81.     {
  82.         $entity $event->getEntity();
  83.         if (!$entity->needsToBePurchased()) {
  84.             return;
  85.         }
  86.         $buyer $event->getSender();
  87.         $seller $entity->getConversation()->getPartner($buyer);
  88.         $purchasable = new ConversationMessagePurchasable($entity$seller);
  89.         $this->purchaseService->handlePurchase($purchasable$buyer);
  90.     }
  91.     /**
  92.      * @throws \Doctrine\ORM\ORMException
  93.      * @throws \Doctrine\ORM\OptimisticLockException
  94.      */
  95.     public function sendMessageNotification(PaymentCreatedEvent $event)
  96.     {
  97.         $payment $event->getPayment();
  98.         if (PaymentType::BOOKING !== $payment->getType()) {
  99.             return;
  100.         }
  101.         if (!in_array($payment->getMethod(), $this->methodWhitelistForNotification)) {
  102.             return;
  103.         }
  104.         $member $payment->getAccount()->getMember();
  105.         $support $this->memberService->getSupportMember();
  106.         /*
  107.          * No support user configured OR support _is_ the affected member
  108.          */
  109.         if (null === $support || $support->getId() == $member->getId()) {
  110.             return;
  111.         }
  112.         /**
  113.          * @var $booking Booking
  114.          */
  115.         $booking $event->getPaymentConceptObject();
  116.         if (AdminBonusMethod::NAME == $payment->getMethod() && $booking && $booking->getOverrideCoins()) {
  117.             $amount $booking->getOverrideCoins();
  118.         } else {
  119.             $amount number_format($payment->getAmount(), 2',''.');
  120.         }
  121.         $msg sprintf($this->getMessageFormat($payment), $member->getUsername(), $amount);
  122.         $source ConversationMessageSource::SYSTEM;
  123.         $type ConversationMessageType::TEXT;
  124.         $this->messenger->sendDirectMessage($support$member$msg$type$source);
  125.     }
  126.     public function sendPubSubOperatorNotification(NewMessageEvent $event): void
  127.     {
  128.         $message $event->getEntity();
  129.         $from $event->getSender();
  130.         $recipient $message->getConversation()->getPartner($from);
  131.         // only interested in messages from endusers -to- amateurs
  132.         if ($from->getIsAmateur() || !$recipient->getIsAmateur()) {
  133.             return;
  134.         }
  135.         // also not interested, if the amateur does not have at least one operator
  136.         if (!$recipient->getOperators()->count()) {
  137.             return;
  138.         }
  139.         foreach ($recipient->getOperators() as $operatorRelationship) {
  140.             /**
  141.              * @var $operatorRelationship MemberOperator
  142.              */
  143.             if (!$operatorRelationship->getIsOnline()) {
  144.                 // also not interested, if it appears that the operator is not
  145.                 // actively working for the amateur who received the message
  146.                 continue;
  147.             }
  148.             $operatorMember $operatorRelationship->getOperator();
  149.             if (!$operatorMember->isMemberOnline()) {
  150.                 // another case: appears the operating member is not online himself
  151.                 continue;
  152.             }
  153.             // all good actually. notify the frontend operator app about the incoming message
  154.             $notification = new MessengerNotification();
  155.             $data = [
  156.                 'fromMember' => $from->getId(),
  157.                 'fromUsername' => $from->getUsername(),
  158.                 'toMember' => $recipient->getId(),
  159.                 'toUsername' => $recipient->getUsername(),
  160.                 'partner' => [
  161.                     'id' => $from->getId(),
  162.                     'username' => $from->getUsername(),
  163.                 ],
  164.                 'message' => $event->getEntity()->getMessage(),
  165.                 'conversation' => $message->getConversation()->getId(),
  166.                 'source' => $message->getSource(),
  167.                 'created_at' => $message->getCreatedAt()->format(\DateTimeInterface::ATOM),
  168.             ];
  169.             if ($from->getMainPhoto() instanceof MemberMedia) {
  170.                 $data['image'] = $from->getMainPhoto()->getUrl(ImageFilter::SIZE_100x100);
  171.             }
  172.             $notification->setData($data);
  173.             // recipient is the operator! (2nd param)
  174.             // $this->redisEvent->publishToMemberWithFrom($from, $operatorMember, $notification);
  175.         }
  176.     }
  177.     public function sendPubSubNotification(NewMessageEvent $event): void
  178.     {
  179.         $from $event->getSender();
  180.         $message $event->getEntity();
  181.         $recipient $message->getConversation()->getPartner($from);
  182.         $notification = new MessengerNotification();
  183.         $data = [
  184.             'fromMember' => $from->getId(),
  185.             'fromUsername' => $from->getUsername(),
  186.             'toMember' => $recipient->getId(),
  187.             'toUsername' => $recipient->getUsername(),
  188.             'partner' => [
  189.                 'id' => $from->getId(),
  190.                 'username' => $from->getUsername(),
  191.             ],
  192.             'message' => $event->getEntity()->getMessage(),
  193.             'conversation' => $message->getConversation()->getId(),
  194.             'source' => $message->getSource(),
  195.             'created_at' => $message->getCreatedAt()->format(\DateTimeInterface::ATOM),
  196.         ];
  197.         if ($from->getMainPhoto() instanceof MemberMedia) {
  198.             $data['image'] = $from->getMainPhoto()->getUrl(ImageFilter::SIZE_100x100);
  199.         }
  200.         $notification->setData($data);
  201.         $this->redisEvent->publishToMemberWithFrom($from$recipient$notification);
  202.     }
  203.     public function getMessageFormat(Payment $payment): string
  204.     {
  205.         if (AdminBonusMethod::NAME == $payment->getMethod()) {
  206.             return 'Hallo %s,'.
  207.                 "\nwir haben dir soeben einen Bonus in Höhe von %d Coins verbucht.".
  208.                 "\nViel Spaß!".
  209.                 "\nFür weitere Fragen stehen wir dir gerne zur Verfügung.".
  210.                 "\nLiebe Grüße vom Frivol.com Support";
  211.         }
  212.         return 'Hallo %s,'.
  213.             "\nwir haben deine Zahlung über %s EUR erhalten und soeben verbucht. Du kannst die Coins ab sofort nutzen.".
  214.             "\nViel Spaß!".
  215.             "\nFür weitere Fragen stehen wir dir gerne zur Verfügung.".
  216.             "\nLiebe Grüße vom Frivol.com Support";
  217.     }
  218. }