Completed
Push — master ( 044641...e61035 )
by
unknown
05:15
created

SignatureParameterHandler   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 85.19%

Importance

Changes 0
Metric Value
wmc 9
lcom 1
cbo 2
dl 0
loc 97
ccs 23
cts 27
cp 0.8519
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getRouteParameters() 0 7 1
A getPayload() 0 16 3
A isValid() 0 4 1
A calculateSignature() 0 4 1
A normalize() 0 9 2
1
<?php
2
3
namespace MediaMonks\SonataMediaBundle\Handler;
4
5
use MediaMonks\SonataMediaBundle\Exception\SignatureInvalidException;
6
use MediaMonks\SonataMediaBundle\Model\MediaInterface;
7
use Symfony\Component\HttpFoundation\Request;
8
9
class SignatureParameterHandler implements ParameterHandlerInterface
10
{
11
    const PARAMETER_SIGNATURE = 's';
12
    const PARAMETER_BUST_CACHE = 'bc';
13
14
    /**
15
     * @var string
16
     */
17
    private $key;
18
19
    /**
20
     * @var string
21
     */
22
    private $hashAlgorithm;
23
24
    /**
25
     * @param $key
26
     * @param string $hashAlgorithm
27
     */
28 3
    public function __construct($key, $hashAlgorithm = 'sha256')
29
    {
30 3
        $this->key = $key;
31 3
        $this->hashAlgorithm = $hashAlgorithm;
32 3
    }
33
34
    /**
35
     * @param MediaInterface $media
36
     * @param ParameterBag $parameterBag
37
     * @return array
38
     */
39 1
    public function getRouteParameters(MediaInterface $media, ParameterBag $parameterBag)
40
    {
41 1
        $parameters = $parameterBag->toArray($media);
42 1
        $parameters[self::PARAMETER_SIGNATURE] = $this->calculateSignature($parameters);
43
44 1
        return $parameters;
45
    }
46
47
    /**
48
     * @param MediaInterface $media
49
     * @param $width
50
     * @param $height
51
     * @param array $extra
52
     * @return ParameterBag
53
     * @throws SignatureInvalidException
54
     */
55 2
    public function getPayload(MediaInterface $media, $width, $height, array $extra = [])
56
    {
57 2
        if (!isset($extra[self::PARAMETER_SIGNATURE])) {
58
            throw new SignatureInvalidException();
59
        }
60
61 2
        $signature = $extra[self::PARAMETER_SIGNATURE];
62 2
        unset($extra[self::PARAMETER_SIGNATURE]);
63
64 2
        $parameters = new ParameterBag($width, $height, $extra);
65 2
        if (!$this->isValid($media, $parameters, $signature)) {
66
            throw new SignatureInvalidException();
67
        }
68
69 2
        return $parameters;
70
    }
71
72
    /**
73
     * @param MediaInterface $media
74
     * @param ParameterBag $parameters
75
     * @param $expectedSignature
76
     * @return bool
77
     */
78 2
    private function isValid(MediaInterface $media, ParameterBag $parameters, $expectedSignature)
79
    {
80 2
        return hash_equals($this->calculateSignature($parameters->toArray($media)), $expectedSignature);
81
    }
82
83
    /**
84
     * @param array $parameters
85
     * @return string
86
     */
87 3
    private function calculateSignature(array $parameters)
88
    {
89 3
        return hash_hmac($this->hashAlgorithm, $this->key, json_encode($this->normalize($parameters)));
90
    }
91
92
    /**
93
     * @param array $parameters
94
     * @return array
95
     */
96 3
    private function normalize(array $parameters)
97
    {
98 3
        if (isset($parameters[self::PARAMETER_BUST_CACHE])) {
99
            unset($parameters[self::PARAMETER_BUST_CACHE]);
100
        }
101 3
        ksort($parameters);
102
103 3
        return array_map('strval', $parameters);
104
    }
105
}
106