Completed
Pull Request — master (#9)
by Ionuț
02:08
created

Client::getBlob()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 3
1
<?php namespace Crunch\Salesforce;
2
3
use Crunch\Salesforce\Exceptions\RequestException;
4
use GuzzleHttp\Exception\RequestException as GuzzleRequestException;
5
use Crunch\Salesforce\Exceptions\AuthenticationException;
6
use GuzzleHttp\Psr7\Response;
7
8
class Client
9
{
10
    /**
11
     * @var string
12
     */
13
    protected $salesforceLoginUrl;
14
15
    /**
16
     * @var string
17
     */
18
    protected $clientId;
19
20
    /**
21
     * @var string
22
     */
23
    protected $clientSecret;
24
25
    /**
26
     * @var AccessToken
27
     */
28
    private $accessToken;
29
30
    /**
31
     * @var string
32
     */
33
    private $baseUrl;
34
35
    /**
36
     * @var \GuzzleHttp\Client
37
     */
38
    private $guzzleClient;
39
40
41
    /**
42
     * Create a sf client using a client config object or an array of params
43
     *
44
     * @param ClientConfigInterface $clientConfig
45
     * @param \GuzzleHttp\Client    $guzzleClient
46
     * @throws \Exception
47
     */
48
    public function __construct(ClientConfigInterface $clientConfig, \GuzzleHttp\Client $guzzleClient)
49
    {
50
        $this->salesforceLoginUrl = $clientConfig->getLoginUrl();
51
        $this->clientId           = $clientConfig->getClientId();
52
        $this->clientSecret       = $clientConfig->getClientSecret();
53
54
        $this->guzzleClient = $guzzleClient;
55
    }
56
57
    /**
58
     * Create an instance of the salesforce client using the passed in config data
59
     *
60
     * @param $salesforceLoginUrl
61
     * @param $clientId
62
     * @param $clientSecret
63
     * @return Client
64
     */
65
    public static function create($salesforceLoginUrl, $clientId, $clientSecret)
66
    {
67
        return new self(new ClientConfig($salesforceLoginUrl, $clientId, $clientSecret), new \GuzzleHttp\Client);
68
    }
69
70
    /**
71
     * Fetch a specific object
72
     *
73
     * @param string $objectType
74
     * @param string $sfId
75
     * @param array  $fields
76
     * @return string
77
     */
78
    public function getRecord($objectType, $sfId, array $fields)
79
    {
80
        $url      = $this->baseUrl . '/services/data/v20.0/sobjects/' . $objectType . '/' . $sfId . '?fields=' . implode(',', $fields);
81
        $response = $this->makeRequest('get', $url, ['headers' => ['Authorization' => $this->getAuthHeader()]]);
82
83
        return json_decode($response->getBody(), true);
84
    }
85
86
    /**
87
     * Fetch a blob field of a specific object
88
     *
89
     * @param string $objectType
90
     * @param string $sfId
91
     * @param string $blobField
92
     * @return Response
93
     */
94
    public function getBlob($objectType, $sfId, $blobField)
95
    {
96
        $url      = $this->baseUrl . '/services/data/v20.0/sobjects/' . $objectType . '/' . $sfId . '/' . $blobField;
97
        $response = $this->makeRequest('get', $url, ['headers' => ['Authorization' => $this->getAuthHeader()]]);
98
99
        return $response;
100
    }
101
102
    /**
103
     * Execute an SOQL query and return the result set
104
     * This will loop through large result sets collecting all the data so the query should be limited
105
     *
106
     * @param string|null $query
107
     * @param string|null $next_url
108
     * @return array
109
     * @throws \Exception
110
     */
111
    public function search($query = null, $next_url = null)
112
    {
113
        if ( ! empty($next_url)) {
114
            $url = $this->baseUrl . '/' . $next_url;
115
        } else {
116
            $url = $this->baseUrl . '/services/data/v24.0/query/?q=' . urlencode($query);
117
        }
118
        $response = $this->makeRequest('get', $url, ['headers' => ['Authorization' => $this->getAuthHeader()]]);
119
        $data     = json_decode($response->getBody(), true);
120
121
        $results = $data['records'];
122
        if ( ! $data['done']) {
123
            $more_results = $this->search(null, substr($data['nextRecordsUrl'], 1));
124
            if ( ! empty($more_results)) {
125
                $results = array_merge($results, $more_results);
126
            }
127
        }
128
129
        return $results;
130
    }
131
132
    /**
133
     * Make an update request
134
     *
135
     * @param string $object The object type to update
136
     * @param string $id The ID of the record to update
137
     * @param array  $data The data to put into the record
138
     * @return bool
139
     * @throws \Exception
140
     */
141
    public function updateRecord($object, $id, array $data)
142
    {
143
        $url = $this->baseUrl . '/services/data/v20.0/sobjects/' . $object . '/' . $id;
144
145
        $this->makeRequest('patch', $url, [
146
            'headers' => ['Content-Type' => 'application/json', 'Authorization' => $this->getAuthHeader()],
147
            'body'    => json_encode($data)
148
        ]);
149
150
        return true;
151
    }
152
153
    /**
154
     * Create a new object in salesforce
155
     *
156
     * @param string $object
157
     * @param string $data
158
     * @return bool
159
     * @throws \Exception
160
     */
161
    public function createRecord($object, $data)
162
    {
163
        $url = $this->baseUrl . '/services/data/v20.0/sobjects/' . $object . '/';
164
165
        $response     = $this->makeRequest('post', $url, [
166
            'headers' => ['Content-Type' => 'application/json', 'Authorization' => $this->getAuthHeader()],
167
            'body'    => json_encode($data)
168
        ]);
169
        $responseBody = json_decode($response->getBody(), true);
170
171
        return $responseBody['id'];
172
    }
173
174
    /**
175
     * Delete an object with th specified id
176
     *
177
     * @param $object
178
     * @param $id
179
     * @return bool
180
     * @throws \Exception
181
     */
182
    public function deleteRecord($object, $id)
183
    {
184
        $url = $this->baseUrl . '/services/data/v20.0/sobjects/' . $object . '/' . $id;
185
186
        $this->makeRequest('delete', $url, ['headers' => ['Authorization' => $this->getAuthHeader()]]);
187
188
        return true;
189
    }
190
191
    /**
192
     * Complete the oauth process by confirming the code and returning an access token
193
     *
194
     * @param $code
195
     * @param $redirect_url
196
     * @return array|mixed
197
     * @throws \Exception
198
     */
199
    public function authorizeConfirm($code, $redirect_url)
200
    {
201
        $url = $this->salesforceLoginUrl . 'services/oauth2/token';
202
203
        $post_data = [
204
            'grant_type'    => 'authorization_code',
205
            'client_id'     => $this->clientId,
206
            'client_secret' => $this->clientSecret,
207
            'code'          => $code,
208
            'redirect_uri'  => $redirect_url
209
        ];
210
211
        $response = $this->makeRequest('post', $url, ['form_params' => $post_data]);
212
213
        return json_decode($response->getBody(), true);
214
    }
215
216
    /**
217
     * Get the url to redirect users to when setting up a salesforce access token
218
     *
219
     * @param $redirectUrl
220
     * @return string
221
     */
222
    public function getLoginUrl($redirectUrl)
223
    {
224
        $params = [
225
            'client_id'     => $this->clientId,
226
            'redirect_uri'  => $redirectUrl,
227
            'response_type' => 'code',
228
            'grant_type'    => 'authorization_code'
229
        ];
230
231
        return $this->salesforceLoginUrl . 'services/oauth2/authorize?' . http_build_query($params);
232
    }
233
234
    /**
235
     * Refresh an existing access token
236
     *
237
     * @return AccessToken
238
     * @throws \Exception
239
     */
240
    public function refreshToken()
241
    {
242
        $url = $this->salesforceLoginUrl . 'services/oauth2/token';
243
244
        $post_data = [
245
            'grant_type'    => 'refresh_token',
246
            'client_id'     => $this->clientId,
247
            'client_secret' => $this->clientSecret,
248
            'refresh_token' => $this->accessToken->getRefreshToken()
249
        ];
250
251
        $response = $this->makeRequest('post', $url, ['form_params' => $post_data]);
252
253
        $update = json_decode($response->getBody(), true);
254
        $this->accessToken->updateFromSalesforceRefresh($update);
255
256
        return $this->accessToken;
257
    }
258
259
    /**
260
     * @param AccessToken $accessToken
261
     */
262
    public function setAccessToken(AccessToken $accessToken)
263
    {
264
        $this->accessToken = $accessToken;
265
        $this->baseUrl     = $accessToken->getApiUrl();
266
    }
267
268
    /**
269
     * @param string $method
270
     * @param string $url
271
     * @param array  $data
272
     * @return mixed
273
     * @throws AuthenticationException
274
     * @throws RequestException
275
     */
276
    private function makeRequest($method, $url, $data)
277
    {
278
        try {
279
            $response = $this->guzzleClient->$method($url, $data);
280
281
            return $response;
282
        } catch (GuzzleRequestException $e) {
283
            
284
            if ($e->getResponse() === null) {
285
        		throw $e;
286
        	}
287
288
            //If its an auth error convert to an auth exception
289
            if ($e->getResponse()->getStatusCode() == 401) {
290
                $error = json_decode($e->getResponse()->getBody(), true);
291
                throw new AuthenticationException($error[0]['errorCode'], $error[0]['message']);
292
            }
293
            throw new RequestException($e->getMessage(), (string)$e->getResponse()->getBody());
294
        }
295
296
    }
297
298
    /**
299
     * @return string
300
     */
301
    private function getAuthHeader()
302
    {
303
        if ($this->accessToken === null) {
304
    		throw new AuthenticationException(0, "Access token not set");
305
    	}
306
    	
307
        return 'Bearer ' . $this->accessToken->getAccessToken();
308
    }
309
310
}
311