TeamInvite::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 15
dl 0
loc 17
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (C) 2020-2025 Iain Cambridge
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
10
 * the Free Software Foundation, either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Parthenon\User\RequestProcessor;
23
24
use Parthenon\Common\Exception\GeneralException;
25
use Parthenon\Common\Exception\RequestProcessor\AlreadyInvitedException;
26
use Parthenon\Common\LoggerAwareTrait;
27
use Parthenon\Common\RequestHandler\RequestHandlerManagerInterface;
28
use Parthenon\Notification\EmailSenderInterface;
29
use Parthenon\User\Entity\MemberInterface;
30
use Parthenon\User\Entity\TeamInviteCode;
31
use Parthenon\User\Entity\UserInterface;
32
use Parthenon\User\Event\PostTeamInviteEvent;
33
use Parthenon\User\Event\PreTeamInviteEvent;
34
use Parthenon\User\Factory\EntityFactory;
35
use Parthenon\User\Form\Type\UserInviteType;
36
use Parthenon\User\Notification\MessageFactory;
37
use Parthenon\User\Repository\TeamInviteCodeRepositoryInterface;
38
use Parthenon\User\Repository\TeamRepositoryInterface;
39
use Parthenon\User\Repository\UserRepositoryInterface;
40
use Symfony\Bundle\SecurityBundle\Security;
41
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
42
use Symfony\Component\Form\FormFactoryInterface;
43
use Symfony\Component\HttpFoundation\Request;
44
use Symfony\Component\HttpFoundation\RequestStack;
45
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
46
47
class TeamInvite
48
{
49
    use LoggerAwareTrait;
50
51
    public function __construct(
52
        private FormFactoryInterface $formFactory,
53
        private Security $security,
54
        private TeamInviteCodeRepositoryInterface $inviteCodeRepository,
55
        private EmailSenderInterface $sender,
56
        private UserInviteType $userInviteType,
57
        private EventDispatcherInterface $dispatcher,
58
        private MessageFactory $messageFactory,
59
        private EntityFactory $entityFactory,
60
        private TeamRepositoryInterface $teamRepository,
61
        private RequestStack $requestStack,
62
        private RequestHandlerManagerInterface $requestHandlerManager,
63
        private AuthorizationCheckerInterface $authorizationChecker,
64
        private UserRepositoryInterface $userRepository,
65
        private string $defaultRole,
66
        private array $roles,
67
    ) {
68
    }
69
70
    public function process(Request $request)
71
    {
72
        $output = ['success' => false, 'already_invited' => false, 'already_a_member' => false, 'hit_limit' => false];
73
74
        $formType = $this->formFactory->create(get_class($this->userInviteType));
75
        $requestHander = $this->requestHandlerManager->getRequestHandler($request);
76
77
        if ($request->isMethod('POST')) {
78
            $requestHander->handleForm($formType, $request);
79
            if ($formType->isSubmitted() && $formType->isValid()) {
80
                $email = $formType->getData()['email'];
81
                $role = $formType->getData()['role'] ?? $this->defaultRole;
82
                $output['processed'] = true;
83
                try {
84
                    $user = $this->security->getUser();
85
                    if (!$user instanceof UserInterface) {
86
                        throw new \InvalidArgumentException('Not a user');
87
                    }
88
89
                    if (!$user instanceof MemberInterface) {
90
                        $this->getLogger()->critical('A user tried to send a team invite when not a member of a team');
91
                        throw new \InvalidArgumentException('Not a member of a team');
92
                    }
93
                    $team = $this->teamRepository->getByMember($user);
94
95
                    if ($this->inviteCodeRepository->hasInviteForEmailAndTeam($email, $team)) {
96
                        throw new AlreadyInvitedException();
97
                    }
98
99
                    if (!in_array($role, $this->roles) && $this->defaultRole !== $role) {
100
                        $this->getLogger()->error('A team invite was not sent due an invalid role being used', ['role' => $role]);
101
                        throw new GeneralException('Invalid role');
102
                    }
103
104
                    $inviteCode = $this->entityFactory->buildTeamInviteCode($user, $team, $email, $role);
105
                    if (!$this->authorizationChecker->isGranted(TeamInviteCode::AUTH_CHECKER_ATTRIBUTE, $inviteCode)) {
106
                        $output['success'] = false;
107
                        $output['hit_limit'] = true;
108
                        $this->getLogger()->info('A team invite was not sent due to plan limits');
109
110
                        return $requestHander->generateErrorOutput($formType, $output);
111
                    }
112
113
                    $this->dispatcher->dispatch(new PreTeamInviteEvent($user, $team, $inviteCode), PreTeamInviteEvent::NAME);
114
                    $this->inviteCodeRepository->save($inviteCode);
115
                    $message = $this->messageFactory->getTeamInviteMessage($user, $team, $inviteCode);
116
117
                    $this->sender->send($message);
118
                    $this->dispatcher->dispatch(new PostTeamInviteEvent($user, $team, $inviteCode), PostTeamInviteEvent::NAME);
119
                    $output['success'] = true;
120
                    $this->requestStack->getSession()->getFlashBag()->add('success', 'parthenon.user.team_invite.success');
121
                    $this->getLogger()->info('A team invite was successfully sent');
122
                } catch (AlreadyInvitedException $e) {
123
                    $this->getLogger()->info('A team invite failed to be created due to one already existing');
124
125
                    $this->requestStack->getSession()->getFlashBag()->add('error', 'parthenon.user.team_invite.already_invited');
126
                    $output['already_invited'] = true;
127
128
                    return $requestHander->generateErrorOutput($formType, $output);
129
                }
130
            }
131
        }
132
133
        $output['form'] = $formType->createView();
134
135
        return $requestHander->generateDefaultOutput($formType, $output);
136
    }
137
}
138