Completed
Push — scalar-types/order ( bd3d7c )
by Kamil
21:55
created

getAuthenticatedUserEmail()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 4
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\CoreBundle\Validator\Constraints;
15
16
use Sylius\Bundle\UserBundle\Doctrine\ORM\UserRepository;
17
use Sylius\Component\Review\Model\ReviewerInterface;
18
use Sylius\Component\User\Model\UserInterface;
19
use Sylius\Component\User\Repository\UserRepositoryInterface;
20
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
21
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
22
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
23
use Symfony\Component\Validator\Constraint;
24
use Symfony\Component\Validator\ConstraintValidator;
25
26
/**
27
 * @author Mateusz Zalewski <[email protected]>
28
 * @author Grzegorz Sadowski <[email protected]>
29
 */
30
class UniqueReviewerEmailValidator extends ConstraintValidator
31
{
32
    /**
33
     * @var UserRepository
34
     */
35
    private $userRepository;
36
37
    /**
38
     * @var TokenStorageInterface
39
     */
40
    private $tokenStorage;
41
42
    /**
43
     * @var AuthorizationCheckerInterface
44
     */
45
    private $authorizationChecker;
46
47
    /**
48
     * @param UserRepositoryInterface $userRepository
49
     * @param TokenStorageInterface $tokenStorage
50
     * @param AuthorizationCheckerInterface $authorizationChecker
51
     */
52
    public function __construct(
53
        UserRepositoryInterface $userRepository,
54
        TokenStorageInterface $tokenStorage,
55
        AuthorizationCheckerInterface $authorizationChecker
56
    ) {
57
        $this->userRepository = $userRepository;
0 ignored issues
show
Documentation Bug introduced by
$userRepository is of type object<Sylius\Component\...serRepositoryInterface>, but the property $userRepository was declared to be of type object<Sylius\Bundle\Use...ine\ORM\UserRepository>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
58
        $this->tokenStorage = $tokenStorage;
59
        $this->authorizationChecker = $authorizationChecker;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    public function validate($review, Constraint $constraint)
66
    {
67
        /* @var ReviewerInterface|null $customer */
68
        $customer = $review->getAuthor();
69
70
        $token = $this->tokenStorage->getToken();
71
        if (null !== $customer) {
72
            if (null === $customer->getEmail()) {
73
                return;
74
            }
75
76
            if ($customer->getEmail() === $this->getAuthenticatedUserEmail($token)) {
0 ignored issues
show
Bug introduced by
It seems like $token defined by $this->tokenStorage->getToken() on line 70 can be null; however, Sylius\Bundle\CoreBundle...uthenticatedUserEmail() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
77
                return;
78
            }
79
        }
80
81
        if (null !== $customer && null !== $this->userRepository->findOneByEmail($customer->getEmail())) {
82
            $this->context->buildViolation($constraint->message)->atPath('author')->addViolation();
83
        }
84
    }
85
86
    /**
87
     * @param TokenInterface $token
88
     *
89
     * @return string|null
90
     */
91
    private function getAuthenticatedUserEmail(TokenInterface $token): ?string
92
    {
93
        if (null === $token) {
94
            return null;
95
        }
96
97
        if (!$this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
98
            return null;
99
        }
100
101
        $user = $token->getUser();
102
        if (!$user instanceof UserInterface) {
103
            return null;
104
        }
105
106
        return $user->getEmail();
107
108
    }
109
}
110