Skip to content
Open
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
113 changes: 113 additions & 0 deletions backend/Actions/NextCrm/NextCrmController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

/**
* NextCrm Integration
*/

namespace BitApps\Integrations\Actions\NextCrm;

use WP_Error;

/**
* Provide functionality for NextCrm integration
*/
class NextCrmController
{
public static function isExists()
{
if (!\defined('NEXTCRM_VERSION') || !\function_exists('nextcrm_manager')) {
wp_send_json_error(
__(
'NextCRM is not activated or not installed',
'bit-integrations'
),
400
);
}
}

public function refreshTags()
{
self::isExists();

$response['tags'] = self::toOptions(nextcrm_manager()->contact->get_tags());
wp_send_json_success($response, 200);
}

public function refreshLists()
{
self::isExists();

$response['lists'] = self::toOptions(nextcrm_manager()->contact->get_lists());
wp_send_json_success($response, 200);
}

public function refreshCampaigns()
{
self::isExists();

$response['campaigns'] = self::toOptions(nextcrm_get_campaigns());
wp_send_json_success($response, 200);
}

public function refreshContactFields()
{
self::isExists();

$response['contactFields'] = self::toOptions(nextcrm_get_contact_properties());
wp_send_json_success($response, 200);
}

public function refreshContactTypes()
{
self::isExists();

$response['contactTypes'] = self::toOptions(nextcrm_contact_types());
wp_send_json_success($response, 200);
}

public function refreshContactStatuses()
{
self::isExists();

$response['contactStatuses'] = self::toOptions(nextcrm_contact_status());
wp_send_json_success($response, 200);
}

public function execute($integrationData, $fieldValues)
{
$integrationDetails = $integrationData->flow_details;
$integId = $integrationData->id;
$fieldMap = $integrationDetails->field_map;
$utilities = isset($integrationDetails->utilities) ? $integrationDetails->utilities : [];

if (empty($fieldMap)) {
return new WP_Error('field_map_empty', __('Field map is empty', 'bit-integrations'));
}

$recordApiHelper = new RecordApiHelper($integrationDetails, $integId);

return $recordApiHelper->execute($fieldValues, $fieldMap, $utilities);
}

/**
* NextCRM returns its dropdown sources as `[value => label]` maps.
*
* @param array $map
*
* @return array
*/
private static function toOptions($map)
{
$options = [];

foreach ((array) $map as $value => $label) {
$options[] = (object) [
'value' => $value,
'label' => \is_scalar($label) ? (string) $label : (string) $value,
];
}

return $options;
}
}
189 changes: 189 additions & 0 deletions backend/Actions/NextCrm/RecordApiHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<?php

/**
* NextCrm Record Api
*/

namespace BitApps\Integrations\Actions\NextCrm;

use BitApps\Integrations\Config;
use BitApps\Integrations\Core\Util\Common;
use BitApps\Integrations\Core\Util\Hooks;
use BitApps\Integrations\Log\LogHandler;

