Covivo/mobicoop

View on GitHub
api/src/Action/Service/ActionManager.php

Summary

Maintainability
D
2 days
Test Coverage
<?php

/**
 * Copyright (c) 2020, MOBICOOP. All rights reserved.
 * This project is dual licensed under AGPL and proprietary licence.
 ***************************
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as
 *    published by the Free Software Foundation, either version 3 of the
 *    License, or (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <gnu.org/licenses>.
 ***************************
 *    Licence MOBICOOP described in the file
 *    LICENSE
 **************************/

namespace App\Action\Service;

use Symfony\Contracts\EventDispatcher\Event;
use App\Action\Entity\Action;
use App\Action\Entity\Animation;
use App\Action\Entity\Log;
use App\Action\Event\ActionEvent;
use App\Action\Event\LogEvent;
use App\Action\Exception\ActionException;
use App\Action\Repository\ActionRepository;
use App\Action\Service\DiaryManager;
use App\App\Entity\App;
use App\Communication\Service\NotificationManager;
use App\Solidary\Entity\Solidary;
use App\Solidary\Entity\SolidaryAnimation;
use App\Solidary\Entity\SolidarySolution;
use App\Solidary\Event\SolidaryAnimationPostedEvent;
use App\Solidary\Event\SolidaryContactEmailEvent;
use App\Solidary\Event\SolidaryContactMessageEvent;
use App\Solidary\Event\SolidaryContactSmsEvent;
use App\Solidary\Event\SolidaryCreatedEvent;
use App\Solidary\Event\SolidaryUpdatedEvent;
use App\Solidary\Event\SolidaryUserCreatedEvent;
use App\Solidary\Event\SolidaryUserStructureAcceptedEvent;
use App\Solidary\Event\SolidaryUserStructureRefusedEvent;
use App\Solidary\Event\SolidaryUserUpdatedEvent;
use App\Solidary\Exception\SolidaryException;
use App\User\Entity\User;
use App\User\Event\LoginDelegateEvent;
use Symfony\Component\Security\Core\Security;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * Action Manager
 *
 * @author Maxime Bardot <maxime.bardot@mobicoop.org>
 */
class ActionManager
{
    private $notificationManager;
    private $diaryManager;
    private $actionRepository;
    private $security;
    private $entityManager;
    private $eventDispatcher;

    public function __construct(
        NotificationManager $notificationManager,
        DiaryManager $diaryManager,
        ActionRepository $actionRepository,
        Security $security,
        EntityManagerInterface $entityManager,
        EventDispatcherInterface $eventDispatcher
    ) {
        $this->notificationManager = $notificationManager;
        $this->diaryManager = $diaryManager;
        $this->actionRepository = $actionRepository;
        $this->security = $security;
        $this->entityManager = $entityManager;
        $this->eventDispatcher = $eventDispatcher;
    }
    
    /**
     * Get an Action by its name
     *
     * @param string $name  The action's name
     * @return Action
     */
    public function getActionByName(string $name): Action
    {
        $action = $this->actionRepository->findOneBy(['name'=>$name]);
        if (is_null($action)) {
            throw new ActionException(ActionException::BAD_ACTION);
        }
        return $action;
    }
    
    /**
     * Handle events
     *
     * @param string $actionName    Name of the action of this event
     * @param Event $event          Event of the action
     * @return void
     */
    public function handleAction(string $actionName, Event $event=null)
    {
        // Get the action
        $action = $this->actionRepository->findOneBy(['name'=>$actionName]);
        if (empty($action)) {
            throw new ActionException(ActionException::BAD_ACTION);
        }
        switch ($actionName) {
            case SolidaryUserStructureAcceptedEvent::NAME:$this->onSolidaryUserStructureAccepted($action, $event);
                break;
            case SolidaryUserStructureRefusedEvent::NAME:$this->onSolidaryUserStructureRefused($action, $event);
                break;
            case SolidaryUserCreatedEvent::NAME:$this->onSolidaryUserCreated($action, $event);
                break;
            case SolidaryUserUpdatedEvent::NAME:$this->onSolidaryUserUpdated($action, $event);
                break;
            case SolidaryCreatedEvent::NAME:$this->onSolidaryCreated($action, $event);
                break;
            case SolidaryUpdatedEvent::NAME:$this->onSolidaryUpdated($action, $event);
                break;
            case SolidaryContactMessageEvent::NAME:$this->onSolidaryContactMessage($action, $event);
                break;
            case SolidaryContactSmsEvent::NAME:$this->onSolidaryContactSms($action, $event);
                break;
            case SolidaryContactEmailEvent::NAME:$this->onSolidaryContactEmail($action, $event);
                break;
            case SolidaryAnimationPostedEvent::NAME:$this->onSolidaryAnimationPosted($event);
                break;
            case LoginDelegateEvent::NAME:$this->onLoginDelegate($action, $event);
                break;
        }
    }

