Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
JsonMapper_DateTimeInterface
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
2 / 2
14
100.00% covered (success)
100.00%
1 / 1
 __invoke
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 validate
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
13
1<?php
2/**
3 * JsonMapper deserializer for DateTimeInterface objects.
4 *
5 * @see FactoryRegistry::addFactory()
6 *
7 * @package brianhenryie/bh-wp-bitcoin-gateway
8 */
9
10namespace BrianHenryIE\WP_Bitcoin_Gateway\API\Helpers\JsonMapper;
11
12use BrianHenryIE\WP_Bitcoin_Gateway\API\Model\Exceptions\BH_WP_Bitcoin_Gateway_Exception;
13use DateInvalidTimeZoneException;
14use DateMalformedStringException;
15use DateTimeImmutable;
16use DateTimeInterface;
17use DateTimeZone;
18
19/**
20 * E.g. `{"date":"2026-01-14 05:44:17.084622","timezone_type":3,"timezone":"UTC"}`.
21 *
22 * The `timezone_type` is more of an informational getter than a property, it is not used in constructing the object.
23 */
24class JsonMapper_DateTimeInterface {
25
26    /**
27     * Callable function for parsing DateTimeInterface by JsonMapper factory.
28     *
29     * @param object{date?:string|mixed, timezone:string|mixed, timezone_type:int} $json_object The JSON object to parse to DateTimeInterface.
30     *
31     * @throws BH_WP_Bitcoin_Gateway_Exception If the object fails validation.
32     * @throws DateMalformedStringException If the string provided is invalid.
33     * @throws DateInvalidTimeZoneException If the string provided is invalid.
34     */
35    public function __invoke( object $json_object ): DateTimeInterface {
36
37        $this->validate( $json_object );
38        /** @var object{date:string, timezone:string} $json_object */
39
40        return new DateTimeImmutable(
41            datetime: $json_object->date,
42            timezone: new DateTimeZone(
43                timezone: $json_object->timezone
44            ),
45        );
46    }
47
48    /**
49     * Confirm the JSON object has the expected keys in their expected types.
50     *
51     * @param object{date?:string|mixed, timezone?:string|mixed} $json_object The JSON string (as object) that JsonMapper has been told will parse to DateTimeInterface.
52     *
53     * @throws BH_WP_Bitcoin_Gateway_Exception If the object does not contain the necessary properties:types.
54     */
55    protected function validate( object $json_object ): void {
56        if (
57            property_exists( $json_object, 'date' )
58            && property_exists( $json_object, 'timezone' )
59            && is_string( $json_object->date )
60            && is_string( $json_object->timezone )
61            && ! empty( $json_object->date )
62            && ! empty( $json_object->timezone )
63        ) {
64            return;
65        }
66
67        $previous_exception = null;
68        if ( property_exists( $json_object, 'date' ) && empty( $json_object->date ) ) {
69            $previous_exception = new DateMalformedStringException(
70                message: is_string( $json_object->date ) ? $json_object->date : ''
71            );
72        }
73
74        if ( property_exists( $json_object, 'timezone' ) && empty( $json_object->timezone ) ) {
75            $previous_exception = new DateInvalidTimeZoneException(
76                message: is_string( $json_object->timezone ) ? $json_object->timezone : ''
77            );
78        }
79
80        throw new BH_WP_Bitcoin_Gateway_Exception(
81            message: 'Invalid json encoded DateTime object.',
82            previous: $previous_exception,
83        );
84    }
85}