Completed
Pull Request — master (#23)
by
unknown
05:25
created

Api::performRequest()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.0111
c 0
b 0
f 0
cc 6
nc 9
nop 3
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Matt
5
 * Date: 20/04/2016
6
 * Time: 2:32 PM
7
 */
8
9
namespace Freshdesk;
10
11
use Freshdesk\Exceptions\AccessDeniedException;
12
use Freshdesk\Exceptions\ApiException;
13
use Freshdesk\Exceptions\AuthenticationException;
14
use Freshdesk\Exceptions\ConflictingStateException;
15
use Freshdesk\Exceptions\RateLimitExceededException;
16
use Freshdesk\Exceptions\UnsupportedContentTypeException;
17
use Freshdesk\Resources\Agent;
18
use Freshdesk\Resources\BusinessHour;
19
use Freshdesk\Resources\Category;
20
use Freshdesk\Resources\Comment;
21
use Freshdesk\Resources\Company;
22
use Freshdesk\Resources\Contact;
23
use Freshdesk\Resources\Conversation;
24
use Freshdesk\Resources\EmailConfig;
25
use Freshdesk\Resources\Forum;
26
use Freshdesk\Resources\Group;
27
use Freshdesk\Resources\Product;
28
use Freshdesk\Resources\SLAPolicy;
29
use Freshdesk\Resources\Ticket;
30
use Freshdesk\Resources\TimeEntry;
31
use Freshdesk\Resources\Topic;
32
use GuzzleHttp\Client;
33
use GuzzleHttp\Exception\RequestException;
34
35
/**
36
 * Class for interacting with the Freshdesk Api
37
 *
38
 * This is the only class that should be instantiated directly. All API resources are available
39
 * via the relevant public properties
40
 *
41
 * @package Api
42
 * @author Matthew Clarkson <[email protected]>
43
 */
44
class Api
45
{
46
    /**
47
     * Agent resources
48
     *
49
     * @api
50
     * @var Agent
51
     */
52
    public $agents;
53
54
    /**
55
     * Company resources
56
     *
57
     * @api
58
     * @var Company
59
     */
60
    public $companies;
61
62
    /**
63
     * Contact resources
64
     *
65
     * @api
66
     * @var Contact
67
     */
68
    public $contacts;
69
70
    /**
71
     * Group resources
72
     *
73
     * @api
74
     * @var Group
75
     */
76
    public $groups;
77
78
    /**
79
     * Ticket resources
80
     *
81
     * @api
82
     * @var Ticket
83
     */
84
    public $tickets;
85
86
    /**
87
     * TimeEntry resources
88
     *
89
     * @api
90
     * @var TimeEntry
91
     */
92
    public $timeEntries;
93
94
    /**
95
     * Conversation resources
96
     *
97
     * @api
98
     * @var Conversation
99
     */
100
    public $conversations;
101
102
    /**
103
     * Category resources
104
     *
105
     * @api
106
     * @var Category
107
     */
108
    public $categories;
109
110
    /**
111
     * Forum resources
112
     *
113
     * @api
114
     * @var Forum
115
     */
116
    public $forums;
117
118
    /**
119
     * Topic resources
120
     *
121
     * @api
122
     * @var Topic
123
     */
124
    public $topics;
125
126
    /**
127
     * Comment resources
128
     *
129
     * @api
130
     * @var Comment
131
     */
132
    public $comments;
133
134
    //Admin
135
136
    /**
137
     * Email Config resources
138
     *
139
     * @api
140
     * @var EmailConfig
141
     */
142
    public $emailConfigs;
143
144
    /**
145
     * Access Product resources
146
     *
147
     * @api
148
     * @var Product
149
     */
150
    public $products;
151
152
    /**
153
     * Business Hours resources
154
     *
155
     * @api
156
     * @var BusinessHour
157
     */
158
    public $businessHours;
159
160
    /**
161
     * SLA Policy resources
162
     *
163
     * @api
164
     * @var SLAPolicy
165
     */
166
    public $slaPolicies;
167
168
    /**
169
     * @internal
170
     * @var Client
171
     */
172
    protected $client;
173
174
    /**
175
     * @internal
176
     * @var string
177
     */
178
    private $baseUrl;
179
180
    /**
181
     * Constructs a new api instance
182
     *
183
     * @api
184
     * @param string $apiKey
185
     * @param string $domain
186
     * @throws Exceptions\InvalidConfigurationException
187
     */
188
    public function __construct($apiKey, $domain)
189
    {
190
        $this->validateConstructorArgs($apiKey, $domain);
191
192
        $this->baseUrl = sprintf('https://%s.freshdesk.com/api/v2', $domain);
193
194
        $this->client = new Client([
195
                'auth' => [$apiKey, 'X']
196
            ]
197
        );
198
199
        $this->setupResources();
200
    }
201
202
203
    /**
204
     * Internal method for handling requests
205
     *
206
     * @internal
207
     * @param $method
208
     * @param $endpoint
209
     * @param array|null $data
210
     * @param array|null $query
211
     * @return mixed|null
212
     * @throws ApiException
213
     * @throws ConflictingStateException
214
     * @throws RateLimitExceededException
215
     * @throws UnsupportedContentTypeException
216
     */
217
    public function request($method, $endpoint, array $data = null, array $query = null)
218
    {
219
        $key = 'json';
220
        if ($this->hasAttachments($data)) {
221
            $data = $this->formatDataForMultipart($data);
222
            $key = 'multipart';
223
        }
224
        $options = [$key => $data];
225
226
        if (isset($query)) {
227
            $options['query'] = $query;
228
        }
229
230
        $url = $this->baseUrl . $endpoint;
231
232
        return $this->performRequest($method, $url, $options);
233
    }
234
235
    /**
236
     * Checks for attachments in the $data payload
237
     *
238
     * @internal
239
     *
240
     * @param $data
241
     */
242
    private function hasAttachments($data)
243
    {
244
        return (isset($data['attachments']) && count($data['attachments']) > 0);
245
    }
246
247
248
    /**
249
     * Formats the data into a Guzzle Mulitpart request format
250
     *
251
     * @internal
252
     *
253
     * @param $data
254
     */
255
    private function formatDataForMultipart($data)
256
    {
257
        $multipartData = [];
258
259
        foreach ($data as $key => $value) {
260
            if (is_array($value)) {
261
                foreach ($value as $k => $v) {
262
                    $multipartData[] = [
263
                        'name' => sprintf('%s[]', $key),
264
                        'contents' => $v,
265
                        'filename' => sprintf('file%d.jpg', $k),
266
                    ];
267
                }
268
            } else {
269
                $multipartData[] = [
270
                    'name' => $key,
271
                    'contents' => $value,
272
                ];
273
            }
274
        }
275
        return $multipartData;
276
    }
277
278
    /**
279
     * Performs the request
280
     *
281
     * @internal
282
     *
283
     * @param $method
284
     * @param $url
285
     * @param $options
286
     * @return mixed|null
287
     * @throws AccessDeniedException
288
     * @throws ApiException
289
     * @throws AuthenticationException
290
     * @throws ConflictingStateException
291
     */
292
    private function performRequest($method, $url, $options) {
293
294
        try {
295
            switch ($method) {
296
                case 'GET':
297
                    return json_decode($this->client->get($url, $options)->getBody(), true);
298
                case 'POST':
299
                    return json_decode($this->client->post($url, $options)->getBody(), true);
300
                case 'PUT':
301
                    return json_decode($this->client->put($url, $options)->getBody(), true);
302
                case 'DELETE':
303
                    return json_decode($this->client->delete($url, $options)->getBody(), true);
304
                default:
305
                    return null;
306
            }
307
        } catch (RequestException $e) {
308
            throw ApiException::create($e);
309
        }
310
    }
311
312
313
    /**
314
     * @param $apiKey
315
     * @param $domain
316
     * @throws Exceptions\InvalidConfigurationException
317
     * @internal
318
     *
319
     */
320
    private function validateConstructorArgs($apiKey, $domain)
321
    {
322
        if (!isset($apiKey)) {
323
            throw new Exceptions\InvalidConfigurationException("API key is empty.");
324
        }
325
326
        if (!isset($domain)) {
327
            throw new Exceptions\InvalidConfigurationException("Domain is empty.");
328
        }
329
    }
330
331
    /**
332
     * @internal
333
     */
334
    private function setupResources()
335
    {
336
        //People
337
        $this->agents = new Agent($this);
338
        $this->companies = new Company($this);
339
        $this->contacts = new Contact($this);
340
        $this->groups = new Group($this);
341
342
        //Tickets
343
        $this->tickets = new Ticket($this);
344
        $this->timeEntries = new TimeEntry($this);
345
        $this->conversations = new Conversation($this);
346
347
        //Discussions
348
        $this->categories = new Category($this);
349
        $this->forums = new Forum($this);
350
        $this->topics = new Topic($this);
351
        $this->comments = new Comment($this);
352
353
        //Admin
354
        $this->products = new Product($this);
355
        $this->emailConfigs = new EmailConfig($this);
356
        $this->slaPolicies = new SLAPolicy($this);
357
        $this->businessHours = new BusinessHour($this);
358
    }
359
}
360