    private function onSolidaryUserStructureAccepted(Action $action, SolidaryUserStructureAcceptedEvent $event)
    {
        $user = $event->getSolidaryUserStructure()->getSolidaryUser()->getUser();
        $admin = $this->security->getUser();
        $this->treatDiary($action, $user, $admin);
    }

    private function onSolidaryUserStructureRefused(Action $action, SolidaryUserStructureRefusedEvent $event)
    {
        $user = $event->getSolidaryUserStructure()->getSolidaryUser()->getUser();
        $admin = $this->security->getUser();
        $this->treatDiary($action, $user, $admin);
    }

    private function onSolidaryUserCreated(Action $action, SolidaryUserCreatedEvent $event)
    {
        $this->treatDiary($action, $event->getUser(), $event->getAuthor());
    }

    private function onSolidaryUserUpdated(Action $action, SolidaryUserUpdatedEvent $event)
    {
        $user = $event->getSolidaryUser()->getUser();
        $admin = $this->security->getUser();
        $this->treatDiary($action, $user, $admin);
    }

    private function onSolidaryCreated(Action $action, SolidaryCreatedEvent $event)
    {
        $this->treatDiary($action, $event->getUser(), $event->getAuthor(), null, $event->getSolidary());
    }

    private function onSolidaryUpdated(Action $action, SolidaryUpdatedEvent $event)
    {
        $user = $event->getSolidary()->getSolidaryUserStructure()->getSolidaryUser()->getUser();
        $admin = $this->security->getUser();
        $this->treatDiary($action, $user, $admin, null, $event->getSolidary());
    }

    private function onSolidaryContactMessage(Action $action, SolidaryContactMessageEvent $event)
    {
        $solidaryContact = $event->getSolidaryContact();
        $user = $solidaryContact->getSolidarySolution()->getSolidary()->getSolidaryUserStructure()->getSolidaryUser()->getUser();
        
        
        if (!is_null($solidaryContact->getSolidarySolution()->getSolidaryMatching()->getMatching())) {
            $recipient = $solidaryContact->getSolidarySolution()->getSolidaryMatching()->getMatching()->getProposalOffer()->getUser();
        } else {
            $recipient = $solidaryContact->getSolidarySolution()->getSolidaryMatching()->getSolidaryUser()->getUser();
        }
        $admin = $this->security->getUser();

        // Trigger the message by notifies
        $this->notificationManager->notifies(SolidaryContactMessageEvent::NAME, $recipient, $event->getSolidaryContact());


        // Store in diary
        $this->treatDiary($action, $user, $admin, null, $event->getSolidaryContact()->getSolidarySolution()->getSolidary());
    }

    private function onSolidaryContactSms(Action $action, SolidaryContactSmsEvent $event)
    {
        $solidaryContact = $event->getSolidaryContact();
        $user = $solidaryContact->getSolidarySolution()->getSolidary()->getSolidaryUserStructure()->getSolidaryUser()->getUser();
        
        
        if (!is_null($solidaryContact->getSolidarySolution()->getSolidaryMatching()->getMatching())) {
            $recipient = $solidaryContact->getSolidarySolution()->getSolidaryMatching()->getMatching()->getProposalOffer()->getUser();
        } else {
            $recipient = $solidaryContact->getSolidarySolution()->getSolidaryMatching()->getSolidaryUser()->getUser();
        }
        $admin = $this->security->getUser();

        // Trigger the sms by notifies (need to add lines in table notification)
        $this->notificationManager->notifies(SolidaryContactSmsEvent::NAME, $recipient, $event->getSolidaryContact());

        // Store in diary
        $this->treatDiary($action, $user, $admin, null, $event->getSolidaryContact()->getSolidarySolution()->getSolidary());
    }
    
    private function onSolidaryContactEmail(Action $action, SolidaryContactEmailEvent $event)
    {
        $solidaryContact = $event->getSolidaryContact();
        $user = $solidaryContact->getSolidarySolution()->getSolidary()->getSolidaryUserStructure()->getSolidaryUser()->getUser();
        
        
        if (!is_null($solidaryContact->getSolidarySolution()->getSolidaryMatching()->getMatching())) {
            $recipient = $solidaryContact->getSolidarySolution()->getSolidaryMatching()->getMatching()->getProposalOffer()->getUser();
        } else {
            $recipient = $solidaryContact->getSolidarySolution()->getSolidaryMatching()->getSolidaryUser()->getUser();
        }
        $admin = $this->security->getUser();

        // Trigger the email by notifies
        $this->notificationManager->notifies(SolidaryContactEmailEvent::NAME, $recipient, $event->getSolidaryContact());

        // Store in diary
        $this->treatDiary($action, $user, $admin, null, $event->getSolidaryContact()->getSolidarySolution()->getSolidary());
    }

