PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.21.13
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.21.13
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 2.21.13, at includes/Core/Integration/ZohoProjects/ZohoProjectsHandler.php

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