Completed
Push — master ( 150711...b978b7 )
by Joschi
03:11
created

JsonUtility   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 66.67%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 94
ccs 18
cts 27
cp 0.6667
rs 10
wmc 16
lcom 0
cbo 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A encode() 0 4 1
B encodeDates() 0 19 7
A decode() 0 4 1
B decodeDates() 0 18 7
1
<?php
2
3
/**
4
 * apparat/resource
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Resource
8
 * @subpackage  Apparat\Resource\Application
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Resource\Application\Service;
38
39
/**
40
 * JsonUtility
41
 *
42
 * @package Apparat\Resource
43
 * @subpackage Apparat\Resource\Application
44
 */
45
class JsonUtility
46
{
47
    /**
48
     * Regular expression for matching ISO 8601 date representations
49
     *
50
     * @var string
51
     */
52
    const iso8601DateRegex = '~^
0 ignored issues
show
Coding Style introduced by
Constant iso8601DateRegex should be defined in uppercase
Loading history...
Coding Style introduced by
This class constant is not uppercase (expected ISO8601DATEREGEX).
Loading history...
53
        (?P<year>[0-9][0-9][0-9][0-9])
54
        -(?P<month>[0-9][0-9]?)
55
        -(?P<day>[0-9][0-9]?)
56
        (?:(?:[Tt]|[ \t]+)
57
        (?P<hour>[0-9][0-9]?)
58
        :(?P<minute>[0-9][0-9])
59
        :(?P<second>[0-9][0-9])
60
        (?:\.(?P<fraction>[0-9]*))?
61
        (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
62
        (?::(?P<tz_minute>[0-9][0-9]))?))?)?
63
        $~x';
64
65
    /**
66
     * JSON encode data
67
     *
68
     * @param mixed $data Data
69
     * @return string JSON string
70
     */
71 2
    public static function encode($data)
72
    {
73 2
        return json_encode(self::encodeDates($data), JSON_PRETTY_PRINT);
74
    }
75
76
    /**
77
     * Recursively encode DateTime objects to ISO 8601 date strings
78
     *
79
     * @param mixed $data Data
80
     * @return mixed Data with encoded ISO 8601 dates
81
     */
82 2
    protected static function encodeDates($data)
83
    {
84
        switch (true) {
85 2
            case $data instanceof \DateTime:
86
            case $data instanceof \DateTimeImmutable:
87 1
                return $data->format('c');
88
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
89
            case $data instanceof \stdClass:
90
                foreach ($data as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $data of type object<stdClass> is not traversable.
Loading history...
91
                    $data->$key = self::encodeDates($value);
92
                }
93
                break;
94 2
            case is_array($data):
95 2
                foreach ($data as $key => $value) {
96 2
                    $data[$key] = self::encodeDates($value);
97
                }
98
        }
99 2
        return $data;
100
    }
101
102
    /**
103
     * JSON decode a string
104
     *
105
     * @param string $str JSON string
106
     * @param bool $assoc Decode objects to associative arrays
107
     * @return mixed Decoded data
108
     */
109 4
    public static function decode($str, $assoc = false)
110
    {
111 4
        return self::decodeDates(json_decode($str, $assoc));
112
    }
113
114
    /**
115
     * Recursively decode ISO 8601 dates to DateTimeImmutable objects
116
     *
117
     * @param mixed $data Data
118
     * @return mixed Data with decoded ISO 8601 dates
119
     */
120 4
    protected static function decodeDates($data)
121
    {
122
        switch (true) {
123 4
            case is_string($data) && preg_match(self::iso8601DateRegex, $data):
124 2
                return new \DateTimeImmutable($data);
125
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
126
            case $data instanceof \stdClass:
127
                foreach ($data as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $data of type object<stdClass> is not traversable.
Loading history...
128
                    $data->$key = self::decodeDates($value);
129
                }
130
                break;
131 4
            case is_array($data):
132 4
                foreach ($data as $key => $value) {
133 4
                    $data[$key] = self::decodeDates($value);
134
                }
135
        }
136 4
        return $data;
137
    }
138
}