Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.25% covered (warning)
81.25%
26 / 32
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
VultrUtil
81.25% covered (warning)
81.25%
26 / 32
57.14% covered (warning)
57.14%
4 / 7
18.91
0.00% covered (danger)
0.00%
0 / 1
 initJSONMapper
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 mapObject
72.73% covered (warning)
72.73%
8 / 11
0.00% covered (danger)
0.00%
0 / 1
4.32
 convertJSONToObject
66.67% covered (warning)
66.67%
4 / 6
0.00% covered (danger)
0.00%
0 / 1
2.15
 decodeJSON
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
6.07
 convertCamelCaseToUnderscore
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 convertUnderscoreToCamelCase
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLevel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Vultr\VultrPhp\Util;
6
7use Exception;
8use JsonMapper\Enums\TextNotation;
9use JsonMapper\JsonMapper;
10use JsonMapper\JsonMapperFactory;
11use JsonMapper\Middleware\CaseConversion;
12use Psr\Http\Message\ResponseInterface;
13use stdClass;
14use Throwable;
15use Vultr\VultrPhp\VultrException;
16
17class VultrUtil
18{
19    public static function initJSONMapper() : JsonMapper
20    {
21        $map = (new JsonMapperFactory())->bestFit();
22        $map->push(new CaseConversion(TextNotation::UNDERSCORE(), TextNotation::CAMEL_CASE()));
23        return $map;
24    }
25    /**
26     * @param $stdClass - Raw class that comes from json_decode. This is what JsonMapper accepts.
27     * @param $model - A model that will be used to map the json response to the object.
28     * Model is passed in via reference, the model will immediately be reset before its mapped and cloned.
29     * @param $prop - The arching prop that has the contents that we will map the object to.
30     * Ex a Backup object will have "backup" : { 'id', etc etc}
31     * So in $prop we would specifiy "backup"
32     * @throws VultrException
33     * @return ModelInterface
34     */
35    public static function mapObject(stdClass $stdclass, ModelInterface $model, ?string $prop = null) : ModelInterface
36    {
37        $object = $stdclass;
38        if ($prop !== null)
39        {
40            $object = $stdclass->$prop;
41        }
42
43        if (!is_object($object))
44        {
45            throw new VultrException('Failed to map object for '.get_class($model).': Object is invalid. Percieved Object Data: '.var_export($object, true).'. Object Parameter: '.var_export($stdclass, true));
46        }
47
48        $model->resetObject();
49        $mapped_object = $model;
50        try
51        {
52            $mapped_object = static::initJSONMapper()->mapObject($object, clone $model);
53        }
54        catch (Throwable $e)
55        {
56            throw new VultrException('Failed to map object for '.get_class($model).': '.$e->getMessage(), VultrException::DEFAULT_CODE, null, $e);
57        }
58
59        return $mapped_object;
60    }
61
62    /**
63     * @param $json - string - Raw JSON
64     * @param $model - A model that will be used to map the json response to the object.
65     * Model is passed in via reference, the model will immediately be reset before its mapped and cloned.
66     * @param $prop - The arching prop that has the contents that we will map the object to.
67     * Ex a Backup object will have "backup" : { 'id', etc etc}
68     * So in $prop we would specifiy "backup"
69     * @throws VultrException
70     * @return ModelInterface
71     */
72    public static function convertJSONToObject(string $json, ModelInterface $model, ?string $prop = null) : ModelInterface
73    {
74        $class_name = get_class($model);
75        $std_class = static::decodeJSON($json);
76
77        try
78        {
79            $object = static::mapObject($std_class, $model, $prop);
80        }
81        catch (Throwable $e)
82        {
83            throw new VultrException('Failed to deserialize '.$class_name.' object: '.$e->getMessage(), VultrException::DEFAULT_CODE, null, $e);
84        }
85
86        return $object;
87    }
88
89    public static function decodeJSON(string $json, bool $array = false) : stdClass|array
90    {
91        try
92        {
93            $decode = json_decode($json, $array, 512, JSON_THROW_ON_ERROR);
94            if ($array && !is_array($decode))
95            {
96                throw Exception('JSON was unable to be parsed into an array.');
97            }
98            else if (!$array && !is_object($decode))
99            {
100                throw new Exception('JSON was unable to be parsed into an object');
101            }
102        }
103        catch (Throwable $e)
104        {
105            throw new VultrException('Failed to decode json: '.$e->getMessage().'. perceived json data: '.var_export($json, true), VultrException::DEFAULT_CODE, null, $e);
106        }
107
108        return $decode;
109    }
110
111    /**
112     * @param $camelCase - string - a camel cased string that will be converted to underscore notation
113     * @param $lowercase - bool - whether the string will be all lowercase or not.
114     * @return string
115     */
116    public static function convertCamelCaseToUnderscore(string $camelCase, bool $lowercase = true) : string
117    {
118        $underscored = (string)preg_replace('/(?<!^)[A-Z]/', '_$0', $camelCase);
119        return $lowercase ? strtolower($underscored) : $underscored;
120    }
121
122    public static function convertUnderscoreToCamelCase(string $key) : string
123    {
124        return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $key))));
125    }
126
127    /**
128     * Get Status Code level
129     * @return int
130     */
131    public static function getLevel(ResponseInterface $response) : int
132    {
133        return (int) floor($response->getStatusCode() / 100);
134    }
135}