Completed
Push — develop ( bc0474...64d4ff )
by Michael
01:52 queued 13s
created

IFTTT::extractDataFromPayload()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2.0023

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 11
cts 12
cp 0.9167
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 12
nc 2
nop 1
crap 2.0023
1
<?php
2
3
namespace dokuwiki\plugin\swarmwebhook\webhooks;
4
5
use DateTime;
6
use dokuwiki\plugin\struct\meta\Schema;
7
use dokuwiki\plugin\swarmwebhook\meta\Response;
8
9
class IFTTT extends AbstractWebhook
10
{
11
    const IFTTT_TIME_FORMAT = 'F d, Y \a\t h:iA';
12
13 1
    public function run($json)
14
    {
15 1
        global $conf, $INPUT;
16
17 1
        if ($conf['allowdebug']) {
18
            dbglog($_SERVER);
19
        }
20
21
        // check that we have helper
22 1
        $webhookData = json_decode($json, true);
23
24 1
        $verificationResult = $this->verifyRequest($webhookData);
25 1
        if ($verificationResult !== true) {
26
            http_status($verificationResult->code, $verificationResult->content);
27
            return;
28
        }
29
30 1
        $ok = $this->handleWebhookPayload($webhookData, $json);
31
32 1
        if ($ok !== true) {
33
            http_status($verificationResult->code, $verificationResult->content);
34
            return;
35
        }
36
37 1
        http_status(202);
38 1
    }
39
40
    /**
41
     * @param array $webhookData
42
     *
43
     * @return true|Response
44
     *
45
     */
46 1
    protected function verifyRequest(array $webhookData)
47
    {
48
        /** @var null|\helper_plugin_swarmwebhook $helper */
49 1
        $helper = plugin_load('helper', 'swarmwebhook');
50 1
        $storedSecret = $helper->getConf('hook secret');
51 1
        if (empty($storedSecret)) {
52 1
            return true;
53
        }
54
55
        if (empty($webhookData['secret'])) {
56
            return new Response(401, 'Header X_HOOK_SECRET missing!');
57
        }
58
59
        if ($webhookData['secret'] !== $storedSecret) {
60
            return new Response(403, 'Header X_HOOK_SECRET not identical with configured secret!');
61
        }
62
63
        return true;
64
    }
65
66
    /**
67
     * @param array $webhookData
68
     * @param string $json
69
     *
70
     * @return true|Response
71
     */
72 1
    protected function handleWebhookPayload(array $webhookData, $json)
73
    {
74 1
        $lookupData = $this->extractDataFromPayload($webhookData);
75 1
        $lookupData['json'] = $json;
76 1
        $lookupData['service'] = 'IFTTT';
77
78
79
        /** @var \helper_plugin_swarmwebhook $helper */
80 1
        $helper = plugin_load('helper', 'swarmwebhook');
81
        try {
82 1
            $schemas = Schema::getAll('lookup');
83 1
            if (!in_array('swarm', $schemas)) {
84 1
                $helper->createNewSwarmSchema();
85
            }
86
87 1
            $helper->deleteCheckinFromLookup($lookupData['checkinid']);
88 1
            $helper->saveDataToLookup($lookupData);
89
        } catch (\Exception $e) { // FIXME: catch more specific exceptions!
90
            $errorMessage = $e->getMessage();
91
            dbglog($errorMessage);
92
            return new Response(500, $errorMessage);
93
        }
94
95 1
        return true;
96
    }
97
98
    /**
99
     * Extract the data to be saved from the payload
100
     *
101
     * @param array $data
102
     *
103
     * @return array
104
     */
105 1
    protected function extractDataFromPayload(array $data)
106
    {
107 1
        $checkinID = $data['ts'];
108 1
        $locationName = $data['VenueName'];
109
110
        // gues time zone
111 1
        $nowTS = time();
112
113 1
        $dateTime = $this->parseTimeIntoTimestamp($data['ts'], $nowTS);
114
115
        $lookupData = [
116 1
            'date' => $dateTime->format('Y-m-d'),
117 1
            'time' => $dateTime->format(\DateTime::ATOM),
118 1
            'checkinid' => $checkinID,
119 1
            'locname' => $locationName,
120
        ];
121 1
        if (!empty($data['shout'])) {
122
            $lookupData['shout'] = $data['shout'];
123
        }
124 1
        return $lookupData;
125
    }
126
127
    /**
128
     * @param $timestring
129
     * @param $nowTS
130
     *
131
     * @return \DateTime
132
     */
133 2
    protected function parseTimeIntoTimestamp($timestring, $nowTS)
134
    {
135
        //May 25, 2018 at 04:32PM
136
137 2
        $guessedTZOffset = $this->guessTZOffset($timestring, $nowTS);
138 2
        $timeZone = new \DateTimeZone($guessedTZOffset);
139 2
        $dateTime = DateTime::createFromFormat(self::IFTTT_TIME_FORMAT, $timestring, $timeZone);
140
141 2
        return $dateTime;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $dateTime could also return false which is incompatible with the documented return type DateTime. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
142
    }
143
144 2
    protected function guessTZOffset($timestring, $nowTS)
145
    {
146 2
        $dateTime = DateTime::createFromFormat(self::IFTTT_TIME_FORMAT, $timestring, new \DateTimeZone('+0000'));
147 2
        if ($dateTime === false) {
148
            dbglog(DateTime::getLastErrors());
149
            $dateTime = new DateTime('now');
150
        }
151 2
        $guessedOffset = round(($dateTime->getTimestamp() - $nowTS)/3600)*100;
152 2
        $sign = $guessedOffset > 0 ? '+' : '';
153
154 2
        return $sign . (string)$guessedOffset;
155
    }
156
}
157