GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Pagerduty::getUserDetails()   B
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 29
rs 8.5806
cc 4
eloc 17
nc 4
nop 1
1
<?php
2
/**
3
 * Interface to PagerDuty schedules & user details.
4
 *
5
 * @author  Morgan Pyne <[email protected]>
6
 *
7
 */
8
9
namespace Vend\Phoneduty;
10
use \DateTime;
11
use \DateTimeZone;
12
use \DateInterval;
13
14
15
class Pagerduty {
16
17
    const DEFAULT_TIMEZONE = 'Pacific/Auckland';
18
19
    protected $APItoken;
20
    protected $URL;
21
    protected $httpClient;
22
23
    /**
24
     * Constructor. Expects an API token and PagerDuty domain.
25
     *
26
     * @param string $APItoken
27
     * @param string $domain
28
     *
29
     */
30
    public function __construct($APItoken, $domain) {
31
        $this->APItoken = $APItoken;
32
        $this->URL = "https://{$domain}.pagerduty.com/api/v1";
33
34
        $this->httpClient = new \GuzzleHttp\Client(
35
            array('defaults' =>
36
                array('headers' =>
37
                    array(
38
                        'Content-Type' => 'application/json',
39
                        'Authorization' => "Token token={$APItoken}"
40
                    )
41
                )
42
            )
43
        );
44
    }
45
46
    /**
47
     * Get the ID of current on-call user for a given schedule
48
     *
49
     * @param string $scheduleID
50
     *
51
     * @return string $userID
52
     */
53
    public function getOncallUserForSchedule($scheduleID)
54
    {
55
56
        // PagerDuty requires a datetime range to provide a final schedule
57
        // i.e. one accounting for overrides, which we need to find out who
58
        // is actually on call at a given time.
59
        $UTC = new DateTimeZone("UTC");
60
        $datetime = new DateTime('now', $UTC);
61
        $now = urlencode($datetime->format(DateTime::ISO8601));
62
        $datetime->add(new DateInterval('PT1S'));
63
        $oneSecondLater = urlencode($datetime->format(DateTime::ISO8601));
64
65
        $pagerDutyScheduleURL = "{$this->URL}/schedules/{$scheduleID}?since={$now}&until={$oneSecondLater}";
66
67
        $userID = null;
68
69
        // See http://developer.pagerduty.com/documentation/rest/schedules/show for details
70
        $response = $this->httpClient->get($pagerDutyScheduleURL);
71
72
        if ($response->getStatusCode() == 200) {
73
            $json = json_decode($response->getBody(), true);
74
            $userID = $json['schedule']['final_schedule']['rendered_schedule_entries'][0]['user']['id'];
75
        }
76
77
        return $userID;
78
    }
79
80
81
    /**
82
     *
83
     * Retrieve the details of the on-call user
84
     *
85
     * Details include full name, first name, local time, phone number
86
     *
87
     * @param string $userID
88
     *
89
     * @return array $user
90
     */
91
    public function getUserDetails($userID)
92
    {
93
        // See http://developer.pagerduty.com/documentation/rest/users/show
94
        $pagerDutyUserURL = "{$this->URL}/users/{$userID}";
95
        $queryString = array('query' => array('include[]' => 'contact_methods'));
96
97
        $response = $this->httpClient->get($pagerDutyUserURL, $queryString);
98
99
        $user = null;
100
101
        if ($response->getStatusCode() == 200) {
102
            $json = json_decode($response->getBody(), true);
103
104
            foreach($json['user']['contact_methods'] as $method) {
105
                if($method['type'] == 'phone') {
106
                    $user = array(
107
                        'full_name'   => $json['user']['name'],
108
                        'first_name'  => $this->extractFirstName($json['user']['name']),
109
                        'local_time'    => $this->getCurrentTimeForTimezone(
110
                            $this->convertFriendlyTimezoneToFull($json['user']['time_zone'])),
111
                        'phone_number' => "+{$method['country_code']}{$method['phone_number']}",
112
                    );
113
                    break;
114
                }
115
            }
116
        }
117
118
        return $user;
119
    }
120
121
    /**
122
     * Extract the first name from a full name.
123
     *
124
     * Perform a a naive split on the full name by space, assume
125
     * the first piece is the first name.
126
     *
127
     * @param string $name
128
     *
129
     * @return string
130
     */
131
    protected function extractFirstName($name) {
132
133
        $pieces = explode(' ', $name);
134
        return $pieces[0];
135
    }
136
137
    /**
138
     *
139
     * Get the current time for the specified timezone.
140
     * If the timezone is invalid, default to using
141
     * self::DEFAULT_TIMEZONE
142
     *
143
     * (this is a workaround to PagerDuty currently returning
144
     * some broken timezone data)
145
     *
146
     * @param string $tz
147
     *
148
     * @return DateTime
149
     */
150
    protected function getCurrentTimeForTimezone($tz) {
151
152
        try {
153
            $tzObj = new DateTimeZone($tz);
154
        } catch (\Exception $e) {
155
            // TZ is invalid, try default
156
            $tzObj = new DateTimeZone(self::DEFAULT_TIMEZONE);
157
        }
158
159
        return new DateTime('now', $tzObj);
160
    }
161
162
    /*
163
     * The PagerDuty API does not return fully qualified timezone strings,
164
     * which means PHP won't parse them properly
165
     *
166
     * Details of what it returns are found here:
167
     * https://developer.pagerduty.com/documentation/rest/types
168
     *
169
     * These tz shortnames are apparently derived from the ActiveSupport::Timezone
170
     * class from Rails:
171
     * http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html
172
     *
173
     * @param string $tz
174
     *
175
     * @return string
176
     */
177
    protected function convertFriendlyTimezoneToFull($tz)
178
    {
179
        $timezones = [
180
            "International Date Line West" => "Pacific/Midway",
181
            "Midway Island" => "Pacific/Midway",
182
            "American Samoa" => "Pacific/Pago_Pago",
183
            "Hawaii" => "Pacific/Honolulu",
184
            "Alaska" => "America/Juneau",
185
            "Pacific Time (US & Canada)" => "America/Los_Angeles",
186
            "Tijuana" => "America/Tijuana",
187
            "Mountain Time (US & Canada)" => "America/Denver",
188
            "Arizona" => "America/Phoenix",
189
            "Chihuahua" => "America/Chihuahua",
190
            "Mazatlan" => "America/Mazatlan",
191
            "Central Time (US & Canada)" => "America/Chicago",
192
            "Saskatchewan" => "America/Regina",
193
            "Guadalajara" => "America/Mexico_City",
194
            "Mexico City" => "America/Mexico_City",
195
            "Monterrey" => "America/Monterrey",
196
            "Central America" => "America/Guatemala",
197
            "Eastern Time (US & Canada)" => "America/New_York",
198
            "Indiana (East)" => "America/Indiana/Indianapolis",
199
            "Bogota" => "America/Bogota",
200
            "Lima" => "America/Lima",
201
            "Quito" => "America/Lima",
202
            "Atlantic Time (Canada)" => "America/Halifax",
203
            "Caracas" => "America/Caracas",
204
            "La Paz" => "America/La_Paz",
205
            "Santiago" => "America/Santiago",
206
            "Newfoundland" => "America/St_Johns",
207
            "Brasilia" => "America/Sao_Paulo",
208
            "Buenos Aires" => "America/Argentina/Buenos_Aires",
209
            "Montevideo" => "America/Montevideo",
210
            "Georgetown" => "America/Guyana",
211
            "Greenland" => "America/Godthab",
212
            "Mid-Atlantic" => "Atlantic/South_Georgia",
213
            "Azores" => "Atlantic/Azores",
214
            "Cape Verde Is." => "Atlantic/Cape_Verde",
215
            "Dublin" => "Europe/Dublin",
216
            "Edinburgh" => "Europe/London",
217
            "Lisbon" => "Europe/Lisbon",
218
            "London" => "Europe/London",
219
            "Casablanca" => "Africa/Casablanca",
220
            "Monrovia" => "Africa/Monrovia",
221
            "UTC" => "Etc/UTC",
222
            "Belgrade" => "Europe/Belgrade",
223
            "Bratislava" => "Europe/Bratislava",
224
            "Budapest" => "Europe/Budapest",
225
            "Ljubljana" => "Europe/Ljubljana",
226
            "Prague" => "Europe/Prague",
227
            "Sarajevo" => "Europe/Sarajevo",
228
            "Skopje" => "Europe/Skopje",
229
            "Warsaw" => "Europe/Warsaw",
230
            "Zagreb" => "Europe/Zagreb",
231
            "Brussels" => "Europe/Brussels",
232
            "Copenhagen" => "Europe/Copenhagen",
233
            "Madrid" => "Europe/Madrid",
234
            "Paris" => "Europe/Paris",
235
            "Amsterdam" => "Europe/Amsterdam",
236
            "Berlin" => "Europe/Berlin",
237
            "Bern" => "Europe/Berlin",
238
            "Rome" => "Europe/Rome",
239
            "Stockholm" => "Europe/Stockholm",
240
            "Vienna" => "Europe/Vienna",
241
            "West Central Africa" => "Africa/Algiers",
242
            "Bucharest" => "Europe/Bucharest",
243
            "Cairo" => "Africa/Cairo",
244
            "Helsinki" => "Europe/Helsinki",
245
            "Kyiv" => "Europe/Kiev",
246
            "Riga" => "Europe/Riga",
247
            "Sofia" => "Europe/Sofia",
248
            "Tallinn" => "Europe/Tallinn",
249
            "Vilnius" => "Europe/Vilnius",
250
            "Athens" => "Europe/Athens",
251
            "Istanbul" => "Europe/Istanbul",
252
            "Minsk" => "Europe/Minsk",
253
            "Jerusalem" => "Asia/Jerusalem",
254
            "Harare" => "Africa/Harare",
255
            "Pretoria" => "Africa/Johannesburg",
256
            "Kaliningrad" => "Europe/Kaliningrad",
257
            "Moscow" => "Europe/Moscow",
258
            "St. Petersburg" => "Europe/Moscow",
259
            "Volgograd" => "Europe/Volgograd",
260
            "Samara" => "Europe/Samara",
261
            "Kuwait" => "Asia/Kuwait",
262
            "Riyadh" => "Asia/Riyadh",
263
            "Nairobi" => "Africa/Nairobi",
264
            "Baghdad" => "Asia/Baghdad",
265
            "Tehran" => "Asia/Tehran",
266
            "Abu Dhabi" => "Asia/Muscat",
267
            "Muscat" => "Asia/Muscat",
268
            "Baku" => "Asia/Baku",
269
            "Tbilisi" => "Asia/Tbilisi",
270
            "Yerevan" => "Asia/Yerevan",
271
            "Kabul" => "Asia/Kabul",
272
            "Ekaterinburg" => "Asia/Yekaterinburg",
273
            "Islamabad" => "Asia/Karachi",
274
            "Karachi" => "Asia/Karachi",
275
            "Tashkent" => "Asia/Tashkent",
276
            "Chennai" => "Asia/Kolkata",
277
            "Kolkata" => "Asia/Kolkata",
278
            "Mumbai" => "Asia/Kolkata",
279
            "New Delhi" => "Asia/Kolkata",
280
            "Kathmandu" => "Asia/Kathmandu",
281
            "Astana" => "Asia/Dhaka",
282
            "Dhaka" => "Asia/Dhaka",
283
            "Sri Jayawardenepura" => "Asia/Colombo",
284
            "Almaty" => "Asia/Almaty",
285
            "Novosibirsk" => "Asia/Novosibirsk",
286
            "Rangoon" => "Asia/Rangoon",
287
            "Bangkok" => "Asia/Bangkok",
288
            "Hanoi" => "Asia/Bangkok",
289
            "Jakarta" => "Asia/Jakarta",
290
            "Krasnoyarsk" => "Asia/Krasnoyarsk",
291
            "Beijing" => "Asia/Shanghai",
292
            "Chongqing" => "Asia/Chongqing",
293
            "Hong Kong" => "Asia/Hong_Kong",
294
            "Urumqi" => "Asia/Urumqi",
295
            "Kuala Lumpur" => "Asia/Kuala_Lumpur",
296
            "Singapore" => "Asia/Singapore",
297
            "Taipei" => "Asia/Taipei",
298
            "Perth" => "Australia/Perth",
299
            "Irkutsk" => "Asia/Irkutsk",
300
            "Ulaanbaatar" => "Asia/Ulaanbaatar",
301
            "Seoul" => "Asia/Seoul",
302
            "Osaka" => "Asia/Tokyo",
303
            "Sapporo" => "Asia/Tokyo",
304
            "Tokyo" => "Asia/Tokyo",
305
            "Yakutsk" => "Asia/Yakutsk",
306
            "Darwin" => "Australia/Darwin",
307
            "Adelaide" => "Australia/Adelaide",
308
            "Canberra" => "Australia/Melbourne",
309
            "Melbourne" => "Australia/Melbourne",
310
            "Sydney" => "Australia/Sydney",
311
            "Brisbane" => "Australia/Brisbane",
312
            "Hobart" => "Australia/Hobart",
313
            "Vladivostok" => "Asia/Vladivostok",
314
            "Guam" => "Pacific/Guam",
315
            "Port Moresby" => "Pacific/Port_Moresby",
316
            "Magadan" => "Asia/Magadan",
317
            "Srednekolymsk" => "Asia/Srednekolymsk",
318
            "Solomon Is." => "Pacific/Guadalcanal",
319
            "New Caledonia" => "Pacific/Noumea",
320
            "Fiji" => "Pacific/Fiji",
321
            "Kamchatka" => "Asia/Kamchatka",
322
            "Marshall Is." => "Pacific/Majuro",
323
            "Auckland" => "Pacific/Auckland",
324
            "Wellington" => "Pacific/Auckland",
325
            "Nuku'alofa" => "Pacific/Tongatapu",
326
            "Tokelau Is." => "Pacific/Fakaofo",
327
            "Chatham Is." => "Pacific/Chatham",
328
            "Samoa" => "Pacific/Apia"
329
        ];
330
331
        return (array_key_exists($tz, $timezones) ? $timezones[$tz] : null);
332
    }
333
}
334