/**
* Provide functionality for Record insert, update
*/
class RecordApiHelper
{
private $_integrationID;

private $_integrationDetails;

public function __construct($integrationDetails, $integId)
{
$this->_integrationDetails = $integrationDetails;
$this->_integrationID = $integId;
}

/**
* Execute the integration
*
* @param array $fieldValues Field values from trigger
* @param array $fieldMap Field mapping
* @param array $utilities Optional actions to perform
*
* @return array
*/
public function execute($fieldValues, $fieldMap, $utilities)
{
if (!\defined('NEXTCRM_VERSION')) {
return [
'success' => false,
'message' => __('NextCRM is not installed or activated', 'bit-integrations')
];
}

$fieldData = static::generateReqDataFromFieldMap($fieldMap, $fieldValues);

$mainAction = $this->_integrationDetails->mainAction ?? 'create_contact';

$defaultResponse = [
'success' => false,
// translators: %s: Plugin name
'message' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro')
];

switch ($mainAction) {
case 'create_contact':
$response = Hooks::apply(Config::withPrefix('next_crm_create_contact'), $defaultResponse, $fieldData, $utilities);
$type = 'contact';

break;

case 'update_contact':
$response = Hooks::apply(Config::withPrefix('next_crm_update_contact'), $defaultResponse, $fieldData, $utilities);
$type = 'contact';

break;

case 'create_or_update_contact':
$response = Hooks::apply(Config::withPrefix('next_crm_create_or_update_contact'), $defaultResponse, $fieldData, $utilities);
$type = 'contact';

break;

case 'delete_contact':
$response = Hooks::apply(Config::withPrefix('next_crm_delete_contact'), $defaultResponse, $fieldData);
$type = 'contact';

break;

case 'change_contact_status':
$response = Hooks::apply(Config::withPrefix('next_crm_change_contact_status'), $defaultResponse, $fieldData, $this->_integrationDetails);
$type = 'contact';

break;

case 'update_contact_field':
$response = Hooks::apply(Config::withPrefix('next_crm_update_contact_field'), $defaultResponse, $fieldData, $this->_integrationDetails);
$type = 'contact';

break;

case 'set_contact_meta':
$response = Hooks::apply(Config::withPrefix('next_crm_set_contact_meta'), $defaultResponse, $fieldData);
$type = 'contact';

break;

case 'delete_contact_meta':
$response = Hooks::apply(Config::withPrefix('next_crm_delete_contact_meta'), $defaultResponse, $fieldData);
$type = 'contact';

break;

case 'add_contact_activity':
$response = Hooks::apply(Config::withPrefix('next_crm_add_contact_activity'), $defaultResponse, $fieldData, $utilities);
$type = 'activity';

break;

case 'create_tag':
$response = Hooks::apply(Config::withPrefix('next_crm_create_tag'), $defaultResponse, $fieldData);
$type = 'tag';

break;

case 'add_tag_to_contact':
$response = Hooks::apply(Config::withPrefix('next_crm_add_tag_to_contact'), $defaultResponse, $fieldData, $this->_integrationDetails);
$type = 'tag';

break;

case 'remove_tag_from_contact':
$response = Hooks::apply(Config::withPrefix('next_crm_remove_tag_from_contact'), $defaultResponse, $fieldData, $this->_integrationDetails);
$type = 'tag';

break;

case 'create_list':
$response = Hooks::apply(Config::withPrefix('next_crm_create_list'), $defaultResponse, $fieldData);
$type = 'list';

break;

case 'add_contact_to_list':
$response = Hooks::apply(Config::withPrefix('next_crm_add_contact_to_list'), $defaultResponse, $fieldData, $this->_integrationDetails);
$type = 'list';

break;

case 'remove_contact_from_list':
$response = Hooks::apply(Config::withPrefix('next_crm_remove_contact_from_list'), $defaultResponse, $fieldData, $this->_integrationDetails);
$type = 'list';

break;

case 'send_campaign_email':
$response = Hooks::apply(Config::withPrefix('next_crm_send_campaign_email'), $defaultResponse, $fieldData, $utilities, $this->_integrationDetails);
$type = 'campaign';

break;

default:
$response = [
'success' => false,
'message' => __('Invalid action', 'bit-integrations')
];
$type = 'NextCrm';

break;
}

$responseType = isset($response['success']) && $response['success'] ? 'success' : 'error';
LogHandler::save($this->_integrationID, ['type' => $type, 'type_name' => $mainAction], $responseType, $response);

return $response;
}

private static function generateReqDataFromFieldMap($fieldMap, $fieldValues)
{
$dataFinal = [];

foreach ($fieldMap as $item) {
$triggerValue = $item->formField;
$actionValue = $item->nextCrmField;

if (empty($actionValue)) {
continue;
}

$dataFinal[$actionValue] = $triggerValue === 'custom' && isset($item->customValue)
? Common::replaceFieldWithValue($item->customValue, $fieldValues)
: $fieldValues[$triggerValue] ?? '';
}

return $dataFinal;
}
}
15 changes: 15 additions & 0 deletions backend/Actions/NextCrm/Routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

if (!defined('ABSPATH')) {
exit;
}

use BitApps\Integrations\Actions\NextCrm\NextCrmController;
use BitApps\Integrations\Core\Util\Route;

Route::post('refresh_next_crm_tags', [NextCrmController::class, 'refreshTags']);
Route::post('refresh_next_crm_lists', [NextCrmController::class, 'refreshLists']);
Route::post('refresh_next_crm_campaigns', [NextCrmController::class, 'refreshCampaigns']);
Route::post('refresh_next_crm_contact_fields', [NextCrmController::class, 'refreshContactFields']);
Route::post('refresh_next_crm_contact_types', [NextCrmController::class, 'refreshContactTypes']);
Route::post('refresh_next_crm_contact_statuses', [NextCrmController::class, 'refreshContactStatuses']);
1 change: 1 addition & 0 deletions backend/Core/Util/AllTriggersName.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public static function allTriggersName()
'MoreConvertWishlist' => ['name' => 'MoreConvert Wishlist', 'isPro' => true, 'is_active' => false],
'Newsletter' => ['name' => 'Newsletter', 'isPro' => true, 'is_active' => false],
'NewUserApprove' => ['name' => 'New User Approve', 'isPro' => true, 'is_active' => false],
'NextCrm' => ['name' => 'NextCRM', 'isPro' => true, 'is_active' => false],
'NexForms' => ['name' => 'NEX-Forms', 'isPro' => true, 'is_active' => false],
'NF' => ['name' => 'Ninja Forms', 'isPro' => true, 'is_active' => false],
'NinjaTables' => ['name' => 'Ninja Tables', 'isPro' => true, 'is_active' => false],
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/Utils/StaticData/webhookIntegrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ export const customFormIntegrations = [
'GiveWp',
'SenseiLMS',
'FluentPlayer',
'BitCrm'
'BitCrm',
'NextCrm'
]

