Completed
Push — v2.0.x ( 255948...c24837 )
by Florent
03:51
created

Loader   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 24
Bugs 9 Features 4
Metric Value
wmc 45
c 24
b 9
f 4
lcom 1
cbo 5
dl 0
loc 227
rs 8.3673

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A load() 0 11 3
C loadSerializedJsonJWS() 0 27 7
D loadSerializedJsonJWE() 0 34 9
B convert() 0 15 7
B fromFlattenedSerializationRecipientToSerialization() 0 20 5
A fromFlattenedSerializationSignatureToSerialization() 0 19 4
A fromCompactSerializationToSerialization() 0 12 3
A fromCompactSerializationRecipientToSerialization() 0 18 4
A fromCompactSerializationSignatureToSerialization() 0 14 2

How to fix   Complexity   

Complex Class

Complex classes like Loader often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Loader, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace Jose;
13
14
use Base64Url\Base64Url;
15
use Jose\Object\JWE;
16
use Jose\Object\JWS;
17
use Jose\Object\Recipient;
18
use Jose\Object\Signature;
19
20
/**
21
 * Class able to load JWS or JWE.
22
 * JWS object can also be verified.
23
 */
24
final class Loader implements LoaderInterface
25
{
26
    /**
27
     * Loader constructor.
28
     */
29
    private function __construct()
30
    {
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public static function load($input)
37
    {
38
        $json = self::convert($input);
39
        if (array_key_exists('signatures', $json)) {
40
            return self::loadSerializedJsonJWS($json);
41
        }
42
        if (array_key_exists('recipients', $json)) {
43
            return self::loadSerializedJsonJWE($json, $input);
44
        }
45
        throw new \InvalidArgumentException('Unable to load the input');
46
    }
47
48
    /**
49
     * @param array $data
50
     *
51
     * @return \Jose\Object\JWSInterface|\Jose\Object\JWSInterface[]
52
     */
53
    private static function loadSerializedJsonJWS(array $data)
54
    {
55
        $jws = new JWS();
56
        if (array_key_exists('payload', $data)) {
57
            $payload = Base64Url::decode($data['payload']);
58
            $json = json_decode($payload, true);
59
            if (null !== $json && !empty($payload)) {
60
                $payload = $json;
61
            }
62
            $jws = $jws->withPayload($payload);
63
        }
64
65
        foreach ($data['signatures'] as $signature) {
66
            $object = new Signature();
67
            $object = $object->withSignature(Base64Url::decode($signature['signature']));
68
            if (array_key_exists('protected', $signature)) {
69
                $object = $object->withEncodedProtectedHeaders($signature['protected']);
70
            }
71
            if (array_key_exists('header', $signature)) {
72
                $object = $object->withHeaders($signature['header']);
73
            }
74
75
            $jws = $jws->addSignature($object);
76
        }
77
78
        return $jws;
79
    }
80
81
    /**
82
     * @param array  $data
83
     * @param string $input
84
     *
85
     * @return \Jose\Object\JWEInterface|\Jose\Object\JWEInterface[]
86
     */
87
    private static function loadSerializedJsonJWE(array $data, $input)
0 ignored issues
show
Unused Code introduced by
The parameter $input is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
88
    {
89
        $jwe = new JWE();
90
        $jwe = $jwe->withCiphertext(Base64Url::decode($data['ciphertext']));
91
        if (array_key_exists('iv', $data)) {
92
            $jwe = $jwe->withIV(Base64Url::decode($data['iv']));
93
        }
94
        if (array_key_exists('aad', $data)) {
95
            $jwe = $jwe->withAAD(Base64Url::decode($data['aad']));
96
        }
97
        if (array_key_exists('tag', $data)) {
98
            $jwe = $jwe->withTag(Base64Url::decode($data['tag']));
99
        }
100
        if (array_key_exists('protected', $data)) {
101
            $jwe = $jwe->withEncodedSharedProtectedHeaders($data['protected']);
102
            $jwe = $jwe->withSharedProtectedHeaders(json_decode(Base64Url::decode($data['protected']), true));
103
        }
104
        if (array_key_exists('unprotected', $data)) {
105
            $jwe = $jwe->withSharedHeaders($data['unprotected']);
106
        }
107
        foreach ($data['recipients'] as $recipient) {
108
            $object = new Recipient();
109
            if (array_key_exists('header', $recipient)) {
110
                $object = $object->withHeaders($recipient['header']);
111
            }
112
            if (array_key_exists('encrypted_key', $recipient)) {
113
                $object = $object->withEncryptedKey(Base64Url::decode($recipient['encrypted_key']));
114
            }
115
116
            $jwe = $jwe->addRecipient($object);
117
        }
118
119
        return $jwe;
120
    }
121
122
    private static function convert($input)
123
    {
124
        if (is_array($data = json_decode($input, true))) {
125
            if (array_key_exists('signatures', $data) || array_key_exists('recipients', $data)) {
126
                return $data;
127
            } elseif (array_key_exists('signature', $data)) {
128
                return self::fromFlattenedSerializationSignatureToSerialization($data);
129
            } elseif (array_key_exists('ciphertext', $data)) {
130
                return self::fromFlattenedSerializationRecipientToSerialization($data);
131
            }
132
        } elseif (is_string($input)) {
133
            return self::fromCompactSerializationToSerialization($input);
134
        }
135
        throw new \InvalidArgumentException('Unsupported input');
136
    }
137
138
    /**
139
     * @param $input
140
     *
141
     * @return array
142
     */
143
    private static function fromFlattenedSerializationRecipientToSerialization($input)
144
    {
145
        $recipient = [];
146
        foreach (['header', 'encrypted_key'] as $key) {
147
            if (array_key_exists($key, $input)) {
148
                $recipient[$key] = $input[$key];
149
            }
150
        }
151
        $recipients = [
152
            'ciphertext' => $input['ciphertext'],
153
            'recipients' => [$recipient],
154
        ];
155
        foreach (['ciphertext', 'protected', 'unprotected', 'iv', 'aad', 'tag'] as $key) {
156
            if (array_key_exists($key, $input)) {
157
                $recipients[$key] = $input[$key];
158
            }
159
        }
160
161
        return $recipients;
162
    }
163
164
    /**
165
     * @param $input
166
     *
167
     * @return array
168
     */
169
    private static function fromFlattenedSerializationSignatureToSerialization($input)
170
    {
171
        $signature = [
172
            'signature' => $input['signature'],
173
        ];
174
        foreach (['protected', 'header'] as $key) {
175
            if (array_key_exists($key, $input)) {
176
                $signature[$key] = $input[$key];
177
            }
178
        }
179
180
        $temp = [];
181
        if (!empty($input['payload'])) {
182
            $temp['payload'] = $input['payload'];
183
        }
184
        $temp['signatures'] = [$signature];
185
186
        return $temp;
187
    }
188
189
    /**
190
     * @param $input
191
     *
192
     * @return array
193
     */
194
    private static function fromCompactSerializationToSerialization($input)
195
    {
196
        $parts = explode('.', $input);
197
        switch (count($parts)) {
198
            case 3:
199
                return self::fromCompactSerializationSignatureToSerialization($parts);
200
            case 5:
201
                return self::fromCompactSerializationRecipientToSerialization($parts);
202
            default:
203
                throw new \InvalidArgumentException('Unsupported input');
204
        }
205
    }
206
207
    /**
208
     * @param array $parts
209
     *
210
     * @return array
211
     */
212
    private static function fromCompactSerializationRecipientToSerialization(array $parts)
213
    {
214
        $recipient = [];
215
        if (!empty($parts[1])) {
216
            $recipient['encrypted_key'] = $parts[1];
217
        }
218
219
        $recipients = [
220
            'recipients' => [$recipient],
221
        ];
222
        foreach ([3 => 'ciphertext', 0 => 'protected', 2 => 'iv', 4 => 'tag'] as $part => $key) {
223
            if (!empty($parts[$part])) {
224
                $recipients[$key] = $parts[$part];
225
            }
226
        }
227
228
        return $recipients;
229
    }
230
231
    /**
232
     * @param array $parts
233
     *
234
     * @return array
235
     */
236
    private static function fromCompactSerializationSignatureToSerialization(array $parts)
237
    {
238
        $temp = [];
239
240
        if (!empty($parts[1])) {
241
            $temp['payload'] = $parts[1];
242
        }
243
        $temp['signatures'] = [[
244
            'protected' => $parts[0],
245
            'signature' => $parts[2],
246
        ]];
247
248
        return $temp;
249
    }
250
}
251