    private function onSolidaryAnimationPosted(SolidaryAnimationPostedEvent $event)
    {
        $solidaryAnimation = $event->getSolidaryAnimation();

        // We get the action of this SolidaryAnimation
        $action = $this->actionRepository->findOneBy(['name'=>$solidaryAnimation->getActionName()]);
        if (empty($action)) {
            throw new SolidaryException(SolidaryException::BAD_SOLIDARY_ACTION);
        }

        $this->treatDiary(
            $action,
            $solidaryAnimation->getUser(),
            $solidaryAnimation->getAuthor(),
            $solidaryAnimation->getComment(),
            $solidaryAnimation->getSolidary(),
            $solidaryAnimation->getSolidarySolution(),
            $solidaryAnimation->getProgression()
        );

        // if the animation also implicate a transporter/carpooler we add a diary entry for that transporter/carpooler
        if ($solidaryAnimation->getSolidarySolution()) {
            $user = null;
            if ($solidaryAnimation->getSolidarySolution()->getSolidaryMatching()->getSolidaryUser()) {
                $user = $solidaryAnimation->getSolidarySolution()->getSolidaryMatching()->getSolidaryUser()->getUser();
            } else {
                $user =  $solidaryAnimation->getSolidarySolution()->getSolidaryMatching()->getMatching()->getProposalOffer()->getUser();
            }
            $this->treatDiary(
                $action,
                $user,
                $solidaryAnimation->getAuthor(),
                $solidaryAnimation->getComment(),
                $solidaryAnimation->getSolidary(),
                null,
                $solidaryAnimation->getProgression()
            );
        }
    }

    private function onLoginDelegate(Action $action, LoginDelegateEvent $event)
    {
        $this->treatDiary($action, $event->getUserDelegated(), $event->getUser());
    }

    /**
     * Check if a diary registration is required and do it
     *
     * @param Action $action
     * @param User $user
     * @param User $author
     * @param string $comment
     * @param Solidary $solidary
     * @param SolidarySolution $solidarySolution
     * @param float $progression
     * @return void
     */
    private function treatDiary(Action $action, User $user, User $author, ?string $comment=null, ?Solidary $solidary=null, ?SolidarySolution $solidarySolution=null, float $progression=0)
    {
        if ($action->isInDiary()) {
            $this->diaryManager->addDiaryEntry(
                $action,
                $user,
                $author,
                $comment,
                $solidary,
                $solidarySolution,
                $progression
            );
        }
    }

    public function onAction(ActionEvent $actionEvent)
    {
        // if Action needs to be logged
        if ($actionEvent->getAction()->isInLog()) {
            $log = new Log();
            $log->setAction($actionEvent->getAction());

            if (!is_null($actionEvent->getUser())) {
                $log->setUser($actionEvent->getUser());
            }
            if (!is_null($actionEvent->getUserDelegate())) {
                $log->setUserDelegate($actionEvent->getUserDelegate());
            }
            if (!is_null($actionEvent->getUserRelated())) {
                $log->setUserRelated($actionEvent->getUserRelated());
            }
            if (!is_null($actionEvent->getProposal())) {
                $log->setProposal($actionEvent->getProposal());
            }
            if (!is_null($actionEvent->getMatching())) {
                $log->setMatching($actionEvent->getMatching());
            }
            if (!is_null($actionEvent->getAsk())) {
                $log->setAsk($actionEvent->getAsk());
            }
            if (!is_null($actionEvent->getArticle())) {
                $log->setArticle($actionEvent->getArticle());
            }
            if (!is_null($actionEvent->getEvent())) {
                $log->setEvent($actionEvent->getEvent());
            }
            if (!is_null($actionEvent->getCommunity())) {
                $log->setCommunity($actionEvent->getCommunity());
            }
            if (!is_null($actionEvent->getSolidary())) {
                $log->setSolidary($actionEvent->getSolidary());
            }
            if (!is_null($actionEvent->getTerritory())) {
                $log->setTerritory($actionEvent->getTerritory());
            }
            if (!is_null($actionEvent->getCar())) {
                $log->setCar($actionEvent->getCar());
            }
            if (!is_null($actionEvent->getMessage())) {
                $log->setMessage($actionEvent->getMessage());
            }
            if (!is_null($actionEvent->getCampaign())) {
                $log->setCampaign($actionEvent->getCampaign());
            }
            if (!is_null($actionEvent->getCarpoolPayment())) {
                $log->setCarpoolPayment($actionEvent->getCarpoolPayment());
            }
            if (!is_null($actionEvent->getCarpoolItem())) {
                $log->setCarpoolItem($actionEvent->getCarpoolItem());
            }

            $this->entityManager->persist($log);
            $this->entityManager->flush();

            // Dispatch a LogEvent
            $event = new LogEvent($log);
            $this->eventDispatcher->dispatch(LogEvent::NAME, $event);
        }
    }
}