Completed
Push — master ( 3d8ad2...d6c4ff )
by Cedric
05:20
created

Qsh::encodeQueryParts()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 1
1
<?php
2
/**
3
 * This file is part of the adlogix/guzzle-atlassian-connect-middleware package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Adlogix\GuzzleAtlassianConnect\Helpers;
10
11
/**
12
 * Class QSH
13
 * QSH is a Query String Hash requested by Atlassian in the JWT token
14
 * @see     https://developer.atlassian.com/static/connect/docs/latest/concepts/understanding-jwt.html#qsh
15
 * @package Adlogix\GuzzleAtlassianConnect\Helpers
16
 * @author  Cedric Michaux <[email protected]>
17
 */
18
class Qsh
19
{
20
    /**
21
     * @param $method
22
     * @param $url
23
     *
24
     * @return string
25
     */
26
    public static function create($method, $url)
27
    {
28
        $method = strtoupper($method);
29
30
31
        $parts = parse_url($url);
32
        $path = self::getCorrectPath($parts['path']);
33
34
        $canonicalQuery = '';
35
        if (array_key_exists('query', $parts)) {
36
            $canonicalQuery = self::getCanonicalQuery($parts['query']);
37
        }
38
39
        $qshString = $method . '&' . $path . '&' . $canonicalQuery;
40
        $qsh = hash('sha256', $qshString);
41
42
        return $qsh;
43
    }
44
45
    /**
46
     *
47
     * @param string $path
48
     *
49
     * @return mixed
50
     */
51
    private static function getCorrectPath($path)
52
    {
53
54
        $path = str_replace(' ', '%20', $path);
55
56
        if ('/' !== $path[0]) {
57
            $path = '/' . $path;
58
        }
59
60
        return $path;
61
    }
62
63
    /**
64
     * @param string $query
65
     *
66
     * @return string
67
     */
68
    private static function getCanonicalQuery($query = '')
69
    {
70
71
        if (empty($query)) {
72
            return $query;
73
        }
74
75
        $queryArray = self::encodeQueryParts($query);
76
77
        ksort($queryArray);
78
79
        $query = self::buildQuery($queryArray);
80
81
        return $query;
82
    }
83
84
    /**
85
     * @param string $query
86
     *
87
     * @return array
88
     */
89
    private static function encodeQueryParts($query)
90
    {
91
        $queryParts = explode('&', $query);
92
        $queryArray = [];
93
94
        foreach ($queryParts as $queryPart) {
95
            $pieces = explode('=', $queryPart, 2);
96
97
            $key = rawurlencode($pieces[0]);
98
            $value = rawurlencode($pieces[1]);
99
100
            $queryArray[$key][] = $value;
101
        }
102
        return $queryArray;
103
    }
104
105
    /**
106
     * @param array $queryArray
107
     *
108
     * @return string
109
     */
110
    private static function buildQuery($queryArray)
111
    {
112
        $query = '';
113
        foreach ($queryArray as $key => $pieceOfQuery) {
114
            $pieceOfQuery = implode(',', $pieceOfQuery);
115
            $query .= $key . '=' . $pieceOfQuery . '&';
116
        }
117
118
        $query = rtrim($query, '&');
119
        return $query;
120
    }
121
}
122