Client::search()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 4
nc 6
nop 2
1
<?php namespace DarkGold\Salesforce;
2
3
use DarkGold\Salesforce\Exceptions\RequestException;
4
use GuzzleHttp\Exception\RequestException as GuzzleRequestException;
5
use DarkGold\Salesforce\Exceptions\AuthenticationException;
6
7
class Client
8
{
9
    /**
10
     * @var string
11
     */
12
    protected $salesforceLoginUrl;
13
14
    /**
15
     * @var string
16
     */
17
    protected $clientId;
18
19
    /**
20
     * @var string
21
     */
22
    protected $clientSecret;
23
24
    /**
25
     * @var AccessToken
26
     */
27
    private $accessToken;
28
29
    /**
30
     * @var string
31
     */
32
    private $baseUrl;
33
34
    /**
35
     * @var \GuzzleHttp\Client
36
     */
37
    private $guzzleClient;
38
39
    /**
40
     * The version of the API we are going to be using.
41
     * 
42
     * @var string
43
     */
44
    protected $version = '43.0';
45
46
47
    /**
48
     * Create a sf client using a client config object or an array of params
49
     *
50
     * @param ClientConfigInterface $clientConfig
51
     * @param \GuzzleHttp\Client    $guzzleClient
52
     *
53
     * @throws \Exception
54
     */
55
    public function __construct(ClientConfigInterface $clientConfig, \GuzzleHttp\Client $guzzleClient)
56
    {
57
        $this->salesforceLoginUrl = $clientConfig->getLoginUrl();
58
        $this->clientId           = $clientConfig->getClientId();
59
        $this->clientSecret       = $clientConfig->getClientSecret();
60
61
        $this->guzzleClient = $guzzleClient;
62
    }
63
64
    /**
65
     * Create an instance of the salesforce client using the passed in config data
66
     *
67
     * @param $salesforceLoginUrl
68
     * @param $clientId
69
     * @param $clientSecret
70
     *
71
     * @return Client
72
     *
73
     * @throws \Exception
74
     */
75
    public static function create($salesforceLoginUrl, $clientId, $clientSecret)
76
    {
77
        return new self(new ClientConfig($salesforceLoginUrl, $clientId, $clientSecret), new \GuzzleHttp\Client);
78
    }
79
80
    /**
81
     * Fetch a specific object
82
     *
83
     * @param string $objectType
84
     * @param string $sfId
85
     * @param array $fields
86
     *
87
     * @return string
88
     *
89
     * @throws AuthenticationException
90
     * @throws RequestException
91
     */
92 View Code Duplication
    public function getRecord($objectType, $sfId, array $fields)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
93
    {
94
        $url      = $this->baseUrl . "/services/data/v{$this->version}/sobjects/{$objectType}/{$sfId}?fields=" . implode(',', $fields);
95
        $response = $this->makeRequest('get', $url, ['headers' => ['Authorization' => $this->getAuthHeader()]]);
96
97
        return json_decode($response->getBody(), true);
98
    }
99
100
    /**
101
     * Execute an SOQL query and return the result set
102
     * This will loop through large result sets collecting all the data so the query should be limited
103
     *
104
     * @param string|null $query
105
     * @param string|null $next_url
106
     *
107
     * @return array
108
     *
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/v{$this->version}/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
     * Get the details of an object. Includes the individual metadata at all levels for the object.
134
     *
135
     * @param $objectName
136
     *
137
     * @return array
138
     *
139
     * @throws AuthenticationException
140
     * @throws RequestException
141
     */
142 View Code Duplication
    public function describe($objectName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143
    {
144
        $url = $this->baseUrl . "/services/data/v{$this->version}/sobjects/{$objectName}/describe/";
145
        $response = $this->makeRequest('get', $url, ['headers' => ['Authorization' => $this->getAuthHeader()]]);
146
        $data     = json_decode($response->getBody(), true);
147
148
        return $data;
149
    }
150
151
    /**
152
     * Make an update request
153
     *
154
     * @param string $object The object type to update
155
     * @param string $id The ID of the record to update
156
     * @param array  $data The data to put into the record
157
     *
158
     * @return bool
159
     *
160
     * @throws \Exception
161
     */
162
    public function updateRecord($object, $id, array $data)
163
    {
164
        $url = $this->baseUrl . "/services/data/v{$this->version}/sobjects/{$object}/{$id}";
165
166
        $this->makeRequest('patch', $url, [
167
            'headers' => ['Content-Type' => 'application/json', 'Authorization' => $this->getAuthHeader()],
168
            'body'    => json_encode($data)
169
        ]);
170
171
        return true;
172
    }
173
174
    /**
175
     * Create a new object in salesforce
176
     *
177
     * @param string $object
178
     * @param array $data
179
     * @return bool
180
     * @throws \Exception
181
     */
182
    public function createRecord($object, array $data)
183
    {
184
        $url = $this->baseUrl . "/services/data/v{$this->version}/sobjects/{$object}/";
185
186
        $response = $this->makeRequest('post', $url, [
187
            'headers' => ['Content-Type' => 'application/json', 'Authorization' => $this->getAuthHeader()],
188
            'body'    => json_encode($data)
189
        ]);
190
        $responseBody = json_decode($response->getBody(), true);
191
192
        return $responseBody['id'];
193
    }
194
195
    /**
196
     * Delete an object with th specified id
197
     *
198
     * @param $object
199
     * @param $id
200
     *
201
     * @return bool
202
     *
203
     * @throws \Exception
204
     */
205
    public function deleteRecord($object, $id)
206
    {
207
        $url = $this->baseUrl . "/services/data/v{$this->version}/sobjects/{$object}/{$id}";
208
209
        $this->makeRequest('delete', $url, ['headers' => ['Authorization' => $this->getAuthHeader()]]);
210
211
        return true;
212
    }
213
214
    /**
215
     * Complete the oauth process by confirming the code and returning an access token
216
     *
217
     * @param $code
218
     * @param $redirect_url
219
     *
220
     * @return array|mixed
221
     *
222
     * @throws \Exception
223
     */
224
    public function authorizeConfirm($code, $redirect_url)
225
    {
226
        $url = $this->salesforceLoginUrl . 'services/oauth2/token';
227
228
        $post_data = [
229
            'grant_type'    => 'authorization_code',
230
            'client_id'     => $this->clientId,
231
            'client_secret' => $this->clientSecret,
232
            'code'          => $code,
233
            'redirect_uri'  => $redirect_url
234
        ];
235
236
        $response = $this->makeRequest('post', $url, ['form_params' => $post_data]);
237
238
        return json_decode($response->getBody(), true);
239
    }
240
241
    /**
242
     * Get the url to redirect users to when setting up a salesforce access token
243
     *
244
     * @param $redirectUrl
245
     *
246
     * @return string
247
     */
248
    public function getLoginUrl($redirectUrl)
249
    {
250
        $params = [
251
            'client_id'     => $this->clientId,
252
            'redirect_uri'  => $redirectUrl,
253
            'response_type' => 'code',
254
            'grant_type'    => 'authorization_code'
255
        ];
256
257
        return $this->salesforceLoginUrl . 'services/oauth2/authorize?' . http_build_query($params);
258
    }
259
260
    /**
261
     * Refresh an existing access token
262
     *
263
     * @return AccessToken
264
     *
265
     * @throws \Exception
266
     */
267
    public function refreshToken()
268
    {
269
        $url = $this->salesforceLoginUrl . 'services/oauth2/token';
270
271
        $post_data = [
272
            'grant_type'    => 'refresh_token',
273
            'client_id'     => $this->clientId,
274
            'client_secret' => $this->clientSecret,
275
            'refresh_token' => $this->accessToken->getRefreshToken()
276
        ];
277
278
        $response = $this->makeRequest('post', $url, ['form_params' => $post_data]);
279
280
        $update = json_decode($response->getBody(), true);
281
        $this->accessToken->updateFromSalesforceRefresh($update);
282
283
        return $this->accessToken;
284
    }
285
286
    /**
287
     * @param AccessToken $accessToken
288
     */
289
    public function setAccessToken(AccessToken $accessToken)
290
    {
291
        $this->accessToken = $accessToken;
292
        $this->baseUrl     = $accessToken->getApiUrl();
293
    }
294
295
    /**
296
     * @param string $method
297
     * @param string $url
298
     * @param array  $data
299
     *
300
     * @return mixed
301
     *
302
     * @throws AuthenticationException
303
     * @throws RequestException
304
     */
305
    private function makeRequest($method, $url, $data)
306
    {
307
        try {
308
            $response = $this->guzzleClient->$method($url, $data);
309
310
            return $response;
311
        } catch (GuzzleRequestException $e) {
312
            
313
            if ($e->getResponse() === null) {
314
          throw $e;
315
         }
316
317
            //If its an auth error convert to an auth exception
318
            if ($e->getResponse()->getStatusCode() == 401) {
319
                $error = json_decode($e->getResponse()->getBody(), true);
320
                throw new AuthenticationException($error[0]['errorCode'], $error[0]['message']);
321
            }
322
            throw new RequestException($e->getMessage(), (string)$e->getResponse()->getBody());
323
        }
324
325
    }
326
327
    /**
328
     * @return string
329
     *
330
     * @throws AuthenticationException
331
     */
332
    private function getAuthHeader()
333
    {
334
        if ($this->accessToken === null) {
335
      throw new AuthenticationException(0, "Access token not set");
336
     }
337
    	
338
        return 'Bearer ' . $this->accessToken->getAccessToken();
339
    }
340
341
}
342