Completed
Push — master ( 69b363...23eafa )
by
unknown
03:30 queued 49s
created

GraphNode::castToBirthday()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * Copyright 2016 Facebook, Inc.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
namespace Facebook\GraphNodes;
25
26
/**
27
 * Class GraphNode
28
 *
29
 * @package Facebook
30
 */
31
class GraphNode extends Collection
32
{
33
    /**
34
     * @var array Maps object key names to Graph object types.
35
     */
36
    protected static $graphObjectMap = [];
37
38
    /**
39
     * Init this Graph object.
40
     *
41
     * @param array $data
42
     */
43
    public function __construct(array $data = [])
44
    {
45
        parent::__construct($this->castItems($data));
46
    }
47
48
    /**
49
     * Iterates over an array and detects the types each node
50
     * should be cast to and returns all the items as an array.
51
     *
52
     * @TODO Add auto-casting to AccessToken entities.
53
     *
54
     * @param array $data The array to iterate over.
55
     *
56
     * @return array
57
     */
58
    public function castItems(array $data)
59
    {
60
        $items = [];
61
62
        foreach ($data as $k => $v) {
63
            if ($this->shouldCastAsDateTime($k)
64
                && (is_numeric($v)
65
                    || $this->isIso8601DateString($v))
66
            ) {
67
                $items[$k] = $this->castToDateTime($v);
68
            } elseif ($k === 'birthday') {
69
                $items[$k] = $this->castToBirthday($v);
70
            } else {
71
                $items[$k] = $v;
72
            }
73
        }
74
75
        return $items;
76
    }
77
78
    /**
79
     * Uncasts any auto-casted datatypes.
80
     * Basically the reverse of castItems().
81
     *
82
     * @return array
83
     */
84
    public function uncastItems()
85
    {
86
        $items = $this->asArray();
87
88
        return array_map(function ($v) {
89
            if ($v instanceof \DateTime) {
90
                return $v->format(\DateTime::ISO8601);
91
            }
92
93
            return $v;
94
        }, $items);
95
    }
96
97
    /**
98
     * Get the collection of items as JSON.
99
     *
100
     * @param int $options
101
     *
102
     * @return string
103
     */
104
    public function asJson($options = 0)
105
    {
106
        return json_encode($this->uncastItems(), $options);
107
    }
108
109
    /**
110
     * Detects an ISO 8601 formatted string.
111
     *
112
     * @param string $string
113
     *
114
     * @return boolean
115
     *
116
     * @see https://developers.facebook.com/docs/graph-api/using-graph-api/#readmodifiers
117
     * @see http://www.cl.cam.ac.uk/~mgk25/iso-time.html
118
     * @see http://en.wikipedia.org/wiki/ISO_8601
119
     */
120
    public function isIso8601DateString($string)
121
    {
122
        // This insane regex was yoinked from here:
123
        // http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
124
        // ...and I'm all like:
125
        // http://thecodinglove.com/post/95378251969/when-code-works-and-i-dont-know-why
126
        $crazyInsaneRegexThatSomehowDetectsIso8601 = '/^([\+-]?\d{4}(?!\d{2}\b))'
127
            . '((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?'
128
            . '|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d'
129
            . '|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])'
130
            . '((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d'
131
            . '([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/';
132
133
        return preg_match($crazyInsaneRegexThatSomehowDetectsIso8601, $string) === 1;
134
    }
135
136
    /**
137
     * Determines if a value from Graph should be cast to DateTime.
138
     *
139
     * @param string $key
140
     *
141
     * @return boolean
142
     */
143
    public function shouldCastAsDateTime($key)
144
    {
145
        return in_array($key, [
146
            'created_time',
147
            'updated_time',
148
            'start_time',
149
            'end_time',
150
            'backdated_time',
151
            'issued_at',
152
            'expires_at',
153
            'publish_time'
154
        ], true);
155
    }
156
157
    /**
158
     * Casts a date value from Graph to DateTime.
159
     *
160
     * @param int|string $value
161
     *
162
     * @return \DateTime
163
     */
164
    public function castToDateTime($value)
165
    {
166
        if (is_int($value)) {
167
            $dt = new \DateTime();
168
            $dt->setTimestamp($value);
169
        } else {
170
            $dt = new \DateTime($value);
171
        }
172
173
        return $dt;
174
    }
175
176
    /**
177
     * Casts a birthday value from Graph to Birthday
178
     *
179
     * @param string $value
180
     *
181
     * @return Birthday
182
     */
183
    public function castToBirthday($value)
184
    {
185
        return new Birthday($value);
186
    }
187
188
    /**
189
     * Getter for $graphObjectMap.
190
     *
191
     * @return array
192
     */
193
    public static function getObjectMap()
194
    {
195
        return static::$graphObjectMap;
196
    }
197
}
198