PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 3.3.1
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v3.3.1
3.3.1 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 All 138 releases
bit-form / includes / Core / Integration / ZohoCRM / ZohoCRMHandler.php

ZohoCRMHandler.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder 3.3.1, at includes/Core/Integration/ZohoCRM/ZohoCRMHandler.php

829 lines 30.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * ZohoCrm Integration
5 *
6 */
7
8 namespace BitCode\BitForm\Core\Integration\ZohoCRM;
9
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 use BitCode\BitForm\Core\Integration\IntegrationHandler;
15 use BitCode\BitForm\Core\Util\ApiResponse as UtilApiResponse;
16 use BitCode\BitForm\Core\Util\HttpHelper;
17 use BitCode\BitForm\Core\Util\IpTool;
18 use BitCode\BitForm\GlobalHelper;
19 use WP_Error;
20
21 /**
22 * Provide functionality for ZohoCrm integration
23 */
24 class ZohoCRMHandler
25 {
26 private $_formID;
27 private $_integrationID;
28
29 private $_logResponse;
30
31 public function __construct($integrationID, $fromID)
32 {
33 $this->_formID = $fromID;
34 $this->_integrationID = $integrationID;
35 $this->_logResponse = new UtilApiResponse();
36 }
37
38 /**
39 * Helps to register ajax function's with wp
40 *
41 * @return null
42 */
43 public static function registerAjax()
44 {
45 add_action('wp_ajax_bitforms_zcrm_generate_token', [__CLASS__, 'generateTokens']);
46 add_action('wp_ajax_bitforms_zcrm_refresh_modules', [__CLASS__, 'refreshModulesAjaxHelper']);
47 add_action('wp_ajax_bitforms_zcrm_refresh_layouts', [__CLASS__, 'refreshLayoutsAjaxHelper']);
48 add_action('wp_ajax_bitforms_zcrm_get_users', [__CLASS__, 'refreshUsersAjaxHelper']);
49 add_action('wp_ajax_bitforms_zcrm_get_tags', [__CLASS__, 'refreshTagListAjaxHelper']);
50 add_action('wp_ajax_bitforms_zcrm_get_assignment_rules', [__CLASS__, 'getAssignmentRulesAjaxHelper']);
51 add_action('wp_ajax_bitforms_zcrm_get_related_lists', [__CLASS__, 'getRelatedListsAjaxHelper']);
52 }
53
54 /**
55 * Process ajax request for generate_token
56 *
57 * @return JSON 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 if (
70 empty($requestsParams->{'accounts-server'})
71 || empty($requestsParams->dataCenter)
72 || empty($requestsParams->clientId)
73 || empty($requestsParams->clientSecret)
74 || empty($requestsParams->redirectURI)
75 || empty($requestsParams->code)
76 ) {
77 wp_send_json_error(
78 __(
79 'Requested parameter is empty',
80 'bit-form'
81 ),
82 400
83 );
84 }
85 $apiEndpoint = \urldecode($requestsParams->{'accounts-server'}) . '/oauth/v2/token';
86 $requestParams = [
87 'grant_type' => 'authorization_code',
88 'client_id' => $requestsParams->clientId,
89 'client_secret' => $requestsParams->clientSecret,
90 'redirect_uri' => \urldecode($requestsParams->redirectURI),
91 'code' => $requestsParams->code
92 ];
93 $apiResponse = HttpHelper::post($apiEndpoint, $requestParams);
94 if (is_wp_error($apiResponse) || !empty($apiResponse->error)) {
95 wp_send_json_error(
96 empty($apiResponse->error) ? 'Unknown' : $apiResponse->error,
97 400
98 );
99 }
100 $apiResponse->generates_on = \time();
101 wp_send_json_success($apiResponse, 200);
102 } else {
103 wp_send_json_error(
104 __(
105 'Token expired',
106 'bit-form'
107 ),
108 401
109 );
110 }
111 }
112
113 /**
114 * Process ajax request for refresh crm modules
115 *
116 * @return JSON crm module data
117 */
118 public static function refreshModulesAjaxHelper()
119 {
120 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
121 GlobalHelper::requirePostMethod();
122
123 try {
124 $queryParams = GlobalHelper::formatRequestData();
125 } catch (\InvalidArgumentException $e) {
126 wp_send_json_error($e->getMessage(), 400);
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'] = ZohoCRMHandler::_refreshAccessToken($queryParams);
145 }
146 $zohosIntegratedModules = [
147 'zohosign__ZohoSign_Document_Events',
148 'zohoshowtime__ShowTime_Sessions',
149 'zohoshowtime__Zoho_ShowTime',
150 'zohosign__ZohoSign_Documents',
151 'zohosign__ZohoSign_Recipients'
152 ];
153 $modulesMetaApiEndpoint = "{$queryParams->tokenDetails->api_domain}/crm/v2/settings/modules";
154 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
155 $modulesMetaResponse = HttpHelper::get($modulesMetaApiEndpoint, null, $authorizationHeader);
156 if (!is_wp_error($modulesMetaResponse) && (empty($modulesMetaResponse->status) || (!empty($modulesMetaResponse->status) && 'error' !== $modulesMetaResponse->status))) {
157 $retriveModuleData = $modulesMetaResponse->modules;
158
159 $allModules = [];
160 foreach ($retriveModuleData as $key => $value) {
161 if ((!empty($value->inventory_template_supported) && $value->inventory_template_supported) || \in_array($value->api_name, $zohosIntegratedModules)) {
162 continue;
163 }
164 if (!empty($value->api_supported) && $value->api_supported && !empty($value->editable) && $value->editable) {
165 $allModules[$value->api_name] = (object) [
166 'plural_label' => $value->plural_label,
167 'triggers_supported' => $value->triggers_supported,
168 'quick_create' => $value->quick_create,
169 ];
170 }
171 }
172 uksort($allModules, 'strnatcasecmp');
173 $response['modules'] = $allModules;
174 } else {
175 wp_send_json_error(
176 empty($modulesMetaResponse->error) ? 'Unknown' : $modulesMetaResponse->error,
177 400
178 );
179 }
180 if (!empty($response['tokenDetails']) && !empty($queryParams->id)) {
181 ZohoCRMHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response['modules']);
182 }
183 wp_send_json_success($response, 200);
184 } else {
185 wp_send_json_error(
186 __(
187 'Token expired',
188 'bit-form'
189 ),
190 401
191 );
192 }
193 }
194
195 /**
196 * Process ajax request for refesh crm layouts
197 *
198 * @return JSON crm layout data
199 */
200 public static function refreshLayoutsAjaxHelper()
201 {
202 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
203 GlobalHelper::requirePostMethod();
204
205 try {
206 $queryParams = GlobalHelper::formatRequestData();
207 } catch (\InvalidArgumentException $e) {
208 wp_send_json_error($e->getMessage(), 400);
209 }
210
211 if (
212 empty($queryParams->module)
213 || empty($queryParams->tokenDetails)
214 || empty($queryParams->dataCenter)
215 || empty($queryParams->clientId)
216 || empty($queryParams->clientSecret)
217 ) {
218 wp_send_json_error(
219 __(
220 'Requested parameter is empty',
221 'bit-form'
222 ),
223 400
224 );
225 }
226 $response = [];
227 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
228 $response['tokenDetails'] = ZohoCRMHandler::_refreshAccessToken($queryParams);
229 }
230 $layoutsMetaApiEndpoint = "{$queryParams->tokenDetails->api_domain}/crm/v2/settings/layouts";
231 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
232 $requiredParams['module'] = $queryParams->module;
233 $layoutsMetaResponse = HttpHelper::get($layoutsMetaApiEndpoint, $requiredParams, $authorizationHeader);
234 if (!is_wp_error($layoutsMetaResponse) && (empty($layoutsMetaResponse->status) || (!empty($layoutsMetaResponse->status) && 'error' !== $layoutsMetaResponse->status))) {
235 $retriveLayoutsData = $layoutsMetaResponse->layouts;
236 $layouts = [];
237 foreach ($retriveLayoutsData as $layoutKey => $layoutValue) {
238 $fields = [];
239 $fileUploadFields = [];
240 $requiredFields = [];
241 $requiredFileUploadFiles = [];
242 $uniqueFields = [];
243 foreach ($layoutValue->sections as $sectionKey => $sectionValue) {
244 foreach ($sectionValue->fields as $fieldKey => $fieldDetails) {
245 if (empty($fieldDetails->subform) && !empty($fieldDetails->api_name) && !empty($fieldDetails->view_type->create) && $fieldDetails->view_type->create && 'ownerlookup' !== $fieldDetails->data_type) {
246 if ('fileupload' === $fieldDetails->data_type) {
247 $fileUploadFields[$fieldDetails->api_name] = (object) [
248 'display_label' => $fieldDetails->display_label,
249 'length' => $fieldDetails->length,
250 'visible' => $fieldDetails->visible,
251 'json_type' => $fieldDetails->json_type,
252 'data_type' => $fieldDetails->data_type,
253 'required' => $fieldDetails->required
254 ];
255 } else {
256 $fields[$fieldDetails->api_name] = (object) [
257 'display_label' => $fieldDetails->display_label,
258 'length' => $fieldDetails->length,
259 'visible' => $fieldDetails->visible,
260 'json_type' => $fieldDetails->json_type,
261 'data_type' => $fieldDetails->data_type,
262 'required' => $fieldDetails->required
263 ];
264 }
265
266 if (!empty($fieldDetails->required) && $fieldDetails->required) {
267 if ('fileupload' === $fieldDetails->data_type) {
268 $requiredFileUploadFiles[] = $fieldDetails->api_name;
269 } elseif ('Parent_Id' !== $fieldDetails->api_name) {
270 $requiredFields[] = $fieldDetails->api_name;
271 }
272 }
273 if (!empty($fieldDetails->unique) && count((array)$fieldDetails->unique)) {
274 $uniqueFields[] = $fieldDetails->api_name;
275 }
276 }
277 }
278 }
279 uksort($fields, 'strnatcasecmp');
280 uksort($fileUploadFields, 'strnatcasecmp');
281 usort($requiredFields, 'strnatcasecmp');
282 usort($requiredFileUploadFiles, 'strnatcasecmp');
283
284 $layouts[$layoutValue->name] = (object) [
285 'visible' => $layoutValue->visible,
286 'fields' => $fields,
287 'required' => $requiredFields,
288 'unique' => $uniqueFields,
289 'id' => $layoutValue->id,
290 'fileUploadFields' => $fileUploadFields,
291 'requiredFileUploadFields' => $requiredFileUploadFiles
292 ];
293 }
294 uksort($layouts, 'strnatcasecmp');
295 $response['layouts'] = $layouts;
296 } else {
297 wp_send_json_error(
298 'error' === $layoutsMetaResponse->status ? $layoutsMetaResponse->message : 'Unknown',
299 400
300 );
301 }
302 if (!empty($response['tokenDetails']) && $response['tokenDetails'] && !empty($queryParams->id)) {
303 $response['queryModule'] = $queryParams->module;
304 ZohoCRMHandler::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response);
305 }
306 wp_send_json_success($response, 200);
307 } else {
308 wp_send_json_error(
309 __(
310 'Token expired',
311 'bit-form'
312 ),
313 401
314 );
315 }
316 }
317
318 /**
319 * Helps to refresh zoho crm access_token
320 *
321 * @param object $apiData Contains required data for refresh access token
322 * @return string json | boolean $tokenDetails API token details
323 */
324 protected static function _refreshAccessToken($apiData)
325 {
326 if (
327 empty($apiData->dataCenter)
328 || empty($apiData->clientId)
329 || empty($apiData->clientSecret)
330 || empty($apiData->tokenDetails)
331 ) {
332 return false;
333 }
334 $tokenDetails = $apiData->tokenDetails;
335
336 $dataCenter = $apiData->dataCenter;
337 $apiEndpoint = "https://accounts.zoho.{$dataCenter}/oauth/v2/token";
338 $requestParams = [
339 'grant_type' => 'refresh_token',
340 'client_id' => $apiData->clientId,
341 'client_secret' => $apiData->clientSecret,
342 'refresh_token' => $tokenDetails->refresh_token,
343 ];
344
345 $apiResponse = HttpHelper::post($apiEndpoint, $requestParams);
346 if (is_wp_error($apiResponse) || !empty($apiResponse->error)) {
347 return false;
348 }
349 $tokenDetails->generates_on = \time();
350 $tokenDetails->access_token = $apiResponse->access_token;
351 return $tokenDetails;
352 }
353
354 /**
355 * Save updated access_token to avoid unnecessary token generation
356 *
357 * @param integer $fromID ID of Integration related form
358 * @param integer $integrationID ID of Zoho crm Integration
359 * @param object $tokenDetails refreshed token info
360 *
361 * @return null
362 */
363 protected static function _saveRefreshedToken($formID, $integrationID, $tokenDetails, $others = null)
364 {
365 if (empty($formID) || empty($integrationID)) {
366 return;
367 }
368
369 $integrationHandler = new IntegrationHandler($formID, IpTool::getUserDetail());
370 $zcrmDetails = $integrationHandler->getAIntegration($integrationID);
371
372 if (is_wp_error($zcrmDetails)) {
373 return;
374 }
375 $newDetails = json_decode($zcrmDetails[0]->integration_details);
376
377 $newDetails->tokenDetails = $tokenDetails;
378 if (!empty($others['modules'])) {
379 $newDetails->default->modules = $others['modules'];
380 }
381 if (!empty($others['layouts']) && !empty($others['queryModule'])) {
382 $newDetails->default->layouts->{$others['queryModule']} = $others['layouts'];
383 }
384
385 $integrationHandler->updateIntegration($integrationID, $zcrmDetails[0]->integration_name, 'Zoho CRM', wp_json_encode($newDetails), 'form');
386 }
387
388 /**
389 * Process ajax request for refresh crm users
390 *
391 * @return JSON crm users data
392 */
393 public static function refreshUsersAjaxHelper()
394 {
395 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
396 GlobalHelper::requirePostMethod();
397
398 try {
399 $queryParams = GlobalHelper::formatRequestData();
400 } catch (\InvalidArgumentException $e) {
401 wp_send_json_error($e->getMessage(), 400);
402 }
403
404 if (
405 empty($queryParams->tokenDetails)
406 || empty($queryParams->dataCenter)
407 || empty($queryParams->clientId)
408 || empty($queryParams->clientSecret)
409 ) {
410 wp_send_json_error(
411 __(
412 'Requested parameter is empty',
413 'bit-form'
414 ),
415 400
416 );
417 }
418 $response = [];
419 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
420 $response['tokenDetails'] = self::_refreshAccessToken($queryParams);
421 }
422 $usersApiEndpoint = "{$queryParams->tokenDetails->api_domain}/crm/v2/users?type=ActiveConfirmedUsers";
423 $authorizationHeader['Authorization'] = "Zoho-oauthtoken {$queryParams->tokenDetails->access_token}";
424 $retrivedUsersData = [];
425 $usersResponse = (object) [];
426 do {
427 $requiredParams = [];
428 if (!empty($usersResponse->users)) {
429 if (!empty($retrivedUsersData)) {
430 $retrivedUsersData = array_merge($retrivedUsersData, $usersResponse->users);
431 } else {
432 $retrivedUsersData = $usersResponse->users;
433 }
434 }
435 if (!empty($usersResponse->info->more_records) && $usersResponse->info->more_records) {
436 $requiredParams['page'] = intval($usersResponse->info->page) + 1;
437 }
438 $usersResponse = HttpHelper::get($usersApiEndpoint, $requiredParams, $authorizationHeader);
439 } while (null === $usersResponse || (!empty($usersResponse->info->more_records) && $usersResponse->info->more_records));
440 if (empty($requiredParams) && !is_wp_error($usersResponse)) {
441 $retrivedUsersData = $usersResponse->users;
442 }
443 if (!is_wp_error($usersResponse) && !empty($retrivedUsersData)) {
444 $users = [];
445 foreach ($retrivedUsersData as $userKey => $userValue) {
446 $users[$userValue->full_name] = (object) [
447 'full_name' => $userValue->full_name,
448 'id' => $userValue->id,
449 ];
450 }
451 uksort($users, 'strnatcasecmp');
452 $response['users'] = $users;
453 } else {
454 wp_send_json_error(
455 'error' === $usersResponse->status ? $usersResponse->message : 'Unknown',
456 400
457 );
458 }
459 if (!empty($response['tokenDetails']) && $response['tokenDetails'] && !empty($queryParams->id)) {
460 self::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response);
461 }
462 wp_send_json_success($response, 200);
463 } else {
464 wp_send_json_error(
465 __(
466 'Token expired',
467 'bit-form'
468 ),
469 401
470 );
471 }
472 }
473
474 /**
475 * Process ajax request for refresh tags of a module
476 *
477 * @return JSON crm Tags for a module
478 */
479 public static function refreshTagListAjaxHelper()
480 {
481 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
482 GlobalHelper::requirePostMethod();
483
484 try {
485 $queryParams = GlobalHelper::formatRequestData();
486 } catch (\InvalidArgumentException $e) {
487 wp_send_json_error($e->getMessage(), 400);
488 }
489
490 if (
491 empty($queryParams->module)
492 || empty($queryParams->tokenDetails)
493 || empty($queryParams->dataCenter)
494 || empty($queryParams->clientId)
495 || empty($queryParams->clientSecret)
496 ) {
497 wp_send_json_error(
498 __(
499 'Requested parameter is empty',
500 'bit-form'
501 ),
502 400
503 );
504 }
505 $response = [];
506 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
507 $response['tokenDetails'] = self::_refreshAccessToken($queryParams);
508 }
509 $tokenDetails = empty($response['tokenDetails']) ? $queryParams->tokenDetails : $response['tokenDetails'];
510 $tagApiHelper = new TagApiHelper($tokenDetails, $queryParams->module);
511 $tagListApiResponse = $tagApiHelper->getTagList();
512 if (!is_wp_error($tagListApiResponse)) {
513 usort($tagListApiResponse, 'strnatcasecmp');
514 $response['tags'] = $tagListApiResponse;
515 } else {
516 wp_send_json_error(
517 is_wp_error($tagListApiResponse) ? $tagListApiResponse->get_error_message() : (empty($tagListApiResponse) ? __('Tag is empty', 'bit-form') : 'Unknown'),
518 empty($tagListApiResponse) ? 204 : 400
519 );
520 }
521 if (!empty($response['tokenDetails']) && $response['tokenDetails'] && !empty($queryParams->id)) {
522 self::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response);
523 }
524 wp_send_json_success($response, 200);
525 } else {
526 wp_send_json_error(
527 __(
528 'Token expired',
529 'bit-form'
530 ),
531 401
532 );
533 }
534 }
535
536 /**
537 * Process ajax request to get assignment rules of a Zoho CRM module
538 *
539 * @return JSON crm assignment rules data
540 */
541 public static function getAssignmentRulesAjaxHelper()
542 {
543 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
544 GlobalHelper::requirePostMethod();
545
546 try {
547 $queryParams = GlobalHelper::formatRequestData();
548 } catch (\InvalidArgumentException $e) {
549 wp_send_json_error($e->getMessage(), 400);
550 }
551
552 if (
553 empty($queryParams->module)
554 || empty($queryParams->tokenDetails)
555 || empty($queryParams->dataCenter)
556 || empty($queryParams->clientId)
557 || empty($queryParams->clientSecret)
558 ) {
559 wp_send_json_error(
560 __(
561 'Requested parameter is empty',
562 'bit-form'
563 ),
564 400
565 );
566 }
567 $response = [];
568 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
569 $response['tokenDetails'] = self::_refreshAccessToken($queryParams);
570 }
571 $metaDataApiHelper = new MetaDataApiHelper($queryParams->tokenDetails, true);
572 $assignmentRulesResponse = $metaDataApiHelper->getAssignmentRules($queryParams->module);
573 if (
574 !is_wp_error($assignmentRulesResponse)
575 && !empty($assignmentRulesResponse)
576 && empty($assignmentRulesResponse->status)
577 ) {
578 uksort($assignmentRulesResponse, 'strnatcasecmp');
579 $response['assignmentRules'] = $assignmentRulesResponse;
580 } else {
581 wp_send_json_error(
582 !empty($assignmentRulesResponse->status)
583 && 'error' === $assignmentRulesResponse->status ?
584 $assignmentRulesResponse->message : (empty($assignmentRulesResponse) ? __('Assignment rules is empty', 'bit-form') : 'Unknown'),
585 empty($assignmentRulesResponse) ? 204 : 400
586 );
587 }
588 if (!empty($response['tokenDetails']) && $response['tokenDetails'] && !empty($queryParams->id)) {
589 // $response["queryModule"] = $queryParams->module;
590 self::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response);
591 }
592 wp_send_json_success($response, 200);
593 } else {
594 wp_send_json_error(
595 __(
596 'Token expired',
597 'bit-form'
598 ),
599 401
600 );
601 }
602 }
603
604 /**
605 * Process ajax request to get realted lists of a Zoho CRM module
606 *
607 * @return JSON crm layout data
608 */
609 public static function getRelatedListsAjaxHelper()
610 {
611 if (isset($_REQUEST['_ajax_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])), 'bitforms_save')) {
612 GlobalHelper::requirePostMethod();
613
614 try {
615 $queryParams = GlobalHelper::formatRequestData();
616 } catch (\InvalidArgumentException $e) {
617 wp_send_json_error($e->getMessage(), 400);
618 }
619
620 if (
621 empty($queryParams->module)
622 || empty($queryParams->tokenDetails)
623 || empty($queryParams->dataCenter)
624 || empty($queryParams->clientId)
625 || empty($queryParams->clientSecret)
626 ) {
627 wp_send_json_error(
628 __(
629 'Requested parameter is empty',
630 'bit-form'
631 ),
632 400
633 );
634 }
635 $response = [];
636 if ((intval($queryParams->tokenDetails->generates_on) + (55 * 60)) < time()) {
637 $response['tokenDetails'] = self::_refreshAccessToken($queryParams);
638 }
639 $metaDataApiHelper = new MetaDataApiHelper($queryParams->tokenDetails);
640 $relatedListResponse = $metaDataApiHelper->getRelatedLists($queryParams->module);
641 if (
642 !is_wp_error($relatedListResponse)
643 && !empty($relatedListResponse)
644 && empty($relatedListResponse->status)
645 ) {
646 uksort($relatedListResponse, 'strnatcasecmp');
647 $response['relatedLists'] = $relatedListResponse;
648 } else {
649 wp_send_json_error(
650 !empty($relatedListResponse->status)
651 && 'error' === $relatedListResponse->status ?
652 $relatedListResponse->message : (empty($relatedListResponse) ? __('RelatedList is empty', 'bit-form') : 'Unknown'),
653 empty($relatedListResponse) ? 204 : 400
654 );
655 }
656 if (!empty($response['tokenDetails']) && $response['tokenDetails'] && !empty($queryParams->id)) {
657 // $response["queryModule"] = $queryParams->module;
658 self::_saveRefreshedToken($queryParams->formID, $queryParams->id, $response['tokenDetails'], $response);
659 }
660 wp_send_json_success($response, 200);
661 } else {
662 wp_send_json_error(
663 __(
664 'Token expired',
665 'bit-form'
666 ),
667 401
668 );
669 }
670 }
671
672 public static function addRelatedListV2($zcrmApiResponse, $formID, $entryID, $integID, $logID, $fieldValues, $integrationDetails, $recordApiHelper)
673 {
674 foreach ($integrationDetails->relatedlists as $relatedlist) {
675 // Related List apis..
676 $relatedListModule = !empty($relatedlist->module) ? $relatedlist->module : '';
677 $relatedListLayout = !empty($relatedlist->layout) ? $relatedlist->layout : '';
678 $defaultDataConf = $integrationDetails->default;
679 if (empty($relatedListModule) || empty($relatedListLayout)) {
680 return new WP_Error('REQ_FIELD_EMPTY', __('module, layout are required for zoho crm relatedlist', 'bit-form'));
681 }
682 $module = $integrationDetails->module;
683 $moduleSingular = \substr($module, 0, \strlen($module) - 1);
684 if (isset($defaultDataConf->layouts->{$relatedListModule}->{$relatedListLayout}->fields->{$module})) {
685 $moduleSingular = $module;
686 } elseif (!isset($defaultDataConf->layouts->{$relatedListModule}->{$relatedListLayout}->fields->{$moduleSingular})) {
687 $moduleSingular = '';
688 }
689 $relatedListRequired = !empty($defaultDataConf->layouts->{$relatedListModule}->{$relatedListLayout}->required) ?
690 $defaultDataConf->layouts->{$relatedListModule}->{$relatedListLayout}->required : [];
691 $recordID = $zcrmApiResponse->data[0]->details->id;
692 $defaultDataConf->layouts->{$relatedListModule}->{$relatedListLayout}->fields->{'$se_module'} = (object) [
693 'length' => 200,
694 'visible' => true,
695 'json_type' => 'string',
696 'data_type' => 'string',
697 ];
698 $fieldValues['$se_module'] = $module;
699 $relatedlist->field_map[] = (object)
700 [
701 'formField' => '$se_module',
702 'zohoFormField' => '$se_module'
703 ];
704 if (isset($defaultDataConf->layouts->{$relatedListModule}->{$relatedListLayout}->fields->Parent_Id)) {
705 $fieldValues['Parent_Id'] = (object) ['id' => $recordID];
706 $relatedlist->field_map[] = (object)
707 [
708 'formField' => 'Parent_Id',
709 'zohoFormField' => 'Parent_Id'
710 ];
711 } elseif (!empty($moduleSingular)) {
712 $fieldValues[$moduleSingular] = ['id' => $recordID];
713 $relatedlist->field_map[] = (object)
714 [
715 'formField' => $moduleSingular,
716 'zohoFormField' => $moduleSingular
717 ];
718 } elseif ('Contacts' === $module) {
719 $fieldValues['Who_Id'] = (object) ['id' => $recordID];
720 $relatedlist->field_map[] = (object)
721 [
722 'formField' => 'Who_Id',
723 'zohoFormField' => 'Who_Id'
724 ];
725 } else {
726 $fieldValues['What_Id'] = (object) ['id' => $recordID];
727 $relatedlist->field_map[] = (object)
728 [
729 'formField' => 'What_Id',
730 'zohoFormField' => 'What_Id'
731 ];
732 }
733
734 $zcrmRelatedlistApiResponse = $recordApiHelper->executeRecordApi(
735 $formID,
736 $entryID,
737 $integID,
738 $logID,
739 $defaultDataConf,
740 $relatedListModule,
741 $relatedListLayout,
742 $fieldValues,
743 $relatedlist->field_map,
744 $relatedlist->actions,
745 $relatedListRequired,
746 $relatedlist->upload_field_map,
747 true
748 );
749 }
750 }
751
752 public function execute(IntegrationHandler $integrationHandler, $integrationData, $fieldValues, $entryID, $logID)
753 {
754 $entryDetails = [
755 'formId' => $this->_formID,
756 'entryId' => $entryID,
757 'fieldValues' => $fieldValues
758 ];
759
760 $integrationDetails = is_string($integrationData->integration_details) ? json_decode($integrationData->integration_details) : $integrationData->integration_details;
761
762 $tokenDetails = $integrationDetails->tokenDetails;
763 $module = $integrationDetails->module;
764 $layout = $integrationDetails->layout;
765 $fieldMap = $integrationDetails->field_map;
766 $fileMap = $integrationDetails->upload_field_map;
767 $actions = $integrationDetails->actions;
768 $defaultDataConf = $integrationDetails->default;
769
770 if (
771 empty($tokenDetails)
772 || empty($module)
773 || empty($layout)
774 || empty($fieldMap)
775 ) {
776 $error = new WP_Error('REQ_FIELD_EMPTY', __('module, layout, fields are required for zoho crm api', 'bit-form'));
777 $this->_logResponse->apiResponse($logID, $this->_integrationID, 'record', 'validation', $error, $entryDetails);
778 return $error;
779 }
780 if (empty($defaultDataConf->layouts->{$module}->{$layout}->fields) || empty($defaultDataConf->modules->{$module})) {
781 $error = new WP_Error('REQ_FIELD_EMPTY', __('module, layout, fields are required for zoho crm api', 'bit-form'));
782 $this->_logResponse->apiResponse($logID, $this->_integrationID, 'record', 'validation', $error, $entryDetails);
783 return $error;
784 }
785 if ((intval($tokenDetails->generates_on) + (55 * 60)) < time()) {
786 $requiredParams['clientId'] = $integrationDetails->clientId;
787 $requiredParams['clientSecret'] = $integrationDetails->clientSecret;
788 $requiredParams['dataCenter'] = $integrationDetails->dataCenter;
789 $requiredParams['tokenDetails'] = $tokenDetails;
790 $newTokenDetails = ZohoCRMHandler::_refreshAccessToken((object)$requiredParams);
791 if ($newTokenDetails) {
792 ZohoCRMHandler::_saveRefreshedToken($this->_formID, $this->_integrationID, $newTokenDetails);
793 $tokenDetails = $newTokenDetails;
794 }
795 }
796
797 $required = !empty($defaultDataConf->layouts->{$module}->{$layout}->required) ?
798 $defaultDataConf->layouts->{$module}->{$layout}->required : [];
799 $actions = $integrationDetails->actions;
800 $recordApiHelper = new RecordApiHelper($tokenDetails);
801 $zcrmApiResponse = $recordApiHelper->executeRecordApi(
802 $this->_formID,
803 $entryID,
804 $this->_integrationID,
805 $logID,
806 $defaultDataConf,
807 $module,
808 $layout,
809 $fieldValues,
810 $fieldMap,
811 $actions,
812 $required,
813 $fileMap
814 );
815 if (is_wp_error($zcrmApiResponse)) {
816 return $zcrmApiResponse;
817 }
818 if (
819 !empty($zcrmApiResponse->data)
820 && !empty($zcrmApiResponse->data[0]->code)
821 && 'SUCCESS' === $zcrmApiResponse->data[0]->code
822 && count($integrationDetails->relatedlists)
823 ) {
824 $zcrmApiResponse = self::addRelatedListV2($zcrmApiResponse, $this->_formID, $entryID, $this->_integrationID, $logID, $fieldValues, $integrationDetails, $recordApiHelper);
825 }
826 return $zcrmApiResponse;
827 }
828 }
829