Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 76 additions & 100 deletions backend/Actions/ActiveCampaign/RecordApiHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,127 +55,63 @@ public function execute($integrationDetails, $fieldValues, $fieldMap, $actions,
$fieldData = [];
$customFields = [];

foreach ($fieldMap as $fieldKey => $fieldPair) {
if (!empty($fieldPair->activeCampaignField)) {
if ($fieldPair->formField === 'custom' && isset($fieldPair->customValue) && !is_numeric($fieldPair->activeCampaignField)) {
$fieldData[$fieldPair->activeCampaignField] = $fieldPair->customValue;
} elseif (is_numeric($fieldPair->activeCampaignField) && $fieldPair->formField === 'custom' && isset($fieldPair->customValue)) {
$customFields[] = ['field' => (int) $fieldPair->activeCampaignField, 'value' => $fieldPair->customValue];
} elseif (is_numeric($fieldPair->activeCampaignField)) {
$customFields[] = ['field' => (int) $fieldPair->activeCampaignField, 'value' => $fieldValues[$fieldPair->formField]];
// Efficient field mapping
foreach ($fieldMap as $fieldPair) {
if (empty($fieldPair->activeCampaignField)) {
continue;
}
$acField = $fieldPair->activeCampaignField;
$formField = $fieldPair->formField;
$customValue = $fieldPair->customValue ?? null;

if ($formField === 'custom' && isset($customValue)) {
if (is_numeric($acField)) {
$customFields[] = ['field' => (int) $acField, 'value' => $customValue];
} else {
$fieldData[$fieldPair->activeCampaignField] = $fieldValues[$fieldPair->formField];
$fieldData[$acField] = $customValue;
}
} elseif (is_numeric($acField)) {
$customFields[] = ['field' => (int) $acField, 'value' => $fieldValues[$formField] ?? ''];
} else {
$fieldData[$acField] = $fieldValues[$formField] ?? '';
}
}

if (!empty($customFields)) {
if ($customFields) {
$fieldData['fieldValues'] = $customFields;
}
$activeCampaign['contact'] = (object) $fieldData;
$existContact = $this->existContact($activeCampaign['contact']->email);
$activeCampaign = ['contact' => (object) $fieldData];
$email = $fieldData['email'] ?? null;
$existContact = $email ? $this->existContact($email) : null;

$updateContact = !empty($actions->update);
$hasContact = !empty($existContact->contacts);
$type = 'notSet';
$updateContact = $actions->update;
if (!$updateContact && empty($existContact->contacts)) {
$recordApiResponse = null;

if (!$updateContact && !$hasContact) {
$recordApiResponse = $this->storeOrModifyRecord('contacts', wp_json_encode($activeCampaign));
$type = 'insert';
if (isset($recordApiResponse->contact)) {
$recordApiResponse = ['success' => true, 'id' => $recordApiResponse->contact->id];
if (isset($listId) && !empty($listId)) {
$data['contactList'] = (object) [
'list' => $listId,
'contact' => $recordApiResponse['id'],
'status' => 1
];
$this->storeOrModifyRecord('contactLists', wp_json_encode($data));
}
if (isset($tags) && !empty($tags)) {
foreach ($tags as $tag) {
$data['contactTag'] = (object) [
'contact' => $recordApiResponse['id'],
'tag' => $tag
];
$this->storeOrModifyRecord('contactTags', wp_json_encode($data));
}
}
if (isset($integrationDetails->selectedAccount) && !empty($integrationDetails->selectedAccount)) {
$data['accountContact'] = [
'account' => $listId,
'contact' => $recordApiResponse['id'],
];
if (isset($integrationDetails->job_title)) {
$data['accountContact'] += ['jobTitle' => $integrationDetails->job_title];
}
$this->storeOrModifyRecord('accountContacts', wp_json_encode((object) $data));
}
}
} elseif ($updateContact && !empty($existContact->contacts)) {
$recordApiResponse = $this->updateRecord($existContact->contacts[0]->id, $activeCampaign, $existContact);
if (isset($tags) && !empty($tags)) {
foreach ($tags as $tag) {
$data['contactTag'] = (object) [
'contact' => $recordApiResponse->contact->id,
'tag' => $tag
];
$this->storeOrModifyRecord('contactTags', wp_json_encode($data));
}
}
if (isset($recordApiResponse->contact)) {
$recordApiResponse = ['success' => true, 'id' => $recordApiResponse->contact->id];
}
if (isset($integrationDetails->selectedAccount) && !empty($integrationDetails->selectedAccount)) {
$data['accountContact'] = [
'account' => $listId,
'contact' => $recordApiResponse->contact->id,
];
if (isset($integrationDetails->job_title)) {
$data['accountContact'] += ['jobTitle' => $integrationDetails->job_title];
}
$this->storeOrModifyRecord('accountContacts', wp_json_encode((object) $data));
}
} elseif ($updateContact && $hasContact) {
$contactId = $existContact->contacts[0]->id;
$recordApiResponse = $this->updateRecord($contactId, $activeCampaign, $existContact);
$type = 'update';
} elseif ($updateContact && empty($existContact->contacts)) {
} elseif ($updateContact && !$hasContact) {
$recordApiResponse = $this->storeOrModifyRecord('contacts', wp_json_encode($activeCampaign));
$type = 'insert';
if (isset($recordApiResponse->contact)) {
$recordApiResponse = ['success' => true, 'id' => $recordApiResponse->contact->id];
if (isset($listId) && !empty($listId)) {
$data['contactList'] = (object) [
'list' => $listId,
'contact' => $recordApiResponse['id'],
'status' => 1
];
$this->storeOrModifyRecord('contactLists', wp_json_encode($data));
}
if (isset($tags) && !empty($tags)) {
foreach ($tags as $tag) {
$data['contactTag'] = (object) [
'contact' => $recordApiResponse['id'],
'tag' => $tag
];
$this->storeOrModifyRecord('contactTags', wp_json_encode($data));
}
}
if (isset($integrationDetails->selectedAccount) && !empty($integrationDetails->selectedAccount)) {
$data['accountContact'] = [
'account' => $listId,
'contact' => $recordApiResponse['id'],
];
if (isset($integrationDetails->job_title)) {
$data['accountContact'] += ['jobTitle' => $integrationDetails->job_title];
}
$this->storeOrModifyRecord('accountContacts', wp_json_encode((object) $data));
}
}
}

if (!empty($recordApiResponse->contact)) {
$related = $this->handleRelatedActions($recordApiResponse->contact->id, $listId, $tags, $integrationDetails);
$recordApiResponse = (object) array_merge((array) $recordApiResponse, $related);
}

if ($type === 'notSet') {
LogHandler::save($this->_integrationID, ['type' => 'record', 'type_name' => 'insert'], 'error', __('Email already exist', 'bit-integrations'));

return false;
}
if ($recordApiResponse && isset($recordApiResponse->errors)) {
if ($recordApiResponse && !empty($recordApiResponse->errors)) {
LogHandler::save($this->_integrationID, ['type' => 'record', 'type_name' => $type], 'error', $recordApiResponse->errors);
} else {
LogHandler::save($this->_integrationID, ['type' => 'record', 'type_name' => $type], 'success', $recordApiResponse);
Expand All @@ -184,6 +120,46 @@ public function execute($integrationDetails, $fieldValues, $fieldMap, $actions,
return $recordApiResponse;
}

private function handleRelatedActions($contactId, $listId, $tags, $integrationDetails)
{
$data = [];
$result = [];
if (!empty($listId)) {
$data['contactList'] = (object) [
'list' => $listId,
'contact' => $contactId,
'status' => 1
];
$result['lists'] = $this->storeOrModifyRecord('contactLists', wp_json_encode($data));
}
if (!empty($tags)) {
if ($integrationDetails->actions->tagUpdate) {
$result['tags_removed'] = HttpHelper::delete("{$this->_apiEndpoint}/contactTags/{$contactId}", null, $this->_defaultHeader);
}
Comment on lines +135 to +138
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$integrationDetails->actions->tagUpdate is accessed without guarding that actions exists, which can trigger warnings/notices (and in newer PHP versions, runtime warnings) when actions are missing. Use a safe check like !empty($integrationDetails->actions->tagUpdate) (or pass/use the $actions argument already available in execute()) before attempting tag removal.

Copilot uses AI. Check for mistakes.

$result['tags_added'] = [];
foreach ($tags as $tag) {
$data['contactTag'] = (object) [
'contact' => $contactId,
'tag' => $tag
];
$result['tags_added'][] = $this->storeOrModifyRecord('contactTags', wp_json_encode($data));
}
}
if (!empty($integrationDetails->selectedAccount)) {
$data['accountContact'] = [
'account' => $integrationDetails->selectedAccount,
'contact' => $contactId,
];
if (!empty($integrationDetails->job_title)) {
$data['accountContact']['jobTitle'] = $integrationDetails->job_title;
}
$result['account'] = $this->storeOrModifyRecord('accountContacts', wp_json_encode((object) $data));
}

return $result;
}

private function existContact($email)
{
$searchEndPoint = "{$this->_apiEndpoint}/contacts?email={$email}";
Expand Down
2 changes: 1 addition & 1 deletion backend/Actions/ConstantContact/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use BitApps\Integrations\Actions\ConstantContact\ConstantContactController;
use BitApps\Integrations\Core\Util\Route;

Route::post('cContact_generate_token', [ConstantContactController::class, 'generateTokens']);
Route::no_sanitize()->post('cContact_generate_token', [ConstantContactController::class, 'generateTokens']);
Route::post('cContact_refresh_list', [ConstantContactController::class, 'refreshList']);
Route::post('cContact_refresh_fields', [ConstantContactController::class, 'refreshListFields']);
Route::post('cContact_refresh_tags', [ConstantContactController::class, 'refreshTags']);
Expand Down
2 changes: 1 addition & 1 deletion backend/Actions/Dropbox/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
use BitApps\Integrations\Actions\Dropbox\DropboxController;
use BitApps\Integrations\Core\Util\Route;

Route::post('dropbox_authorization', [DropboxController::class, 'checkAuthorization']);
Route::no_sanitize()->post('dropbox_authorization', [DropboxController::class, 'checkAuthorization']);
Route::post('dropbox_get_all_folders', [DropboxController::class, 'getAllFolders']);
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public static function authorization($requestParams)

$apiEndpoint = 'https://oauth2.googleapis.com/token';
$header['Content-Type'] = 'application/x-www-form-urlencoded';

$apiResponse = HttpHelper::post($apiEndpoint, $body, $header);

if (is_wp_error($apiResponse) || !empty($apiResponse->error)) {
Expand Down
2 changes: 1 addition & 1 deletion backend/Actions/GoogleCalendar/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
use BitApps\Integrations\Actions\GoogleCalendar\GoogleCalendarController;
use BitApps\Integrations\Core\Util\Route;

Route::post('googleCalendar_authorization', [GoogleCalendarController::class, 'authorization']);
Route::no_sanitize()->post('googleCalendar_authorization', [GoogleCalendarController::class, 'authorization']);
Route::post('googleCalendar_get_all_lists', [GoogleCalendarController::class, 'getAllCalendarLists']);
2 changes: 1 addition & 1 deletion backend/Actions/GoogleContacts/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
use BitApps\Integrations\Actions\GoogleContacts\GoogleContactsController;
use BitApps\Integrations\Core\Util\Route;

Route::post('googleContacts_authorization', [GoogleContactsController::class, 'authorization']);
Route::no_sanitize()->post('googleContacts_authorization', [GoogleContactsController::class, 'authorization']);
2 changes: 1 addition & 1 deletion backend/Actions/GoogleDrive/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
use BitApps\Integrations\Actions\GoogleDrive\GoogleDriveController;
use BitApps\Integrations\Core\Util\Route;

Route::post('googleDrive_authorization', [GoogleDriveController::class, 'authorization']);
Route::no_sanitize()->post('googleDrive_authorization', [GoogleDriveController::class, 'authorization']);
Route::post('googleDrive_get_all_folders', [GoogleDriveController::class, 'getAllFolders']);
2 changes: 1 addition & 1 deletion backend/Actions/GoogleSheet/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use BitApps\Integrations\Actions\GoogleSheet\GoogleSheetController;
use BitApps\Integrations\Core\Util\Route;

Route::post('gsheet_generate_token', [GoogleSheetController::class, 'generateTokens']);
Route::no_sanitize()->post('gsheet_generate_token', [GoogleSheetController::class, 'generateTokens']);
Route::post('gsheet_refresh_spreadsheets', [GoogleSheetController::class, 'refreshSpreadsheetsAjaxHelper']);
Route::post('gsheet_refresh_worksheets', [GoogleSheetController::class, 'refreshWorksheetsAjaxHelper']);
Route::post('gsheet_refresh_worksheet_headers', [GoogleSheetController::class, 'refreshWorksheetHeadersAjaxHelper']);
2 changes: 1 addition & 1 deletion backend/Actions/Keap/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
use BitApps\Integrations\Actions\Keap\KeapController;
use BitApps\Integrations\Core\Util\Route;

Route::post('keap_generate_token', [KeapController::class, 'generateTokens']);
Route::no_sanitize()->post('keap_generate_token', [KeapController::class, 'generateTokens']);
Route::post('keap_fetch_all_tags', [KeapController::class, 'refreshTagListAjaxHelper']);
Route::post('keap_fetch_all_custom_fields', [KeapController::class, 'refreshCustomFieldAjaxHelper']);
2 changes: 1 addition & 1 deletion backend/Actions/LionDesk/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
use BitApps\Integrations\Actions\LionDesk\LionDeskController;
use BitApps\Integrations\Core\Util\Route;

Route::post('lionDesk_generate_token', [LionDeskController::class, 'generateTokens']);
Route::no_sanitize()->post('lionDesk_generate_token', [LionDeskController::class, 'generateTokens']);
Route::post('lionDesk_fetch_custom_fields', [LionDeskController::class, 'getCustomFields']);
Route::post('lionDesk_fetch_all_tags', [LionDeskController::class, 'getAllTags']);
2 changes: 1 addition & 1 deletion backend/Actions/MailChimp/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use BitApps\Integrations\Actions\MailChimp\MailChimpController;
use BitApps\Integrations\Core\Util\Route;

Route::post('mChimp_generate_token', [MailChimpController::class, 'generateTokens']);
Route::no_sanitize()->post('mChimp_generate_token', [MailChimpController::class, 'generateTokens']);
Route::post('mChimp_refresh_audience', [MailChimpController::class, 'refreshAudience']);
Route::post('mChimp_refresh_fields', [MailChimpController::class, 'refreshAudienceFields']);
Route::post('mChimp_refresh_tags', [MailChimpController::class, 'refreshTags']);
Expand Down
2 changes: 1 addition & 1 deletion backend/Actions/Mailup/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use BitApps\Integrations\Actions\Mailup\MailupController;
use BitApps\Integrations\Core\Util\Route;

Route::post('mailup_authorization', [MailupController::class, 'authorization']);
Route::no_sanitize()->post('mailup_authorization', [MailupController::class, 'authorization']);
Route::post('mailup_fetch_all_list', [MailupController::class, 'getAllList']);
Route::post('mailup_fetch_all_group', [MailupController::class, 'getAllGroup']);
Route::post('mailup_fetch_all_field', [MailupController::class, 'getAllField']);
2 changes: 1 addition & 1 deletion backend/Actions/Mautic/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use BitApps\Integrations\Actions\Mautic\MauticController;
use BitApps\Integrations\Core\Util\Route;

Route::post('mautic_generate_token', [MauticController::class, 'generateTokens']);
Route::no_sanitize()->post('mautic_generate_token', [MauticController::class, 'generateTokens']);
// Route::post('mChimp_refresh_audience', [ MailChimpController::class, 'refreshAudience']);
Route::post('mautic_get_fields', [MauticController::class, 'getAllFields']);
Route::post('mautic_get_tags', [MauticController::class, 'getAllTags']);
Expand Down
2 changes: 1 addition & 1 deletion backend/Actions/Notion/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
use BitApps\Integrations\Actions\Notion\NotionController;
use BitApps\Integrations\Core\Util\Route;

Route::post('notion_authorization', [NotionController::class, 'authorization']);
Route::no_sanitize()->post('notion_authorization', [NotionController::class, 'authorization']);
Route::post('notion_database_lists', [NotionController::class, 'getAllDatabaseLists']);
Route::post('notion_database_properties', [NotionController::class, 'getFieldsProperties']);
2 changes: 1 addition & 1 deletion backend/Actions/OneDrive/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
use BitApps\Integrations\Actions\OneDrive\OneDriveController;
use BitApps\Integrations\Core\Util\Route;

Route::post('oneDrive_authorization', [OneDriveController::class, 'authorization']);
Route::no_sanitize()->post('oneDrive_authorization', [OneDriveController::class, 'authorization']);
Route::post('oneDrive_get_all_folders', [OneDriveController::class, 'getAllFolders']);
Route::post('oneDrive_get_single_folder', [OneDriveController::class, 'singleOneDriveFolderList']);
2 changes: 1 addition & 1 deletion backend/Actions/PCloud/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
use BitApps\Integrations\Actions\PCloud\PCloudController;
use BitApps\Integrations\Core\Util\Route;

Route::post('pCloud_authorization', [PCloudController::class, 'authorization']);
Route::no_sanitize()->post('pCloud_authorization', [PCloudController::class, 'authorization']);
Route::post('pCloud_get_all_folders', [PCloudController::class, 'getAllFolders']);
11 changes: 8 additions & 3 deletions backend/Actions/Salesforce/RecordApiHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

use BitApps\Integrations\Config;
use BitApps\Integrations\Core\Util\Common;
use BitApps\Integrations\Core\Util\HttpHelper;
use BitApps\Integrations\Core\Util\Hooks;
use BitApps\Integrations\Core\Util\HttpHelper;
use BitApps\Integrations\Log\LogHandler;
use DateTime;
use DateTimeImmutable;
Expand Down Expand Up @@ -178,7 +178,7 @@ public function execute($integrationDetails, $fieldValues, $fieldMap, $actions)
$finalData = $this->generateReqDataFromFieldMap($fieldValues, $fieldMap);
$response = $this->insertContact($finalData, $update);

$responseType = !\is_null($response) || (\is_object($response) && isset($response->id)) ? 'success' : 'error';
$responseType = self::getResponseType();
$typeName = !$update || (\is_object($response) && isset($response->id)) ? 'Contact-create' : 'Contact-update';

$message = wp_json_encode($response);
Expand All @@ -204,7 +204,7 @@ public function execute($integrationDetails, $fieldValues, $fieldMap, $actions)

$insertLeadResponse = $this->insertLead($finalData, $update);

$responseType = !\is_null($insertLeadResponse) || (\is_object($insertLeadResponse) && isset($insertLeadResponse->id)) ? 'success' : 'error';
$responseType = self::getResponseType();
$typeName = !$update || (\is_object($insertLeadResponse) && isset($insertLeadResponse->id)) ? 'Lead-create' : 'Lead-update';

$message = wp_json_encode($insertLeadResponse);
Expand Down Expand Up @@ -502,4 +502,9 @@ private static function validateNumericDateWithLength($input, $length)
{
return is_numeric($input) && \strlen($input) === $length;
}

private static function getResponseType()
{
return strpos(HttpHelper::$responseCode, 20) === 0 ? 'success' : 'error';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The strpos function expects string arguments, but HttpHelper::$responseCode can be an integer, and 20 is an integer literal. This can lead to unexpected behavior or errors in different PHP versions. It's safer to cast the response code to a string and use a string for the needle.

        return strpos((string) HttpHelper::$responseCode, '20') === 0 ? 'success' : 'error';

}
Comment on lines +506 to +509
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getResponseType() is using strpos(HttpHelper::$responseCode, 20) which will misclassify 2xx responses like 204 (it doesn’t start with "20") and also relies on implicit int→string conversion. Cast the response code to string and check the first digit (or use an integer range check like 200–299) to reliably detect success.

Copilot uses AI. Check for mistakes.
}
Loading
Loading