PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 3.1.2
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v3.1.2
V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 2.10.1 2.10.2 All 137 releases
bit-form / includes / Core / Integration / ZohoProjects / ZohoProjectsHandler.php

ZohoProjectsHandler.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 3.1.2, at includes/Core/Integration/ZohoProjects/ZohoProjectsHandler.php

1,239 lines 40.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * ZohoProjects Integration
5 *
6 */
7
8 namespace BitCode\BitForm\Core\Integration\ZohoProjects;
9
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 use BitCode\BitForm\Core\Integration\IntegrationHandler;
15 use BitCode\BitForm\Core\Util\HttpHelper;
16 use BitCode\BitForm\Core\Util\IpTool;
17 use BitCode\BitForm\GlobalHelper;
18 use WP_Error;
19
20 /**
21 * Provide functionality for ZohoCrm integration
22 */
23 class ZohoProjectsHandler
24 {
25 private $_formID;
26 private $_integrationID;
27
28 public function __construct($integrationID, $formID)
29 {
30 $this->_formID = $formID;
31 $this->_integrationID = $integrationID;
32 }
33
34 /**
35 * Helps to register ajax function's with wp
36 *
37 * @return null
38 */
39 public static function registerAjax()
40 {
41 add_action('wp_ajax_bitforms_zprojects_generate_token', [__CLASS__, 'generateTokens']);
42 add_action('wp_ajax_bitforms_zprojects_refresh_portals', [__CLASS__, 'refreshPortalsAjaxHelper']);
43 add_action('wp_ajax_bitforms_zprojects_refresh_projects', [__CLASS__, 'refreshProjectsAjaxHelper']);
44 add_action('wp_ajax_bitforms_zprojects_refresh_milestones', [__CLASS__, 'refreshMilestonesAjaxHelper']);
45 add_action('wp_ajax_bitforms_zprojects_refresh_tasklists', [__CLASS__, 'refreshTasklistsAjaxHelper']);
46 add_action('wp_ajax_bitforms_zprojects_refresh_tasks', [__CLASS__, 'refreshTasksAjaxHelper']);
47 add_action('wp_ajax_bitforms_zprojects_refresh_fields', [__CLASS__, 'refreshFieldsAjaxHelper']);
48 add_action('wp_ajax_bitforms_zprojects_refresh_users', [__CLASS__, 'refreshUsersAjaxHelper']);
49 add_action('wp_ajax_bitforms_zprojects_refresh_task_layouts', [__CLASS__, 'refreshTaskLaysAjaxHelper']);
50 add_action('wp_ajax_bitforms_zprojects_refresh_groups', [__CLASS__, 'refreshGroupsAjaxHelper']);
51 add_action('wp_ajax_bitforms_zprojects_refresh_tags', [__CLASS__, 'refreshTagsAjaxHelper']);
52 }
53
54 /**
55 * Process ajax request for generate_token
56 *
57 * @return string zoho crm api response and status
58 */
59 public static function generateTokens()
60 {
61 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
62 GlobalHelper::requirePostMethod();
63
64 try {
65 $requestsParams = GlobalHelper::formatRequestData();
66 } catch (\InvalidArgumentException $e) {
67 wp_send_json_error($e->getMessage(), 400);
68 }
69
70 if (
71 empty($requestsParams->{'accounts-server'})
72 || empty($requestsParams->dataCenter)
73 || empty($requestsParams->clientId)
74 || empty($requestsParams->clientSecret)
75 || empty($requestsParams->redirectURI)
76 || empty($requestsParams->code)
77 ) {
78 wp_send_json_error(
79 __(
80 'Requested parameter is empty',
81 'bit-form'
82 ),
83 400
84 );
85 }
86
87 $apiEndpoint = \urldecode($requestsParams->{'accounts-server'}) . '/oauth/v2/token';
88 $requestParams = [
89 'grant_type' => 'authorization_code',
90 'client_id' => $requestsParams->clientId,
91 'client_secret' => $requestsParams->clientSecret,
92 'redirect_uri' => \urldecode($requestsParams->redirectURI),
93 'code' => $requestsParams->code
94 ];
95 $apiResponse = HttpHelper::post($apiEndpoint, $requestParams);
96
97 if (is_wp_error($apiResponse) || !empty($apiResponse->error)) {
98 wp_send_json_error(
99 empty($apiResponse->error) ? 'Unknown' : $apiResponse->error,
100 400
101 );
102 }
103 $apiResponse->generates_on = \time();
104 wp_send_json_success($apiResponse, 200);
105 } else {
106 wp_send_json_error(
107 __(
108 'Token expired',
109 'bit-form'
110 ),
111 401
112 );
113 }
114 }
115
116 public static function refreshPortalsAjaxHelper()
117 {
118 $authorizationHeader = null;
119 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
120 GlobalHelper::requirePostMethod();
121
122 try {
123 $queryParams = GlobalHelper::formatRequestData();
124 } catch (\InvalidArgumentException $e) {
125 wp_send_json_error($e->getMessage(), 400);
126 }
127
128 if (
129 empty($queryParams->tokenDetails)
130 || empty($queryParams->dataCenter)
131 || empty($queryParams->clientId)
132 || empty($queryParams->clientSecret)
133 ) {
134 wp_send_json_error(
135 __(
136 'Requested parameter is empty',
137 'bit-form'
138 ),
139 400
140 );
141 }
142 $response = [];
143 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
144 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
145 }
146
147 $portalsMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portals/";
148
149 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
150 $portalsMetaResponse = HttpHelper::get($portalsMetaApiEndpoint, null, $authorizationHeader);
151
152 if (!is_wp_error($portalsMetaResponse)) {
153 $allPortals = [];
154 $portals = $portalsMetaResponse->portals;
155
156 if (count($portals) > 0) {
157 foreach ($portals as $portal) {
158 $allPortals[$portal->name] = (object) [
159 'portalId' => $portal->id,
160 'portalName' => $portal->name
161 ];
162 }
163 }
164 uksort($allPortals, 'strnatcasecmp');
165 $response['portals'] = $allPortals;
166 } else {
167 wp_send_json_error(
168 empty($portalsMetaResponse->data) ? 'Unknown' : $portalsMetaResponse->error,
169 400
170 );
171 }
172 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
173 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
174 }
175 wp_send_json_success($response, 200);
176 } else {
177 wp_send_json_error(
178 __(
179 'Token expired',
180 'bit-form'
181 ),
182 401
183 );
184 }
185 }
186
187 public static function refreshProjectsAjaxHelper()
188 {
189 $authorizationHeader = null;
190 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
191 GlobalHelper::requirePostMethod();
192
193 try {
194 $queryParams = GlobalHelper::formatRequestData();
195 } catch (\InvalidArgumentException $e) {
196 wp_send_json_error($e->getMessage(), 400);
197 }
198
199 if (
200 empty($queryParams->tokenDetails)
201 || empty($queryParams->dataCenter)
202 || empty($queryParams->clientId)
203 || empty($queryParams->clientSecret)
204 || empty($queryParams->portalId)
205 ) {
206 wp_send_json_error(
207 __(
208 'Requested parameter is empty',
209 'bit-form'
210 ),
211 400
212 );
213 }
214 $response = [];
215 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
216 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
217 }
218
219 $projectsMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/projects/?range=1000&status=active";
220
221 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
222 $projectsMetaResponse = HttpHelper::get($projectsMetaApiEndpoint, null, $authorizationHeader);
223
224 // wp_send_json_success($projectsMetaResponse, 200);
225
226 if (!is_wp_error($projectsMetaResponse)) {
227 $allProjects = [];
228 $projects = $projectsMetaResponse->projects;
229
230 if (count($projects) > 0) {
231 foreach ($projects as $project) {
232 $allProjects[$project->name] = (object) [
233 'projectId' => $project->id_string,
234 'projectName' => $project->name
235 ];
236 }
237 }
238 uksort($allProjects, 'strnatcasecmp');
239 $response['projects'] = $allProjects;
240 } else {
241 wp_send_json_error(
242 empty($projectsMetaResponse->data) ? 'Unknown' : $projectsMetaResponse->error,
243 400
244 );
245 }
246 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
247 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
248 }
249 wp_send_json_success($response, 200);
250 } else {
251 wp_send_json_error(
252 __(
253 'Token expired',
254 'bit-form'
255 ),
256 401
257 );
258 }
259 }
260
261 public static function refreshMilestonesAjaxHelper()
262 {
263 $authorizationHeader = null;
264 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
265 GlobalHelper::requirePostMethod();
266
267 try {
268 $queryParams = GlobalHelper::formatRequestData();
269 } catch (\InvalidArgumentException $e) {
270 wp_send_json_error($e->getMessage(), 400);
271 }
272
273 if (
274 empty($queryParams->tokenDetails)
275 || empty($queryParams->dataCenter)
276 || empty($queryParams->clientId)
277 || empty($queryParams->clientSecret)
278 || empty($queryParams->portalId)
279 || empty($queryParams->projectId)
280 ) {
281 wp_send_json_error(
282 __(
283 'Requested parameter is empty',
284 'bit-form'
285 ),
286 400
287 );
288 }
289 $response = [];
290 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
291 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
292 }
293
294 $milestonesMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/projects/{$queryParams->projectId}/milestones/?range=1000";
295
296 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
297 $milestonesMetaResponse = HttpHelper::get($milestonesMetaApiEndpoint, null, $authorizationHeader);
298
299 if (!is_wp_error($milestonesMetaResponse)) {
300 $allMilestones = [];
301 $milestones = $milestonesMetaResponse->milestones;
302
303 if (count($milestones) > 0) {
304 foreach ($milestones as $milestone) {
305 $allMilestones[$milestone->name] = (object) [
306 'milestoneId' => $milestone->id_string,
307 'milestoneName' => $milestone->name
308 ];
309 }
310 }
311 uksort($allMilestones, 'strnatcasecmp');
312 $response['milestones'] = $allMilestones;
313 } else {
314 wp_send_json_error(
315 empty($milestonesMetaResponse->data) ? 'Unknown' : $milestonesMetaResponse->error,
316 400
317 );
318 }
319 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
320 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
321 }
322 wp_send_json_success($response, 200);
323 } else {
324 wp_send_json_error(
325 __(
326 'Token expired',
327 'bit-form'
328 ),
329 401
330 );
331 }
332 }
333
334 public static function refreshTasklistsAjaxHelper()
335 {
336 $authorizationHeader = null;
337 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
338 GlobalHelper::requirePostMethod();
339
340 try {
341 $queryParams = GlobalHelper::formatRequestData();
342 } catch (\InvalidArgumentException $e) {
343 wp_send_json_error($e->getMessage(), 400);
344 }
345
346 if (
347 empty($queryParams->tokenDetails)
348 || empty($queryParams->dataCenter)
349 || empty($queryParams->clientId)
350 || empty($queryParams->clientSecret)
351 || empty($queryParams->portalId)
352 || empty($queryParams->projectId)
353 || empty($queryParams->tasklistFlag)
354 ) {
355 wp_send_json_error(
356 __(
357 'Requested parameter is empty',
358 'bit-form'
359 ),
360 400
361 );
362 }
363 $response = [];
364 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
365 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
366 }
367
368 $tasklistsMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/projects/{$queryParams->projectId}/tasklists/?range=1000&flag={$queryParams->tasklistFlag}";
369
370 if ($queryParams->milestoneId) {
371 $tasklistsMetaApiEndpoint .= "&milestone_id={$queryParams->milestoneId}";
372 }
373
374 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
375 $tasklistsMetaResponse = HttpHelper::get($tasklistsMetaApiEndpoint, null, $authorizationHeader);
376
377 if (!is_wp_error($tasklistsMetaResponse)) {
378 $allTasklists = [];
379 $tasklists = $tasklistsMetaResponse->tasklists;
380
381 if (count($tasklists) > 0) {
382 foreach ($tasklists as $tasklist) {
383 $allTasklists[$tasklist->name] = (object) [
384 'tasklistId' => $tasklist->id_string,
385 'tasklistName' => $tasklist->name
386 ];
387 }
388 }
389 uksort($allTasklists, 'strnatcasecmp');
390 $response['tasklists'] = $allTasklists;
391 } else {
392 wp_send_json_error(
393 empty($tasklistsMetaResponse->data) ? 'Unknown' : $tasklistsMetaResponse->error,
394 400
395 );
396 }
397 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
398 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
399 }
400 wp_send_json_success($response, 200);
401 } else {
402 wp_send_json_error(
403 __(
404 'Token expired',
405 'bit-form'
406 ),
407 401
408 );
409 }
410 }
411
412 public static function refreshTasksAjaxHelper()
413 {
414 $authorizationHeader = null;
415 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
416 GlobalHelper::requirePostMethod();
417
418 try {
419 $queryParams = GlobalHelper::formatRequestData();
420 } catch (\InvalidArgumentException $e) {
421 wp_send_json_error($e->getMessage(), 400);
422 }
423
424 if (
425 empty($queryParams->tokenDetails)
426 || empty($queryParams->dataCenter)
427 || empty($queryParams->clientId)
428 || empty($queryParams->clientSecret)
429 || empty($queryParams->portalId)
430 || empty($queryParams->projectId)
431 ) {
432 wp_send_json_error(
433 __(
434 'Requested parameter is empty',
435 'bit-form'
436 ),
437 400
438 );
439 }
440 $response = [];
441 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
442 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
443 }
444
445 $tasksMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/projects/{$queryParams->projectId}/tasks/?range=1000";
446
447 if ($queryParams->milestoneId) {
448 $tasksMetaApiEndpoint .= "&milestone_id={$queryParams->milestoneId}";
449 }
450 if ($queryParams->tasklistId) {
451 $tasksMetaApiEndpoint .= "&tasklist_id={$queryParams->tasklistId}";
452 }
453
454 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
455 $tasksMetaResponse = HttpHelper::get($tasksMetaApiEndpoint, null, $authorizationHeader);
456
457 if (!is_wp_error($tasksMetaResponse)) {
458 $allTasks = [];
459 $tasks = $tasksMetaResponse->tasks;
460
461 if (count($tasks) > 0) {
462 foreach ($tasks as $task) {
463 $allTasks[$task->name] = (object) [
464 'taskId' => $task->id_string,
465 'taskName' => $task->name
466 ];
467 }
468 }
469 uksort($allTasks, 'strnatcasecmp');
470 $response['tasks'] = $allTasks;
471 } else {
472 wp_send_json_error(
473 empty($tasksMetaResponse->data) ? 'Unknown' : $tasksMetaResponse->error,
474 400
475 );
476 }
477 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
478 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
479 }
480 wp_send_json_success($response, 200);
481 } else {
482 wp_send_json_error(
483 __(
484 'Token expired',
485 'bit-form'
486 ),
487 401
488 );
489 }
490 }
491
492 public static function refreshFieldsAjaxHelper()
493 {
494 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
495 GlobalHelper::requirePostMethod();
496
497 try {
498 $queryParams = GlobalHelper::formatRequestData();
499 } catch (\InvalidArgumentException $e) {
500 wp_send_json_error($e->getMessage(), 400);
501 }
502
503 if (
504 empty($queryParams->tokenDetails)
505 || empty($queryParams->dataCenter)
506 || empty($queryParams->clientId)
507 || empty($queryParams->clientSecret)
508 || empty($queryParams->portalId)
509 || empty($queryParams->event)
510 ) {
511 wp_send_json_error(
512 __(
513 'Requested parameter is empty',
514 'bit-form'
515 ),
516 400
517 );
518 }
519 $response = [];
520 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
521 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
522 }
523
524 if ('project' === $queryParams->event) {
525 $response = ZohoProjectsHandler::getProjectFields($queryParams->dataCenter, $queryParams->portalId, $queryParams->tokenDetails->access_token);
526 } elseif ('milestone' === $queryParams->event) {
527 $response = ZohoProjectsHandler::getMilestoneFields();
528 } elseif ('tasklist' === $queryParams->event) {
529 $response = ZohoProjectsHandler::getTasklistFields();
530 } elseif ('task' === $queryParams->event || 'subtask' === $queryParams->event) {
531 $response = ZohoProjectsHandler::getTaskFields($queryParams->dataCenter, $queryParams->portalId, $queryParams->tokenDetails->access_token, $queryParams->projectId);
532 } elseif ('issue' === $queryParams->event) {
533 $response = ZohoProjectsHandler::getIssueFields($queryParams->dataCenter, $queryParams->portalId, $queryParams->tokenDetails->access_token, $queryParams->projectId);
534 }
535
536 if (!empty($response['tokenDetails']) && $response['tokenDetails'] && !empty($queryParams->id)) {
537 $response['queryModule'] = $queryParams->module;
538 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response);
539 }
540 wp_send_json_success($response, 200);
541 } else {
542 wp_send_json_error(
543 __(
544 'Token expired',
545 'bit-form'
546 ),
547 401
548 );
549 }
550 }
551
552 protected static function getProjectFields($dataCenter, $portalId, $access_token)
553 {
554 $allFields = [
555 'Project Title' => [
556 'apiName' => 'name',
557 'displayLabel' => 'Project Title',
558 'required' => true
559 ],
560 'Project Overview' => [
561 'apiName' => 'description',
562 'displayLabel' => 'Project Overview'
563 ],
564 'Start Date' => [
565 'apiName' => 'start_date',
566 'displayLabel' => 'Start Date'
567 ],
568 'End Date' => [
569 'apiName' => 'end_date',
570 'displayLabel' => 'End Date'
571 ],
572 'Strict Project' => [
573 'apiName' => 'strict_project',
574 'displayLabel' => 'Strict Project'
575 ],
576 'Project Budget' => [
577 'apiName' => 'budget_type',
578 'displayLabel' => 'Project Budget'
579 ],
580 'Budget Amount' => [
581 'apiName' => 'budget_value',
582 'displayLabel' => 'Budget Amount'
583 ],
584 'Billing Method' => [
585 'apiName' => 'billing_method',
586 'displayLabel' => 'Billing Method'
587 ],
588 'Currency' => [
589 'apiName' => 'currency',
590 'displayLabel' => 'Currency'
591 ],
592 'Threshold Limit' => [
593 'apiName' => 'threshold',
594 'displayLabel' => 'Threshold Limit'
595 ],
596 'Rate Per Hour' => [
597 'apiName' => 'project_rate',
598 'displayLabel' => 'Rate Per Hour'
599 ],
600 'Fixed Cost' => [
601 'apiName' => 'fixed_cost',
602 'displayLabel' => 'Fixed Cost'
603 ],
604 'Bill Status' => [
605 'apiName' => 'bill_status',
606 'displayLabel' => 'Bill Status'
607 ]
608 ];
609
610 $response['required'][] = 'name';
611
612 $customFieldsMetaApiEndpoint = "https://projectsapi.zoho.{$dataCenter}/restapi/portal/{$portalId}/projects/customfields/";
613 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$access_token}";
614 $customFieldsMetaResponse = HttpHelper::get($customFieldsMetaApiEndpoint, null, $authorizationHeader);
615
616 if (!is_wp_error($customFieldsMetaResponse)) {
617 $fields = $customFieldsMetaResponse->project_custom_fields;
618
619 if (count($fields) > 0) {
620 foreach ($fields as $field) {
621 $allFields[$field->field_name] = (object) [
622 'apiName' => $field->field_id,
623 'displayLabel' => $field->field_name
624 ];
625
626 if ($field->is_mandatory) {
627 $response['required'][] = $field->field_id;
628 }
629 }
630 }
631 }
632
633 $response['fields'] = $allFields;
634 uksort($response['fields'], 'strnatcasecmp');
635 usort($response['required'], 'strnatcasecmp');
636
637 return $response;
638 }
639
640 protected static function getMilestoneFields()
641 {
642 $allFields = [
643 'Milestone Title' => [
644 'apiName' => 'name',
645 'displayLabel' => 'Milestone Title',
646 'required' => true
647 ],
648 'Start Date' => [
649 'apiName' => 'start_date',
650 'displayLabel' => 'Start Date',
651 'required' => true
652 ],
653 'End Date' => [
654 'apiName' => 'end_date',
655 'displayLabel' => 'End Date',
656 'required' => true
657 ]
658 ];
659
660 $response['required'] = ['name', 'start_date', 'end_date'];
661
662 $response['fields'] = $allFields;
663 uksort($response['fields'], 'strnatcasecmp');
664 usort($response['required'], 'strnatcasecmp');
665
666 return $response;
667 }
668
669 protected static function getTasklistFields()
670 {
671 $allFields = [
672 'Tasklist Title' => [
673 'apiName' => 'name',
674 'displayLabel' => 'Tasklist Title',
675 'required' => true
676 ]
677 ];
678
679 $response['required'] = ['name'];
680
681 $response['fields'] = $allFields;
682 uksort($response['fields'], 'strnatcasecmp');
683 usort($response['required'], 'strnatcasecmp');
684
685 return $response;
686 }
687
688 protected static function getTaskFields($dataCenter, $portalId, $access_token, $projectId)
689 {
690 $allFields = [
691 'Task Title' => [
692 'apiName' => 'name',
693 'displayLabel' => 'Task Title',
694 'required' => true
695 ],
696 'Task Description' => [
697 'apiName' => 'description',
698 'displayLabel' => 'Task Description'
699 ],
700 'Start Date' => [
701 'apiName' => 'start_date',
702 'displayLabel' => 'Start Date'
703 ],
704 'End Date' => [
705 'apiName' => 'end_date',
706 'displayLabel' => 'End Date'
707 ],
708 'Duration' => [
709 'apiName' => 'duration',
710 'displayLabel' => 'Duration'
711 ],
712 'Duration Type' => [
713 'apiName' => 'duration_type',
714 'displayLabel' => 'Duration Type'
715 ],
716 'Start Time' => [
717 'apiName' => 'start_time',
718 'displayLabel' => 'Start Time'
719 ],
720 'End Time' => [
721 'apiName' => 'end_time',
722 'displayLabel' => 'End Time'
723 ],
724 'Rate Per Hour' => [
725 'apiName' => 'rate_per_hour',
726 'displayLabel' => 'Rate Per Hour'
727 ],
728 'Priority' => [
729 'apiName' => 'priority',
730 'displayLabel' => 'Priority'
731 ]
732 ];
733
734 $response['required'][] = 'name';
735
736 // for associate with project
737 $authorizationHeader = null;
738 if ($projectId) {
739 $customFieldsMetaApiEndpoint = "https://projectsapi.zoho.{$dataCenter}/restapi/portal/{$portalId}/projects/{$projectId}/tasklayouts";
740 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$access_token}";
741 $customFieldsMetaResponse = HttpHelper::get($customFieldsMetaApiEndpoint, null, $authorizationHeader);
742
743 if (!is_wp_error($customFieldsMetaResponse)) {
744 $sections = $customFieldsMetaResponse->section_details;
745
746 if (count($sections) > 0) {
747 foreach ($sections as $section) {
748 $fields = $section->customfield_details;
749 foreach ($fields as $field) {
750 if (!$field->is_default) {
751 $allFields[$field->display_name] = (object) [
752 'apiName' => 'cf_' . $field->column_name,
753 'displayLabel' => $field->display_name
754 ];
755 if ($field->is_mandatory) {
756 $response['required'][] = 'cf_' . $field->column_name;
757 }
758 }
759 }
760 }
761 }
762 }
763 }
764
765 $response['fields'] = $allFields;
766 uksort($response['fields'], 'strnatcasecmp');
767 usort($response['required'], 'strnatcasecmp');
768
769 return $response;
770 }
771
772 protected static function getIssueFields($dataCenter, $portalId, $access_token, $projectId)
773 {
774 $allFields = [
775 'Issue Title' => [
776 'apiName' => 'title',
777 'displayLabel' => 'Issue Title',
778 'required' => true
779 ],
780 'Description' => [
781 'apiName' => 'description',
782 'displayLabel' => 'Description'
783 ],
784 'Due Date' => [
785 'apiName' => 'due_date',
786 'displayLabel' => 'Due Date'
787 ],
788 'Rate Per Hour' => [
789 'apiName' => 'rate_per_hour',
790 'displayLabel' => 'Rate Per Hour'
791 ]
792 ];
793
794 $response['required'] = ['title'];
795
796 // for associate with project
797 $authorizationHeader = null;
798 if ($projectId) {
799 // Custom Fields
800 $customFieldsMetaApiEndpoint = "https://projectsapi.zoho.{$dataCenter}/restapi/portal/{$portalId}/projects/{$projectId}/bugs/customfields/";
801 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$access_token}";
802 $customFieldsMetaResponse = HttpHelper::get($customFieldsMetaApiEndpoint, null, $authorizationHeader);
803
804 if (!is_wp_error($customFieldsMetaResponse)) {
805 $fields = $customFieldsMetaResponse->customfields;
806
807 if (count($fields) > 0) {
808 foreach ($fields as $field) {
809 $allFields[$field->label_name] = (object) [
810 'apiName' => $field->column_name,
811 'displayLabel' => $field->label_name
812 ];
813
814 if ('true' === $field->is_mandatory) {
815 $response['required'][] = $field->column_name;
816 }
817 }
818 }
819 }
820
821 // Default Fields
822 $defaultFieldsMetaApiEndpoint = "https://projectsapi.zoho.{$dataCenter}/restapi/portal/{$portalId}/projects/{$projectId}/bugs/defaultfields/";
823 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$access_token}";
824 $defaultFieldsMetaResponse = HttpHelper::get($defaultFieldsMetaApiEndpoint, null, $authorizationHeader);
825
826 if (!is_wp_error($defaultFieldsMetaResponse)) {
827 $response['defaultfields'] = $defaultFieldsMetaResponse->defaultfields;
828 }
829 }
830
831 $response['fields'] = $allFields;
832 uksort($response['fields'], 'strnatcasecmp');
833 usort($response['required'], 'strnatcasecmp');
834
835 return $response;
836 }
837
838 public static function refreshUsersAjaxHelper()
839 {
840 $authorizationHeader = null;
841 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
842 GlobalHelper::requirePostMethod();
843
844 try {
845 $queryParams = GlobalHelper::formatRequestData();
846 } catch (\InvalidArgumentException $e) {
847 wp_send_json_error($e->getMessage(), 400);
848 }
849
850 if (
851 empty($queryParams->tokenDetails)
852 || empty($queryParams->dataCenter)
853 || empty($queryParams->clientId)
854 || empty($queryParams->clientSecret)
855 || empty($queryParams->portalId)
856 ) {
857 wp_send_json_error(
858 __(
859 'Requested parameter is empty',
860 'bit-form'
861 ),
862 400
863 );
864 }
865 $response = [];
866 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
867 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
868 }
869
870 $usersMetaApiEndpoint = '';
871
872 if ($queryParams->projectId) {
873 $usersMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/projects/{$queryParams->projectId}/users/";
874 } else {
875 $usersMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/users/";
876 }
877
878 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
879 $usersMetaResponse = HttpHelper::get($usersMetaApiEndpoint, null, $authorizationHeader);
880
881 // wp_send_json_success($usersMetaResponse, 200);
882
883 if (!is_wp_error($usersMetaResponse)) {
884 $users = $usersMetaResponse->users;
885
886 if (count($users) > 0) {
887 foreach ($users as $user) {
888 $response['users'][] = (object) [
889 'userId' => $user->id,
890 'userName' => $user->name,
891 'userEmail' => $user->email,
892 ];
893 }
894 }
895 } else {
896 wp_send_json_error(
897 empty($usersMetaResponse->data) ? 'Unknown' : $usersMetaResponse->error,
898 400
899 );
900 }
901 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
902 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
903 }
904 wp_send_json_success($response, 200);
905 } else {
906 wp_send_json_error(
907 __(
908 'Token expired',
909 'bit-form'
910 ),
911 401
912 );
913 }
914 }
915
916 public static function refreshTaskLaysAjaxHelper()
917 {
918 $authorizationHeader = null;
919 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
920 GlobalHelper::requirePostMethod();
921
922 try {
923 $queryParams = GlobalHelper::formatRequestData();
924 } catch (\InvalidArgumentException $e) {
925 wp_send_json_error($e->getMessage(), 400);
926 }
927
928 if (
929 empty($queryParams->tokenDetails)
930 || empty($queryParams->dataCenter)
931 || empty($queryParams->clientId)
932 || empty($queryParams->clientSecret)
933 || empty($queryParams->portalId)
934 ) {
935 wp_send_json_error(
936 __(
937 'Requested parameter is empty',
938 'bit-form'
939 ),
940 400
941 );
942 }
943 $response = [];
944 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
945 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
946 }
947
948 $taskLaysMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/tasklayouts";
949
950 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
951 $taskLaysMetaResponse = HttpHelper::get($taskLaysMetaApiEndpoint, null, $authorizationHeader);
952
953 // wp_send_json_success($taskLaysMetaResponse, 200);
954
955 if (!is_wp_error($taskLaysMetaResponse)) {
956 $taskLays = $taskLaysMetaResponse->layouts;
957
958 if (count($taskLays) > 0) {
959 foreach ($taskLays as $taskLay) {
960 $response['taskLays'][] = (object) [
961 'taskLayId' => $taskLay->layout_id,
962 'taskLayName' => $taskLay->layout_name
963 ];
964 }
965 }
966 } else {
967 wp_send_json_error(
968 empty($taskLaysMetaResponse->data) ? 'Unknown' : $taskLaysMetaResponse->error,
969 400
970 );
971 }
972 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
973 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
974 }
975 wp_send_json_success($response, 200);
976 } else {
977 wp_send_json_error(
978 __(
979 'Token expired',
980 'bit-form'
981 ),
982 401
983 );
984 }
985 }
986
987 public static function refreshGroupsAjaxHelper()
988 {
989 $authorizationHeader = null;
990 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
991 GlobalHelper::requirePostMethod();
992
993 try {
994 $queryParams = GlobalHelper::formatRequestData();
995 } catch (\InvalidArgumentException $e) {
996 wp_send_json_error($e->getMessage(), 400);
997 }
998 if (
999 empty($queryParams->tokenDetails)
1000 || empty($queryParams->dataCenter)
1001 || empty($queryParams->clientId)
1002 || empty($queryParams->clientSecret)
1003 || empty($queryParams->portalId)
1004 ) {
1005 wp_send_json_error(
1006 __(
1007 'Requested parameter is empty',
1008 'bit-form'
1009 ),
1010 400
1011 );
1012 }
1013 $response = [];
1014 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
1015 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
1016 }
1017
1018 $groupsMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/restapi/portal/{$queryParams->portalId}/projects/groups";
1019
1020 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
1021 $groupsMetaResponse = HttpHelper::get($groupsMetaApiEndpoint, null, $authorizationHeader);
1022
1023 // wp_send_json_success($groupsMetaResponse, 200);
1024
1025 if (!is_wp_error($groupsMetaResponse)) {
1026 $groups = $groupsMetaResponse->groups;
1027
1028 if (count($groups) > 0) {
1029 foreach ($groups as $group) {
1030 $response['groups'][] = (object) [
1031 'groupId' => $group->id,
1032 'groupName' => $group->name
1033 ];
1034 }
1035 }
1036 } else {
1037 wp_send_json_error(
1038 empty($groupsMetaResponse->data) ? 'Unknown' : $groupsMetaResponse->error,
1039 400
1040 );
1041 }
1042 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
1043 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
1044 }
1045 wp_send_json_success($response, 200);
1046 } else {
1047 wp_send_json_error(
1048 __(
1049 'Token expired',
1050 'bit-form'
1051 ),
1052 401
1053 );
1054 }
1055 }
1056
1057 public static function refreshTagsAjaxHelper()
1058 {
1059 $authorizationHeader = null;
1060 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
1061 GlobalHelper::requirePostMethod();
1062
1063 try {
1064 $queryParams = GlobalHelper::formatRequestData();
1065 } catch (\InvalidArgumentException $e) {
1066 wp_send_json_error($e->getMessage(), 400);
1067 }
1068
1069 if (
1070 empty($queryParams->tokenDetails)
1071 || empty($queryParams->dataCenter)
1072 || empty($queryParams->clientId)
1073 || empty($queryParams->clientSecret)
1074 || empty($queryParams->portalId)
1075 ) {
1076 wp_send_json_error(
1077 __(
1078 'Requested parameter is empty',
1079 'bit-form'
1080 ),
1081 400
1082 );
1083 }
1084
1085 $response = [];
1086 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
1087 $response['tokenDetails'] = ZohoProjectsHandler::_refreshAccessToken($queryParams);
1088 }
1089
1090 $tagsMetaApiEndpoint = "https://projectsapi.zoho.{$queryParams->dataCenter}/api/v3/portal/{$queryParams->portalId}/tags";
1091
1092 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
1093 $tagsMetaResponse = HttpHelper::get($tagsMetaApiEndpoint, null, $authorizationHeader);
1094
1095 // wp_send_json_success($tagsMetaResponse, 200);
1096
1097 if (!is_wp_error($tagsMetaResponse)) {
1098 $tags = $tagsMetaResponse->tags;
1099
1100 if (count($tags) > 0) {
1101 $allTags = [];
1102 foreach ($tags as $tag) {
1103 $allTags[$tag->name] = (object) [
1104 'tagId' => $tag->id,
1105 'tagName' => $tag->name
1106 ];
1107 }
1108 uksort($allTags, 'strnatcasecmp');
1109 $response['tags'] = $allTags;
1110 }
1111 } else {
1112 wp_send_json_error(
1113 empty($tagsMetaResponse->data) ? 'Unknown' : $tagsMetaResponse->error,
1114 400
1115 );
1116 }
1117 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
1118 ZohoProjectsHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['lists']);
1119 }
1120 wp_send_json_success($response, 200);
1121 } else {
1122 wp_send_json_error(
1123 __(
1124 'Token expired',
1125 'bit-form'
1126 ),
1127 401
1128 );
1129 }
1130 }
1131
1132 protected static function _refreshAccessToken($apiData)
1133 {
1134 if (
1135 empty($apiData->dataCenter)
1136 || empty($apiData->clientId)
1137 || empty($apiData->clientSecret)
1138 || empty($apiData->tokenDetails)
1139 ) {
1140 return false;
1141 }
1142 $tokenDetails = $apiData->tokenDetails;
1143
1144 $dataCenter = $apiData->dataCenter;
1145 $apiEndpoint = "https://accounts.zoho.{$dataCenter}/oauth/v2/token";
1146 $requestParams = [
1147 'grant_type' => 'refresh_token',
1148 'client_id' => $apiData->clientId,
1149 'client_secret' => $apiData->clientSecret,
1150 'refresh_token' => $tokenDetails->refresh_token,
1151 ];
1152
1153 $apiResponse = HttpHelper::post($apiEndpoint, $requestParams);
1154 if (is_wp_error($apiResponse) || !empty($apiResponse->error)) {
1155 return false;
1156 }
1157 $tokenDetails->generates_on = \time();
1158 $tokenDetails->access_token = $apiResponse->access_token;
1159 return $tokenDetails;
1160 }
1161
1162 /**
1163 * Save updated access_token to avoid unnecessary token generation
1164 *
1165 * @param integer $formID ID of Integration related form
1166 * @param integer $integrationID ID of Zoho crm Integration
1167 * @param object $tokenDetails refreshed token info
1168 *
1169 * @return null
1170 */
1171 protected static function _saveRefreshedToken($formID, $integrationID, $tokenDetails, $others = null)
1172 {
1173 if (empty($formID) || empty($integrationID)) {
1174 return;
1175 }
1176
1177 $integrationHandler = new IntegrationHandler($formID, IpTool::getUserDetail());
1178 $zprojectsDetails = $integrationHandler->getAIntegration($integrationID);
1179
1180 if (is_wp_error($zprojectsDetails)) {
1181 return;
1182 }
1183 $newDetails = json_decode($zprojectsDetails[0]->integration_details);
1184
1185 $newDetails->tokenDetails = $tokenDetails;
1186 if (!empty($others['portals'])) {
1187 $newDetails->default->portals = $others['portals'];
1188 }
1189
1190 $integrationHandler->updateIntegration($integrationID, $zprojectsDetails[0]->integration_name, 'Zoho Projects', wp_json_encode($newDetails), 'form');
1191 }
1192
1193 public function execute(IntegrationHandler $integrationHandler, $integrationData, $fieldValues, $entryID, $logID)
1194 {
1195 $integrationDetails = is_string($integrationData->integration_details) ? json_decode($integrationData->integration_details) : $integrationData->integration_details;
1196
1197 $tokenDetails = $integrationDetails->tokenDetails;
1198 $portalId = $integrationDetails->portalId;
1199 $dataCenter = $integrationDetails->dataCenter;
1200 $fieldMap = $integrationDetails->field_map;
1201 if (
1202 empty($tokenDetails)
1203 || empty($portalId)
1204 || empty($fieldMap)
1205 ) {
1206 return new WP_Error('REQ_FIELD_EMPTY', __('list are required for zoho projects api', 'bit-form'));
1207 }
1208
1209 $requiredParams = null;
1210 if ((intval($tokenDetails->generates_on) + (55 * 60)) < time()) {
1211 $requiredParams['clientId'] = $integrationDetails->clientId;
1212 $requiredParams['clientSecret'] = $integrationDetails->clientSecret;
1213 $requiredParams['dataCenter'] = $integrationDetails->dataCenter;
1214 $requiredParams['tokenDetails'] = $tokenDetails;
1215 $newTokenDetails = ZohoProjectsHandler::_refreshAccessToken((object)$requiredParams);
1216 if ($newTokenDetails) {
1217 ZohoProjectsHandler::_saveRefreshedToken($this->_formID, $this->_integrationID, $newTokenDetails);
1218 $tokenDetails = $newTokenDetails;
1219 }
1220 }
1221
1222 $recordApiHelper = new RecordApiHelper($tokenDetails, $this->_integrationID, $logID);
1223
1224 $zprojectsApiResponse = $recordApiHelper->executeRecordApi(
1225 $this->_formID,
1226 $entryID,
1227 $integrationDetails,
1228 $dataCenter,
1229 $fieldMap,
1230 $fieldValues
1231 );
1232
1233 if (is_wp_error($zprojectsApiResponse)) {
1234 return $zprojectsApiResponse;
1235 }
1236 return $zprojectsApiResponse;
1237 }
1238 }
1239