Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
67.76% covered (warning)
67.76%
124 / 183
15.38% covered (danger)
15.38%
2 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
ObjectSerializer
67.76% covered (warning)
67.76%
124 / 183
15.38% covered (danger)
15.38%
2 / 13
540.92
0.00% covered (danger)
0.00%
0 / 1
 setDateTimeFormat
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 sanitizeForSerialization
82.61% covered (warning)
82.61%
19 / 23
0.00% covered (danger)
0.00%
0 / 1
16.18
 sanitizeFilename
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 sanitizeTimestamp
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 toPathValue
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 toQueryValue
61.76% covered (warning)
61.76%
21 / 34
0.00% covered (danger)
0.00%
0 / 1
59.94
 convertBoolToQueryStringFormat
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 toHeaderValue
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 toString
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
 serializeCollection
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
56
 deserialize
69.49% covered (warning)
69.49%
41 / 59
0.00% covered (danger)
0.00%
0 / 1
50.26
 buildQuery
96.88% covered (success)
96.88%
31 / 32
0.00% covered (danger)
0.00%
0 / 1
16
 isEmptyValue
72.73% covered (warning)
72.73%
8 / 11
0.00% covered (danger)
0.00%
0 / 1
10.64
1<?php
2
3/**
4 * ObjectSerializer.
5 *
6 * @category Class
7 *
8 * @author   OpenAPI Generator team
9 *
10 * @see     https://openapi-generator.tech
11 */
12
13/**
14 * Server API.
15 *
16 * Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. The API also supports collection of Automation Intelligence for requests to your server in edge, pre-origin, or middleware contexts.
17 *
18 * The version of the OpenAPI document: 4
19 * Contact: support@fingerprint.com
20 * Generated by: https://openapi-generator.tech
21 * Generator version: 7.23.0
22 */
23
24/**
25 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
26 * https://openapi-generator.tech
27 * Do not edit the class manually.
28 */
29
30namespace Fingerprint\ServerSdk;
31
32use Fingerprint\ServerSdk\Model\ModelInterface;
33
34/**
35 * ObjectSerializer Class Doc Comment.
36 *
37 * @category Class
38 *
39 * @author   OpenAPI Generator team
40 *
41 * @see     https://openapi-generator.tech
42 */
43class ObjectSerializer
44{
45    private static string $dateTimeFormat = \DateTimeInterface::RFC3339_EXTENDED;
46
47    /**
48     * Change the date format.
49     *
50     * @param string $format the new date format to use
51     */
52    public static function setDateTimeFormat(string $format): void
53    {
54        self::$dateTimeFormat = $format;
55    }
56
57    /**
58     * Serialize data.
59     *
60     * @param mixed       $data   the data to serialize
61     * @param string|null $format the format of the OpenAPITools type of the data
62     *
63     * @return scalar|object|array|null serialized form of $data
64     */
65    public static function sanitizeForSerialization(mixed $data, ?string $format = null): mixed
66    {
67        if (is_scalar($data) || null === $data) {
68            return $data;
69        }
70
71        if ($data instanceof \DateTime) {
72            return ('date' === $format) ? $data->format('Y-m-d') : $data->format(self::$dateTimeFormat);
73        }
74
75        if (is_array($data)) {
76            foreach ($data as $property => $value) {
77                $data[$property] = self::sanitizeForSerialization($value);
78            }
79
80            return $data;
81        }
82
83        if (is_object($data)) {
84            $values = [];
85            if ($data instanceof ModelInterface) {
86                $formats = $data::openAPIFormats();
87                foreach ($data::openAPITypes() as $property => $openAPIType) {
88                    $getter = $data::getters()[$property];
89                    $value = $data->{$getter}();
90                    if ($value instanceof \BackedEnum) {
91                        $value = $value->value;
92                    }
93                    if (($data::isNullable($property) && $data->isNullableSetToNull($property)) || null !== $value) {
94                        $values[$data::attributeMap()[$property]] = self::sanitizeForSerialization($value, $formats[$property]);
95                    }
96                }
97            } else {
98                foreach ($data as $property => $value) {
99                    $values[$property] = self::sanitizeForSerialization($value);
100                }
101            }
102
103            return (object) $values;
104        }
105
106        return (string) $data;
107    }
108
109    /**
110     * Sanitize filename by removing path.
111     * e.g. ../../sun.gif becomes sun.gif.
112     *
113     * @param string $filename filename to be sanitized
114     *
115     * @return string the sanitized filename
116     */
117    public static function sanitizeFilename(string $filename): string
118    {
119        if (preg_match('/.*[\/\\\](.*)$/', $filename, $match)) {
120            return $match[1];
121        }
122
123        return $filename;
124    }
125
126    /**
127     * Shorter timestamp microseconds to 6 digits length.
128     *
129     * @param string $timestamp Original timestamp
130     *
131     * @return string the shorten timestamp
132     */
133    public static function sanitizeTimestamp(string $timestamp): string
134    {
135        return preg_replace('/(:\d{2}.\d{6})\d*/', '$1', $timestamp);
136    }
137
138    /**
139     * Take value and turn it into a string suitable for inclusion in
140     * the path, by url-encoding.
141     *
142     * @param string $value a string which will be part of the path
143     *
144     * @return string the serialized object
145     */
146    public static function toPathValue(string $value): string
147    {
148        return rawurlencode(self::toString($value));
149    }
150
151    /**
152     * Take query parameter properties and turn it into an array suitable for
153     * native http_build_query or GuzzleHttp\Psr7\Query::build.
154     *
155     * @param mixed  $value       Parameter value
156     * @param string $paramName   Parameter name
157     * @param string $openApiType OpenAPIType eg. array or object
158     * @param string $style       Parameter serialization style
159     * @param bool   $explode     Parameter explode option
160     * @param bool   $required    Whether query param is required or not
161     *
162     */
163    public static function toQueryValue(
164        mixed $value,
165        string $paramName,
166        string $openApiType = 'string',
167        string $style = 'form',
168        bool $explode = true,
169        bool $required = true
170    ): array {
171        # Check if we should omit this parameter from the query. This should only happen when:
172        #  - Parameter is NOT required; AND
173        #  - its value is set to a value that is equivalent to "empty", depending on its OpenAPI type. For
174        #    example, 0 as "int" or "boolean" is NOT an empty value.
175        if (self::isEmptyValue($value, $openApiType)) {
176            if ($required) {
177                return ["$paramName" => ''];
178            }
179
180            return [];
181        }
182
183        # Handle int and DateTime union in query
184        if ('int|\DateTime' === $openApiType || '\DateTime|int' === $openApiType) {
185            if ($value instanceof \DateTime) {
186                return ["$paramName" => $value->format(self::$dateTimeFormat)];
187            }
188        }
189
190        # Handle DateTime objects in query
191        if ('\DateTime' === $openApiType && $value instanceof \DateTime) {
192            return ["$paramName" => $value->format(self::$dateTimeFormat)];
193        }
194
195        # Handle BackedEnum objects in query
196        if ($value instanceof \BackedEnum) {
197            return ["$paramName" => (string) $value->value];
198        }
199
200        $query = [];
201        $value = (in_array($openApiType, ['object', 'array'], true)) ? (array) $value : $value;
202
203        // since \GuzzleHttp\Psr7\Query::build fails with nested arrays
204        // need to flatten array first
205        $flattenArray = function ($arr, $name, &$result = []) use (&$flattenArray, $style, $explode) {
206            if (!is_array($arr)) {
207                return $arr;
208            }
209
210            foreach ($arr as $k => $v) {
211                $prop = ('deepObject' === $style) ? "{$name}[$k]" : $k;
212
213                if (is_array($v)) {
214                    $flattenArray($v, $prop, $result);
215                } else {
216                    if ('deepObject' !== $style && !$explode) {
217                        // push key itself
218                        $result[] = $prop;
219                    }
220                    $result[$prop] = $v;
221                }
222            }
223
224            return $result;
225        };
226
227        $value = $flattenArray($value, $paramName);
228
229        // https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#style-values
230        if ('array' === $openApiType && 'deepObject' === $style && $explode) {
231            return $value;
232        }
233
234        if ('object' === $openApiType && ('deepObject' === $style || $explode)) {
235            return $value;
236        }
237
238        if ('boolean' === $openApiType && is_bool($value)) {
239            $value = self::convertBoolToQueryStringFormat($value);
240        }
241
242        // handle style in serializeCollection
243        $query[$paramName] = ($explode) ? $value : self::serializeCollection((array) $value, $style);
244
245        return $query;
246    }
247
248    /**
249     * Convert boolean value to format for query string.
250     *
251     * @param bool $value Boolean value
252     *
253     * @return string Boolean value
254     */
255    public static function convertBoolToQueryStringFormat(bool $value): string
256    {
257        return $value ? 'true' : 'false';
258    }
259
260    /**
261     * Take value and turn it into a string suitable for inclusion in
262     * the header. If it's a string, pass through unchanged
263     * If it's a datetime object, format it in ISO8601.
264     *
265     * @param mixed $value an object which will be part of the header
266     *
267     * @return string the header string
268     */
269    public static function toHeaderValue(mixed $value): string
270    {
271        $callable = [$value, 'toHeaderValue'];
272        if (is_callable($callable)) {
273            return $callable();
274        }
275
276        return self::toString($value);
277    }
278
279    /**
280     * Take value and turn it into a string suitable for inclusion in
281     * the parameter. If it's a string, pass through unchanged
282     * If it's a datetime object, format it in ISO8601
283     * If it's a boolean, convert it to "true" or "false".
284     *
285     * @param float|int|bool|\DateTime $value the value of the parameter
286     *
287     * @return string the header string
288     */
289    public static function toString(mixed $value): string
290    {
291        if ($value instanceof \DateTime) { // datetime in ISO8601 format
292            return $value->format(self::$dateTimeFormat);
293        }
294        if (is_bool($value)) {
295            return $value ? 'true' : 'false';
296        }
297
298        return (string) $value;
299    }
300
301    /**
302     * Serialize an array to a string.
303     *
304     * @param array  $collection                 collection to serialize to a string
305     * @param string $style                      the format use for serialization (csv,
306     *                                           ssv, tsv, pipes, multi)
307     * @param bool   $allowCollectionFormatMulti allow collection format to be a multidimensional array
308     *
309     */
310    public static function serializeCollection(array $collection, string $style, bool $allowCollectionFormatMulti = false): string
311    {
312        if ($allowCollectionFormatMulti && ('multi' === $style)) {
313            // http_build_query() almost does the job for us. We just
314            // need to fix the result of multidimensional arrays.
315            return preg_replace('/%5B[0-9]+%5D=/', '=', http_build_query($collection, '', '&'));
316        }
317
318        return match ($style) {
319            'pipeDelimited', 'pipes' => implode('|', $collection),
320            'tsv' => implode("\t", $collection),
321            'spaceDelimited', 'ssv' => implode(' ', $collection),
322            default => implode(',', $collection),
323        };
324    }
325
326    /**
327     * Deserialize a JSON string into an object.
328     *
329     * @param mixed  $data  object or primitive to be deserialized
330     * @param string $class class name is passed as a string
331     *
332     * @return object|array|null a single or an array of $class instances
333     *
334     * @throws \DateMalformedStringException
335     */
336    public static function deserialize(mixed $data, string $class): mixed
337    {
338        if (null === $data) {
339            return null;
340        }
341
342        if (0 === strcasecmp(substr($class, -2), '[]')) {
343            $data = is_string($data) ? json_decode($data) : $data;
344
345            if (!is_array($data)) {
346                throw new \InvalidArgumentException("Invalid array '$class'");
347            }
348
349            $subClass = substr($class, 0, -2);
350            $values = [];
351            foreach ($data as $value) {
352                $values[] = self::deserialize($value, $subClass);
353            }
354
355            return $values;
356        }
357
358        if (preg_match('/^(array<|map\[)/', $class)) { // for associative array e.g. array<string,int>
359            $data = is_string($data) ? json_decode($data) : $data;
360            settype($data, 'array');
361            $inner = substr($class, 4, -1);
362            $deserialized = [];
363            if (false !== strrpos($inner, ',')) {
364                $subClass_array = explode(',', $inner, 2);
365                $subClass = $subClass_array[1];
366                foreach ($data as $key => $value) {
367                    $deserialized[$key] = self::deserialize($value, $subClass);
368                }
369            }
370
371            return $deserialized;
372        }
373
374        if ('object' === $class) {
375            settype($data, 'array');
376
377            return $data;
378        }
379        if ('mixed' === $class) {
380            settype($data, gettype($data));
381
382            return $data;
383        }
384
385        if ('\DateTime' === $class) {
386            // Some APIs return an invalid, empty string as a
387            // date-time property. DateTime::__construct() will return
388            // the current time for empty input which is probably not
389            // what is meant. The invalid empty string is probably to
390            // be interpreted as a missing field/value. Let's handle
391            // this graceful.
392            if (!empty($data)) {
393                try {
394                    return new \DateTime($data);
395                } catch (\Exception) {
396                    // Some APIs return a date-time with too high nanosecond
397                    // precision for php's DateTime to handle.
398                    // With provided regexp 6 digits of microseconds saved
399                    return new \DateTime(self::sanitizeTimestamp($data));
400                }
401            } else {
402                return null;
403            }
404        }
405
406        /* @psalm-suppress ParadoxicalCondition */
407        if (in_array($class, ['\DateTime', '\SplFileObject', 'array', 'bool', 'boolean', 'byte', 'float', 'int', 'integer', 'mixed', 'number', 'object', 'string', 'void'], true)) {
408            settype($data, $class);
409
410            return $data;
411        }
412
413        if (enum_exists($class)) {
414            /* @var \BackedEnum $class */
415            return $class::tryFrom($data) ?? $data;
416        }
417
418        $data = is_string($data) ? json_decode($data) : $data;
419
420        if (is_array($data)) {
421            $data = (object) $data;
422        }
423
424        // If a discriminator is defined and points to a valid subclass, use it.
425        $discriminator = defined("$class::DISCRIMINATOR") ? $class::DISCRIMINATOR : null;
426        if (!empty($discriminator) && isset($data->{$discriminator}) && is_string($data->{$discriminator})) {
427            $subclass = '\Fingerprint\ServerSdk\Model\\'.$data->{$discriminator};
428            if (is_subclass_of($subclass, $class)) {
429                $class = $subclass;
430            }
431        }
432
433        /** @var ModelInterface $instance */
434        $instance = new $class();
435        foreach ($instance::openAPITypes() as $property => $type) {
436            $propertySetter = $instance::setters()[$property];
437
438            if (!isset($propertySetter)) {
439                continue;
440            }
441
442            if (!isset($data->{$instance::attributeMap()[$property]})) {
443                if ($instance::isNullable($property)) {
444                    $instance->{$propertySetter}(null);
445                }
446
447                continue;
448            }
449
450            $propertyValue = $data->{$instance::attributeMap()[$property]};
451            $instance->{$propertySetter}(self::deserialize($propertyValue, $type));
452        }
453
454        return $instance;
455    }
456
457    /**
458     * Build a query string from an array of key value pairs.
459     *
460     * This function can use the return value of `parse()` to build a query
461     * string. This function does not modify the provided keys when an array is
462     * encountered (like `http_build_query()` would).
463     *
464     * The function is copied from https://github.com/guzzle/psr7/blob/a243f80a1ca7fe8ceed4deee17f12c1930efe662/src/Query.php#L59-L112
465     * with a modification which is described in https://github.com/guzzle/psr7/pull/603
466     *
467     * @param array     $params   query string parameters
468     * @param int|false $encoding set false to not encode, PHP_QUERY_RFC3986
469     *                            to encode using RFC3986, or PHP_QUERY_RFC1738
470     *                            to encode using RFC1738
471     */
472    public static function buildQuery(array $params, bool|int $encoding = PHP_QUERY_RFC3986): string
473    {
474        if (!$params) {
475            return '';
476        }
477
478        if (false === $encoding) {
479            $encoder = function (string $str): string {
480                return $str;
481            };
482        } elseif (PHP_QUERY_RFC3986 === $encoding) {
483            $encoder = 'rawurlencode';
484        } elseif (PHP_QUERY_RFC1738 === $encoding) {
485            $encoder = 'urlencode';
486        } else {
487            throw new \InvalidArgumentException('Invalid type');
488        }
489
490        $castBool = function ($v) { return $v ? 'true' : 'false'; };
491
492        $qs = '';
493        foreach ($params as $k => $v) {
494            $k = $encoder((string) $k);
495            if (!is_array($v)) {
496                $qs .= $k;
497                $v = is_bool($v) ? $castBool($v) : $v;
498                if ($v instanceof \BackedEnum) {
499                    $v = $v->value;
500                }
501                if (null !== $v) {
502                    $qs .= '='.$encoder((string) $v);
503                }
504                $qs .= '&';
505            } else {
506                foreach ($v as $vv) {
507                    $qs .= $k;
508                    $vv = is_bool($vv) ? $castBool($vv) : $vv;
509                    if ($vv instanceof \BackedEnum) {
510                        $vv = $vv->value;
511                    }
512                    if (null !== $vv) {
513                        $qs .= '='.$encoder((string) $vv);
514                    }
515                    $qs .= '&';
516                }
517            }
518        }
519
520        return $qs ? substr($qs, 0, -1) : '';
521    }
522
523    /**
524     * Checks if a value is empty, based on its OpenAPI type.
525     *
526     * @return bool true if $value is empty
527     */
528    private static function isEmptyValue(mixed $value, string $openApiType): bool
529    {
530        # If empty() returns false, it is not empty regardless of its type.
531        if (!empty($value)) {
532            return false;
533        }
534
535        # Null is always empty, as we cannot send a real "null" value in a query parameter.
536        if (null === $value) {
537            return true;
538        }
539
540        return match ($openApiType) {
541            # For numeric values, false and '' are considered empty.
542            # This comparison is safe for floating point values, since the previous call to empty() will
543            # filter out values that don't match 0.
544            'int', 'integer', 'int|\DateTime', '\DateTime|int' => 0 !== $value,
545            'number', 'float' => 0 !== $value && 0.0 !== $value,
546            # For boolean values, '' is considered empty
547            'bool', 'boolean' => !in_array($value, [false, 0], true),
548            # For string values, '' is considered empty.
549            'string' => '' === $value,
550            # For all the other types, any value at this point can be considered empty.
551            default => true,
552        };
553    }
554}