export const actionHookIntegrations = ['ActionHook']
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/AllIntegrations/EditInteg.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ const EditCreatorLms = lazy(() => import('./CreatorLms/EditCreatorLms'))
const EditUltimateAffiliatePro = lazy(() => import('./UltimateAffiliatePro/EditUltimateAffiliatePro'))
const EditBookly = lazy(() => import('./Bookly/EditBookly'))
const EditFluentCart = lazy(() => import('./FluentCart/EditFluentCart'))
const EditNextCrm = lazy(() => import('./NextCrm/EditNextCrm'))
const EditFluentPlayer = lazy(() => import('./FluentPlayer/EditFluentPlayer'))
const EditBitCrm = lazy(() => import('./BitCrm/EditBitCrm'))
const EditWsms = lazy(() => import('./Wsms/EditWsms'))
Expand Down Expand Up @@ -629,6 +630,8 @@ const IntegType = memo(({ allIntegURL, flow }) => {
return <EditUltimateAffiliatePro allIntegURL={allIntegURL} />
case 'Bookly':
return <EditBookly allIntegURL={allIntegURL} />
case 'NextCrm':
return <EditNextCrm allIntegURL={allIntegURL} />
case 'FluentCart':
return <EditFluentCart allIntegURL={allIntegURL} />
case 'FluentPlayer':
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/AllIntegrations/IntegInfo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ const UltimateAffiliateProAuthorization = lazy(
)
const BooklyAuthorization = lazy(() => import('./Bookly/BooklyAuthorization'))
const FluentCartAuthorization = lazy(() => import('./FluentCart/FluentCartAuthorization'))
const NextCrmAuthorization = lazy(() => import('./NextCrm/NextCrmAuthorization'))
const FluentPlayerAuthorization = lazy(() => import('./FluentPlayer/FluentPlayerAuthorization'))
const BitCrmAuthorization = lazy(() => import('./BitCrm/BitCrmAuthorization'))
const WsmsAuthorization = lazy(() => import('./Wsms/WsmsAuthorization'))
Expand Down Expand Up @@ -670,6 +671,8 @@ const IntegrationInfo = memo(({ integrationConf, location, editUrl }) => {
return <BooklyAuthorization booklyConf={integrationConf} step={1} isInfo />
case 'FluentCart':
return <FluentCartAuthorization fluentCartConf={integrationConf} step={1} isInfo />
case 'NextCrm':
return <NextCrmAuthorization nextCrmConf={integrationConf} step={1} isInfo />
case 'FluentPlayer':
return <FluentPlayerAuthorization fluentPlayerConf={integrationConf} step={1} isInfo />
case 'BitCrm':
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/components/AllIntegrations/NewInteg.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ const CreatorLms = lazy(() => import('./CreatorLms/CreatorLms'))
const UltimateAffiliatePro = lazy(() => import('./UltimateAffiliatePro/UltimateAffiliatePro'))
const Bookly = lazy(() => import('./Bookly/Bookly'))
const FluentCart = lazy(() => import('./FluentCart/FluentCart'))
const NextCrm = lazy(() => import('./NextCrm/NextCrm'))
const FluentPlayer = lazy(() => import('./FluentPlayer/FluentPlayer'))
const BitCrm = lazy(() => import('./BitCrm/BitCrm'))
const Wsms = lazy(() => import('./Wsms/Wsms'))
Expand Down Expand Up @@ -1741,6 +1742,15 @@ const NewIntegs = memo(({ integUrlName, allIntegURL, flow, setFlow }) => {
setFlow={setFlow}
/>
)
case 'NextCrm':
return (
<NextCrm
allIntegURL={allIntegURL}
formFields={flow?.triggerData?.fields}
flow={flow}
setFlow={setFlow}
/>
)
case 'FluentCart':
return (
<FluentCart
Expand Down
Loading