Passed
Branch main (b6a268)
by Iain
04:04
created

TeamInvite::__construct()   A

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 Humbly Arrogant Ltd 2020-2022.
7
 *
8
 * Use of this software is governed by the Business Source License included in the LICENSE file and at https://getparthenon.com/docs/next/license.
9
 *
10
 * Change Date: TBD ( 3 years after 2.0.0 release )
11
 *
12
 * On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
13
 */
14
15
namespace Parthenon\User\RequestProcessor;
16
17
use Parthenon\Common\Exception\GeneralException;
18
use Parthenon\Common\Exception\RequestProcessor\AlreadyInvitedException;
19
use Parthenon\Common\LoggerAwareTrait;
20
use Parthenon\Common\RequestHandler\RequestHandlerManagerInterface;
21
use Parthenon\Notification\EmailSenderInterface;
22
use Parthenon\User\Entity\MemberInterface;
23
use Parthenon\User\Entity\TeamInviteCode;
24
use Parthenon\User\Entity\UserInterface;
25
use Parthenon\User\Event\PostTeamInviteEvent;
26
use Parthenon\User\Event\PreTeamInviteEvent;
27
use Parthenon\User\Factory\EntityFactory;
28
use Parthenon\User\Form\Type\UserInviteType;
29
use Parthenon\User\Notification\MessageFactory;
30
use Parthenon\User\Repository\TeamInviteCodeRepositoryInterface;
31
use Parthenon\User\Repository\TeamRepositoryInterface;
32
use Parthenon\User\Repository\UserRepositoryInterface;
33
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
34
use Symfony\Component\Form\FormFactoryInterface;
35
use Symfony\Component\HttpFoundation\Request;
36
use Symfony\Component\HttpFoundation\RequestStack;
37
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
38
use Symfony\Component\Security\Core\Security;
39
40
class TeamInvite
41
{
42
    use LoggerAwareTrait;
43
44
    public function __construct(
45
        private FormFactoryInterface $formFactory,
46
        private Security $security,
47
        private TeamInviteCodeRepositoryInterface $inviteCodeRepository,
48
        private EmailSenderInterface $sender,
49
        private UserInviteType $userInviteType,
50
        private EventDispatcherInterface $dispatcher,
51
        private MessageFactory $messageFactory,
52
        private EntityFactory $entityFactory,
53
        private TeamRepositoryInterface $teamRepository,
54
        private RequestStack $requestStack,
55
        private RequestHandlerManagerInterface $requestHandlerManager,
56
        private AuthorizationCheckerInterface $authorizationChecker,
57
        private UserRepositoryInterface $userRepository,
58
        private string $defaultRole,
59
        private array $roles,
60
    ) {
61
    }
62
63
    public function process(Request $request)
64
    {
65
        $output = ['success' => false, 'already_invited' => false, 'already_a_member' => false, 'hit_limit' => false];
66
67
        $formType = $this->formFactory->create(get_class($this->userInviteType));
68
        $requestHander = $this->requestHandlerManager->getRequestHandler($request);
69
70
        if ($request->isMethod('POST')) {
71
            $requestHander->handleForm($formType, $request);
72
            if ($formType->isSubmitted() && $formType->isValid()) {
73
                $email = $formType->getData()['email'];
74
                $role = $formType->getData()['role'] ?? $this->defaultRole;
75
                $output['processed'] = true;
76
                try {
77
                    $user = $this->security->getUser();
78
                    if (!$user instanceof UserInterface) {
79
                        throw new \InvalidArgumentException('Not a user');
80
                    }
81
82
                    if (!$user instanceof MemberInterface) {
83
                        $this->getLogger()->critical('A user tried to send a team invite when not a member of a team');
84
                        throw new \InvalidArgumentException('Not a member of a team');
85
                    }
86
                    $team = $this->teamRepository->getByMember($user);
87
88
                    if ($this->inviteCodeRepository->hasInviteForEmailAndTeam($email, $team)) {
89
                        throw new AlreadyInvitedException();
90
                    }
91
92
                    if (!in_array($role, $this->roles) && $this->defaultRole !== $role) {
93
                        $this->getLogger()->error('A team invite was not sent due an invalid role being used', ['role' => $role]);
94
                        throw new GeneralException('Invalid role');
95
                    }
96
97
                    $inviteCode = $this->entityFactory->buildTeamInviteCode($user, $team, $email, $role);
98
                    if (!$this->authorizationChecker->isGranted(TeamInviteCode::AUTH_CHECKER_ATTRIBUTE, $inviteCode)) {
99
                        $output['success'] = false;
100
                        $output['hit_limit'] = true;
101
                        $this->getLogger()->info('A team invite was not sent due to plan limits');
102
103
                        return $requestHander->generateErrorOutput($formType, $output);
104
                    }
105
106
                    $this->dispatcher->dispatch(new PreTeamInviteEvent($user, $team, $inviteCode), PreTeamInviteEvent::NAME);
107
                    $this->inviteCodeRepository->save($inviteCode);
108
                    $message = $this->messageFactory->getTeamInviteMessage($user, $team, $inviteCode);
109
110
                    $this->sender->send($message);
111
                    $this->dispatcher->dispatch(new PostTeamInviteEvent($user, $team, $inviteCode), PostTeamInviteEvent::NAME);
112
                    $output['success'] = true;
113
                    $this->requestStack->getSession()->getFlashBag()->add('success', 'parthenon.user.team_invite.success');
0 ignored issues
show
Bug introduced by
The method getFlashBag() does not exist on Symfony\Component\HttpFo...ession\SessionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

113
                    $this->requestStack->getSession()->/** @scrutinizer ignore-call */ getFlashBag()->add('success', 'parthenon.user.team_invite.success');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
114
                    $this->getLogger()->info('A team invite was successfully sent');
115
                } catch (AlreadyInvitedException $e) {
116
                    $this->getLogger()->info('A team invite failed to be created due to one already existing');
117
118
                    $this->requestStack->getSession()->getFlashBag()->add('error', 'parthenon.user.team_invite.already_invited');
119
                    $output['already_invited'] = true;
120
121
                    return $requestHander->generateErrorOutput($formType, $output);
122
                }
123
            }
124
        }
125
126
        $output['form'] = $formType->createView();
127
128
        return $requestHander->generateDefaultOutput($formType, $output);
129
    }
130
}
131