Covivo/mobicoop

View on GitHub
api/src/User/Service/IdentityProofManager.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

/**
 * Copyright (c) 2022, 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\User\Service;

use App\User\Entity\IdentityProof;
use App\User\Entity\User;
use App\User\Event\IdentityProofModeratedEvent;
use App\User\Event\IdentityProofValidationReminderEvent;
use App\User\Repository\IdentityProofRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Security\Core\Security;

class IdentityProofManager
{
    private $admin;
    private $identityProofRepository;
    private $entityManager;
    private $eventDispatcher;
    private $uploadPath;
    private $urlPath;

    public function __construct(
        Security $security,
        IdentityProofRepository $identityProofRepository,
        EntityManagerInterface $entityManager,
        EventDispatcherInterface $eventDispatcher,
        string $uploadPath,
        string $urlPath
    ) {
        $this->admin = $security->getUser();
        $this->identityProofRepository = $identityProofRepository;
        $this->entityManager = $entityManager;
        $this->eventDispatcher = $eventDispatcher;
        $this->uploadPath = $uploadPath;
        $this->urlPath = $urlPath;
    }

    public function createIdentityProof(User $user, File $file): IdentityProof
    {
        if ($this->userHasAcceptedProof($user)) {
            throw new \Exception('This user already has an accepted identity proof.');
        }
        $pendingProof = $this->getPendingProofForUser($user);
        if ($pendingProof) {
            $pendingProof->setStatus(IdentityProof::STATUS_CANCELED);
            $this->removeProofFile($pendingProof);
            $this->entityManager->persist($pendingProof);
            $this->entityManager->flush();
        }
        $identityProof = new IdentityProof();
        $identityProof->setFile($file);
        $identityProof->setUser($user);
        $identityProof->setFileName($user->getId().'-'.time());
        $identityProof->setStatus(IdentityProof::STATUS_PENDING);

        return $identityProof;
    }

    public function postIdentityProof(IdentityProof $identityProof)
    {
        if ($this->userHasAcceptedProof($identityProof->getUser())) {
            throw new \Exception('This user already has an accepted identity proof.');
        }
        $identityProof->setStatus(IdentityProof::STATUS_ACCEPTED);
        $identityProof->setAdmin($this->admin);

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

        $event = new IdentityProofModeratedEvent($identityProof);
        $this->eventDispatcher->dispatch(IdentityProofModeratedEvent::NAME, $event);

        return $identityProof;
    }

    public function patchIdentityProof(int $id, array $fields)
    {
        $identityProof = $this->identityProofRepository->find($id);

        if (!$identityProof) {
            throw new \Exception('Identity proof not found');
        }

        if (array_key_exists('validate', $fields)) {
            if (IdentityProof::STATUS_PENDING != $identityProof->getStatus()) {
                throw new \Exception('Identity proof status is not pending');
            }

            return $this->validateIdentityProof($identityProof, $fields['validate']);
        }

        return $identityProof;
    }

    public function getFileUrl(IdentityProof $identityProof)
    {
        if (IdentityProof::STATUS_PENDING == $identityProof->getStatus()) {
            return $this->urlPath.rawurlencode($identityProof->getFileName());
        }

        return null;
    }

    public function getFileUrlFromArray(array $identityProof)
    {
        if (IdentityProof::STATUS_PENDING == $identityProof['status']) {
            return $this->urlPath.rawurlencode($identityProof['fileName']);
        }

        return null;
    }

    public function sendReminders()
    {
        $now = new \DateTime('now');
        $identityProofs = $this->identityProofRepository->findBy(['status' => IdentityProof::STATUS_PENDING]);
        foreach ($identityProofs as $identityProof) {
            foreach (IdentityProof::INTERVALS_REMINDER as $interval) {
                $modifiedDate = clone $identityProof->getCreatedDate();
                $modifiedDate->modify($interval);
                if ($modifiedDate->format('d/m/Y') === $now->format('d/m/Y')) {
                    $event = new IdentityProofValidationReminderEvent($identityProof);
                    $this->eventDispatcher->dispatch(IdentityProofValidationReminderEvent::NAME, $event);

                    break;
                }
            }
        }
    }

    private function validateIdentityProof(IdentityProof $identityProof, bool $validate): IdentityProof
    {
        $identityProof->setAdmin($this->admin);
        $identityProof->setStatus($validate ? IdentityProof::STATUS_ACCEPTED : IdentityProof::STATUS_REFUSED);
        $this->entityManager->persist($identityProof);
        $this->entityManager->flush();
        $this->removeProofFile($identityProof);

        $event = new IdentityProofModeratedEvent($identityProof);
        $this->eventDispatcher->dispatch(IdentityProofModeratedEvent::NAME, $event);

        return $identityProof;
    }

    private function userHasAcceptedProof(User $user): bool
    {
        return null !== $this->identityProofRepository->findOneBy([
            'user' => $user,
            'status' => IdentityProof::STATUS_ACCEPTED,
        ]);
    }

    private function getPendingProofForUser(User $user): ?IdentityProof
    {
        return $this->identityProofRepository->findOneBy([
            'user' => $user,
            'status' => IdentityProof::STATUS_PENDING,
        ]);
    }

    private function removeProofFile(IdentityProof $identityProof)
    {
        if (file_exists($this->uploadPath.$identityProof->getFileName())) {
            unlink($this->uploadPath.$identityProof->getFileName());
        }
    }
}