-
Notifications
You must be signed in to change notification settings - Fork 4
/
TribeHRConnector.php
168 lines (144 loc) · 6.7 KB
/
TribeHRConnector.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
<?php
class TribeHRConnector
{
private $version = '0.2';
private $username;
private $api_key;
private $subdomain;
private $protocol = 'https';
/**
* Constructor for a new TribeHRConnector instance
*
* @param string $subdomain: The subdomain where your TribeHR site can be found.
* If your site is normally found at "https://foo.mytribehr.com" this would be "foo"
* @param string $username: The username of an account on your TribeHR site that you wish to use to complete the
* requests you will make through the connector
* @param string $api_key: The API key belonging to the same TribeHR user as the $username value
*/
public function __construct($subdomain, $username, $api_key) {
$this->subdomain = $subdomain;
$this->username = $username;
$this->api_key = $api_key;
}
/**
* Setter for the $protocol value if you wish to override the 'https' default protocol.
* It is strongly recommended to leave this as https
*
* @param string $protocol: The request protocol to use (only the alpha part: do not include '://')
* Only current expected values are 'http' or 'https'
*/
public function setProtocol($protocol) {
$this->protocol = $protocol;
}
/**
* Execute the given request/submission against the given TribeHR endpoint
*
* @param uri $uri: the API endpoint path to submit against (eg /users.xml)
* @param string $method: (optional) The request method to use (GET, POST, PUT). Default = GET
* @param mixed $data: The values to submit against the endpoint for create/edit actions, expected as an array
* These should be formatted as defined in the documentation including nested sub-objects
* For any values that represent a file upload: these *must* be a path to the file on your
* local system, prepended by '@' (this is consistent with cURL standards)
*
* @throws exception: This untyped exception contains a string with the given curl_error value
*
* @return TribeHRConnector: Returns an instance of the connector with the following properties now set:
* response, code, meta, header
*/
function sendRequest($uri, $method = 'GET', $data = '') {
// Initialize the correct formatting for our parameters before using them
$method = strtoupper($method);
$data = $this->buildData($data);
// Set all of the cURL options needed to connect to a TribeHR site
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, sprintf('%s://%s.mytribehr.com%s', $this->protocol, $this->subdomain, $uri));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 2);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERPWD, $this->username . ":" . $this->api_key);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, sprintf("TribeHR PHP Connector/%s", $this->version));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: text/xml; charset=utf-8',));
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
// Specify certificate handling behaviours if we're connecting over https (the default)
if ($this->protocol == 'https') {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
}
// Some of the different methods of submitting against the API will need different cURL options set
switch ($method) {
case 'POST':
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
break;
case 'PUT':
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
break;
case 'GET':
// Treat the same as the default (intentional fall-through)
default:
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
break;
}
// Execute the request, set local variables to all of the response properties
// and return the augmented connector itself.
$this->response = curl_exec($ch);
$this->code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$this->meta = curl_getinfo($ch);
$this->header = curl_getinfo($ch , CURLINFO_CONTENT_TYPE);
$curl_error = ($this->code > 0 ? null : curl_error($ch) . ' (' . curl_errno($ch) . ')');
curl_close($ch);
if ($curl_error) {
throw new Exception('An error occurred while connecting to TribeHR: ' . $curl_error);
}
return $this;
}
/**
* Render the given $data in a way that will be understood by cURL
* Any object that has a multi-dimensional array will need http_build_query called.
* Any object that has a file *must* be passed as a plain, single-dimensional array.
* (notice that the two statements above are mutually exclusive.)
*
* @todo: Build in compatibility for multidimensional, file inclusive $data structures
*
* @param mixed $data: The value of $data as passed to sendRequest
* @return mixed: A CURLOPT_POSTFIELDS-compatible string or array, valid for the request
*/
private function buildData($data) {
// If $data is empty or a string, we can just return it plain
if (empty($data) || is_string($data)) {
return $data;
}
// For now, if there are files present, just submit whatever $data was, raw.
// We can update this in the future, but for now hope it's a flat object.
if ($this->filesSubmitted($data)) {
return $data;
}
// This will generate a cURL-compatible request that maps nicely to a multidimensional array on reception.
// The optional 2nd and 3rd arguments to http_build_query() are needed to fix inconsistencies
// when running PHP in other server environments. (see: WEB-6684)
return http_build_query($data, '', '&');
}
/**
* Determine if a given value for $data is intended to be a file submission
*
* @param mixed $data: A value to be submitted against the API
* @return bool: True if the $data value contains a signal that it is an intended file upload
*/
private function filesSubmitted($data) {
// Are there any files? (first character of the value is an '@': see comments on sendRequest)
if (is_array($data)) {
foreach ($data as $currentProperty) {
if ($this->filesSubmitted($currentProperty)) {
return true;
}
}
// Went through each element of the array and found no files
return false;
}
// We have a single attribute. If it is a file, it should start with '@' (cURL standard)
return (substr($data, 0, 1) == '@');
}
}