![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/mautic.corals.io/plugins/MauticCrmBundle/Api/ |
<?php namespace MauticPlugin\MauticCrmBundle\Api; use Mautic\PluginBundle\Exception\ApiErrorException; use MauticPlugin\MauticCrmBundle\Integration\SugarcrmIntegration; /** * @property SugarcrmIntegration $integration */ class SugarcrmApi extends CrmApi { protected $object = 'Leads'; /** * @param array $data * @param string $method * * @return mixed|string * * @throws ApiErrorException */ public function request($sMethod, $data = [], $method = 'GET', $object = null) { if (!$object) { $object = $this->object; } $tokenData = $this->integration->getKeys(); if ('6' == $tokenData['version']) { $request_url = sprintf('%s/service/v4_1/rest.php', $tokenData['sugarcrm_url']); $sessionParams = [ 'session' => $tokenData['id'], ]; if (!isset($data['module_names'])) { $sessionParams['module_name'] = $object; } // Making sure that module_name is the second value of the array else { $sessionParams['module_names'] = $data['module_names']; } $sessionParams = array_merge($sessionParams, $data); $parameters = [ 'method' => $sMethod, 'input_type' => 'JSON', 'response_type' => 'JSON', 'rest_data' => json_encode($sessionParams), ]; $response = $this->integration->makeRequest($request_url, $parameters, $method); if (is_array($response) && !empty($response['name']) && !empty($response['number'])) { throw new ApiErrorException($response['name'].' '.$object.' '.$sMethod.' '.$method); } else { return $response; } } else { $request_url = sprintf('%s/rest/v10/%s', $tokenData['sugarcrm_url'], $sMethod); $settings = [ 'request_timeout' => 50, 'encode_parameters' => 'json', ]; $response = $this->integration->makeRequest($request_url, $data, $method, $settings); if (isset($response['error'])) { throw new ApiErrorException($response['error_message'] ?? $response['error']['message'], ('invalid_grant' == $response['error']) ? 1 : 500); } return $response; } } /** * @return mixed|string * * @throws ApiErrorException */ public function getLeadFields($object = null) { if (!$object) { $object = $this->object; } if ('company' == $object) { $object = 'Accounts'; // sugarCRM object name } elseif ('lead' == $object || 'Lead' == $object) { $object = 'Leads'; } elseif ('contact' == $object || 'Contact' == $object) { $object = 'Contacts'; } $tokenData = $this->integration->getKeys(); if ('6' == $tokenData['version']) { return $this->request('get_module_fields', [], 'GET', $object); } else { $parameters = [ 'module_filter' => $object, 'type_filter' => 'modules', ]; $response = $this->request('metadata', $parameters, 'GET', $object); return $response['modules'][$object]; } } /** * @return array * * @throws ApiErrorException */ public function createLead(array $fields, $lead) { $tokenData = $this->integration->getKeys(); $createdLeadData = []; // search for Sugar id in mautic records first to avoid making an API call if (is_object($lead)) { $sugarLeadRecords = $this->integration->getSugarLeadId($lead); } if ('6' == $tokenData['version']) { // if not found then go ahead and make an API call to find all the records with that email if (isset($fields['email1']) && empty($sugarLeadRecords)) { $sLeads = $this->getLeads(['email' => $fields['email1'], 'offset' => 0, 'max_results' => 1000], 'Leads'); $sugarLeadRecords = $sLeads['entry_list'] ?? []; } $leadFields = []; foreach ($fields as $name => $value) { if ('id' != $name) { $leadFields[] = [ 'name' => $name, 'value' => $value, ]; } } $parameters = [ 'name_value_list' => $leadFields, ]; if (!empty($sugarLeadRecords)) { foreach ($sugarLeadRecords as $sLeadRecord) { $localParam = $parameters; $sugarLeadId = ($sLeadRecord['integration_entity_id'] ?? $sLeadRecord['id']); $sugarObject = ($sLeadRecord['integration_entity'] ?? 'Leads'); // update the converted contact if found and not the Lead if (isset($sLeadRecord['contact_id']) && null != $sLeadRecord['contact_id'] && '' != $sLeadRecord['contact_id']) { unset($fields['Company']); // because this record is not in the Contact object. $localParams['name_value_list'][] = ['name' => 'id', 'value' => $sLeadRecord['contact_id']]; $createdLeadData[] = $this->request('set_entry', $localParams, 'POST', 'Contacts'); } else { $localParams['name_value_list'][] = ['name' => 'id', 'value' => $sugarLeadId]; $createdLeadData[] = $this->request('set_entry', $localParams, 'POST', $sugarObject); } } } else { $createdLeadData = $this->request('set_entry', $parameters, 'POST', 'Leads'); } // $createdLeadData[] = $this->request('set_entry', $parameters, 'POST'); } else { // if not found then go ahead and make an API call to find all the records with that email if (isset($fields['email1']) && empty($sugarLeadRecords)) { $sLeads = $this->getLeads(['email' => $fields['email1'], 'offset' => 0, 'max_results' => 1000], 'Leads'); $sugarLeadRecords = $sLeads['records']; } unset($fields['id']); if (!empty($sugarLeadRecords)) { foreach ($sugarLeadRecords as $sLeadRecord) { $sugarLeadId = ($sLeadRecord['integration_entity_id'] ?? $sLeadRecord['id']); $sugarObject = ($sLeadRecord['integration_entity'] ?? 'Leads'); // update the converted contact if found and not the Lead $config = $this->integration->mergeConfigToFeatureSettings(); $fieldsToUpdateInSugar = isset($config['update_mautic']) ? array_keys($config['update_mautic'], 1) : []; if (isset($sLeadRecord['contact_id']) && null != $sLeadRecord['contact_id'] && '' != $sLeadRecord['contact_id']) { unset($fields['Company']); // because this record is not in the Contact object $fieldsToUpdateInContactsSugar = $this->integration->cleanSugarData($config, $fieldsToUpdateInSugar, 'Contacts'); $contactSugarFields = array_diff_key($fields, $fieldsToUpdateInContactsSugar); $createdLeadData[] = $this->request("Contacts/$sugarLeadId", $contactSugarFields, 'PUT', 'Contacts'); } else { $fieldsToUpdateInLeadsSugar = $this->integration->cleanSugarData($config, $fieldsToUpdateInSugar, 'Leads'); $leadSugarFields = array_diff_key($fields, $fieldsToUpdateInLeadsSugar); $createdLeadData[] = $this->request("$sugarObject/$sugarLeadId", $leadSugarFields, 'PUT', $sugarObject); } } } else { $createdLeadData = $this->request('Leads', $fields, 'POST', 'Leads'); } // $createdLeadData[] = $this->request('set_entry', $fields, 'POST', 'Leads'); } return $createdLeadData; } /** * @return array * * @throws ApiErrorException */ public function syncLeadsToSugar(array $data) { $tokenData = $this->integration->getKeys(); $object = $this->object; if ('6' == $tokenData['version']) { $leadFieldsList = []; $response = []; foreach ($data as $object => $leadFieldsList) { $parameters = [ 'name_value_lists' => $leadFieldsList, ]; $resp = $this->request('set_entries', $parameters, 'POST', $object); if (!empty($resp)) { foreach ($leadFieldsList as $k => $leadFields) { $fields = []; foreach ($leadFields as $item) { $fields[$item['name']] = $item['value']; } if (isset($resp['ids'])) { $result = ['reference_id' => $fields['reference_id'], 'id' => $resp['ids'][$k], 'new' => !isset($fields['id']), 'ko' => false, ]; } if (isset($resp['error'])) { $result['ko'] = true; $result['error'] = $resp['error']['message']; } if (isset($fields['id']) && $fields['id'] != $resp['ids'][$k]) { $result['ko'] = true; $result['error'] = 'Returned ID does not correspond to input id'; } $response[] = $result; } } } return $response; } else { $leadFieldsList = []; $response = []; // body is prepared for Sugar6. Translate it to sugar 7 $reference_ids = []; foreach ($data as $object => $leadFieldsList) { $requests = []; $all_ids = []; foreach ($leadFieldsList as $body) { $fields = []; $ids = []; foreach ($body as $field) { $fields[$field['name']] = $field['value']; } $request = []; if (isset($fields['id'])) { $ids['id'] = $fields['id']; // Update record $sugarLeadId = $fields['id']; unset($fields['id']); $request['method'] = 'PUT'; $request['url'] = "/v10/$object/$sugarLeadId"; $request['data'] = $fields; } else { // Create record $request['data'] = $fields; $request['url'] = '/v10/'.$object; $request['method'] = 'POST'; } $requests[] = $request; $ids['reference_id'] = $fields['reference_id']; $all_ids[] = $ids; } $parameters = [ 'requests' => $requests, ]; $resp = $this->request('bulk', $parameters, 'POST', $object); if (!empty($resp)) { foreach ($resp as $k => $leadFields) { $fields = $leadFields['contents']; if (200 != $leadFields['status']) { $result = ['ko' => true, 'error' => $leadFields['error'].' '.$leadFields['error_message'], ]; } else { $result = ['reference_id' => $all_ids[$k]['reference_id'], 'id' => $fields['id'], 'new' => !isset($all_ids[$k]['id']), 'ko' => false, ]; if (isset($all_ids[$k]['id']) && $fields['id'] != $all_ids[$k]['id']) { $result['ko'] = true; $result['error'] = 'Returned ID does not correspond to input id'; } } $response[] = $result; } } } return $response; } } /** * @param $object * TODO 7.x * * @return array|mixed|string */ public function createLeadActivity(array $activity, $object) { $tokenData = $this->integration->getKeys(); // 1st : set_entries to return name_value_lists (array of arrays of name/value) $set_name_value_lists = []; // set relationship $module_names = []; // Contacts or Leads $module_ids = []; // Contacts or leads ids $link_field_names = []; // Array of mtc_webactivities_contacts or mtc_webactivities_leads $related_ids = []; // Array of arrays of web activity array $name_value_lists = []; // array of empty arrays $delete_array = []; // Array of 0 // set_relationships $s7_records = []; // Send activities and get back sugar activities id if (!empty($activity)) { foreach ($activity as $sugarId => $records) { foreach ($records['records'] as $record) { $rec = []; $rec[] = ['name' => 'name', 'value' => $record['name']]; $rec[] = ['name' => 'description', 'value' => $record['description']]; $rec[] = ['name' => 'url', 'value' => $records['leadUrl']]; $rec[] = ['name' => 'date_entered', 'value' => $record['dateAdded']->format('c')]; $rec[] = ['name' => 'reference_id', 'value' => $record['id'].'-'.$sugarId]; if ('Contacts' == $object) { $rec[] = ['name' => 'contact_id_c', 'value' => $sugarId]; } else { $rec[] = ['name' => 'lead_id_c', 'value' => $sugarId]; } $set_name_value_lists[] = $rec; // Sugar 6 $s7_record = []; foreach ($rec as $r) { $s7_record[$r['name']] = $r['value']; } $s7_records[] = $s7_record; } } $parameters = [ 'name_value_lists' => $set_name_value_lists, ]; if ('6' == $tokenData['version']) { $resp = $this->request('set_entries', $parameters, 'POST', 'mtc_WebActivities'); } else { $requests = []; foreach ($s7_records as $fields) { // Create record $request['data'] = $fields; $request['url'] = '/v10/mtc_WebActivities'; $request['method'] = 'POST'; $requests[] = $request; } $parameters = [ 'requests' => $requests, ]; $resp = $this->request('bulk', $parameters, 'POST', 'bulk'); } if ('6' == $tokenData['version']) { // Send sugar relationsips if (!empty($resp)) { $nbLeads = 0; $nbAct = 0; $idList = []; foreach ($activity as $sugarId => $records) { $related_ids_row = []; $module_names[] = $object; $module_ids[] = $sugarId; if ('Contacts' == $object) { $link_field_names[] = 'mtc_webactivities_contacts'; } else { $link_field_names[] = 'mtc_webactivities_leads'; } ++$nbLeads; foreach ($records['records'] as $record) { $name_value_lists[] = []; $delete_array[] = 0; $idList[] = $sugarId; $related_ids_row[] = $resp['ids'][$nbAct]; ++$nbAct; } $related_ids[] = $related_ids_row; } $parameters = [ 'module_names' => $module_names, // Contacts or Leads 'module_ids' => $module_ids, // Contacts or leads ids 'link_field_names' => $link_field_names, // Array of mtc_webactivities_contacts or mtc_webactivities_leads 'related_ids' => $related_ids, // Array of arrays of web activity array 'name_value_lists' => $name_value_lists, // array of empty arrays 'delete_array' => $delete_array, // Array of 0 ]; $resp2 = $this->request('set_relationships', $parameters, 'POST', $object); } } else { // Sugar 7 set relationship if (!empty($resp)) { $nbAct = 0; foreach ($activity as $sugarId => $records) { if ('Contacts' == $object) { $link_field_name = 'mtc_webactivities_contacts'; } else { $link_field_name = 'mtc_webactivities_leads'; } foreach ($records['records'] as $record) { if (!isset($resp[$nbAct]['contents']['id'])) { continue; } // current Web activity was not created $wa_id = $resp[$nbAct]['contents']['id']; $resp2 = $this->request("mtc_WebActivities/$wa_id/link/$link_field_name/$sugarId", [], 'POST'); ++$nbAct; } } } } return []; } } public function getEmailBySugarUserId($query = null) { $tokenData = $this->integration->getKeys(); if ('6' == $tokenData['version']) { if (isset($query['emails'])) { $q = " users.id IN (SELECT bean_id FROM email_addr_bean_rel eabr JOIN email_addresses ea ON (eabr.email_address_id = ea.id) WHERE bean_module = 'Users' AND ea.email_address IN ('".implode("','", $query['emails'])."') AND eabr.deleted=0) "; } if (isset($query['ids'])) { $q = " users.id IN ('".implode("','", $query['ids'])."') "; } $data = ['filter' => 'all']; $fields = ['id', 'email1']; $parameters = [ 'query' => $q, 'order_by' => '', 'offset' => 0, 'select_fields' => $fields, 'link_name_to_fields_array' => [/* TO BE MODIFIED */ ], 'max_results' => 1000, 'deleted' => 0, 'favorites' => false, ]; $data = $this->request('get_entry_list', $parameters, 'GET', 'Users'); if (isset($query['type']) && 'BYEMAIL' == $query['type']) { $type = 'BYEMAIL'; } else { $type = 'BYID'; } $res = []; if (isset($data['entry_list'])) { foreach ($data['entry_list'] as $record) { $fields = []; $fields['id'] = $record['id']; foreach ($record['name_value_list'] as $item) { $fields[$item['name']] = $item['value']; } if ('BYID' == $type) { $res[$fields['id']] = $fields['email1']; } elseif (isset($fields['email1'])) { $res[$fields['email1']] = $fields['id']; } elseif ('BYEMAIL' == $type && !isset($fields['email1'])) { $res[$query['emails'][0]] = $fields['id']; } } } return $res; } else { // TODO if (isset($query['emails'])) { $filter[] = ['email_addresses.email_address' => ['$in' => $query['emails']]]; $filter[] = ['deleted' => '0']; } if (isset($query['ids'])) { $filter[] = ['id' => ['$in' => $query['ids']]]; } $data = ['filter' => 'all']; $fields = ['id', 'email1', 'email']; $parameters = [ 'filter' => [['$and' => $filter]], 'offset' => 0, 'fields' => implode(',', $fields), 'max_num' => 1000, // 'deleted' => 0, // 'favorites' => false, ]; $data = $this->request('Users/filter', $parameters, 'GET', 'Users'); if (isset($query['type']) && 'BYEMAIL' == $query['type']) { $type = 'BYEMAIL'; } else { $type = 'BYID'; } $res = []; if (isset($data['records'])) { foreach ($data['records'] as $record) { if (isset($record['email'][0]['email_address']) && '' != $record['email'][0]['email_address']) { $found_email = $record['email'][0]['email_address']; if (isset($record['name_value_list'])) { foreach ($record['name_value_list'] as $email) { if ('' != $email['email_address'] && 1 == $email['primary_address']) { $found_email = $email; break; } } } if ('BYID' == $type) { $res[$record['id']] = $found_email; } else { $res[$found_email] = $record['id']; } } } } return $res; } } public function getIdBySugarEmail($query = null) { if (null == $query) { $query = ['type' => 'BYEMAIL']; } else { $query['type'] = 'BYEMAIL'; } return $this->getEmailBySugarUserId($query); } /** * Get SugarCRM leads. * * @param array $query * @param string $object * * @return mixed */ public function getLeads($query, $object) { $tokenData = $this->integration->getKeys(); $availableFields = $this->integration->getIntegrationSettings()->getFeatureSettings(); switch ($object) { case 'company': case 'Account': case 'Accounts': $fields = array_keys(array_filter($availableFields['companyFields'])); break; default: $mixedFields = array_filter($availableFields['leadFields']); $fields = []; $object = ('Contacts' == $object) ? 'Contacts' : 'Leads'; foreach ($mixedFields as $sugarField => $mField) { if (str_contains($sugarField, '__'.$object)) { $fields[] = str_replace('__'.$object, '', $sugarField); } if (str_contains($sugarField, '-'.$object)) { $fields[] = str_replace('-'.$object, '', $sugarField); } } } if ('6' == $tokenData['version']) { $result = []; if (!empty($fields)) { $q = ''; $qry = []; if (isset($query['start'])) { $qry[] = ' '.strtolower($object).".date_modified >= '".$query['start']."' "; } if (isset($query['end'])) { $qry[] = ' '.strtolower($object).".date_modified <= '".$query['end']."' "; } if (isset($query['email'])) { $qry[] = " leads.id IN (SELECT bean_id FROM email_addr_bean_rel eabr JOIN email_addresses ea ON (eabr.email_address_id = ea.id) WHERE bean_module = 'Leads' AND ea.email_address = '".$query['email']."' AND eabr.deleted=0) "; $fields[] = 'contact_id'; } if (isset($query['checkemail'])) { $qry[] = ' leads.deleted=0 '; $qry[] = " leads.id IN (SELECT bean_id FROM email_addr_bean_rel eabr JOIN email_addresses ea ON (eabr.email_address_id = ea.id) WHERE bean_module = 'Leads' AND ea.email_address IN ('".implode("','", $query['checkemail'])."') AND eabr.deleted=0) "; $fields[] = 'contact_id'; $fields[] = 'deleted'; } if (isset($query['checkemail_contacts'])) { $qry[] = ' contacts.deleted=0 '; $qry[] = " contacts.id IN (SELECT bean_id FROM email_addr_bean_rel eabr JOIN email_addresses ea ON (eabr.email_address_id = ea.id) WHERE bean_module = 'Contacts' AND ea.email_address IN ('".implode("','", $query['checkemail_contacts'])."') AND eabr.deleted=0) "; $fields[] = 'deleted'; } $q = implode('AND', $qry); $fields[] = 'id'; $fields[] = 'date_modified'; $fields[] = 'date_entered'; $fields[] = 'assigned_user_id'; $fields[] = 'email1'; if ('Accounts' != $object) { $fields[] = 'account_id'; } $parameters = [ 'query' => $q, 'order_by' => '', 'offset' => $query['offset'], 'select_fields' => $fields, 'link_name_to_fields_array' => [/* TO BE MODIFIED */ [ 'name' => 'email_addresses', 'value' => [ 'email_address', 'opt_out', 'primary_address', ], ], ], 'max_results' => $query['max_results'], 'deleted' => 0, 'favorites' => false, ]; return $this->request('get_entry_list', $parameters, 'GET', $object); } } else { if (!empty($fields)) { $q = ''; $qry = []; $filter = []; if (isset($query['start'])) { $filter[] = ['date_modified' => ['$gte' => $query['start']]]; // $qry[] = ' '.strtolower($object).".date_modified >= '".$query['start']."' "; } if (isset($query['end'])) { $filter[] = ['date_modified' => ['$lte' => $query['end']]]; // $qry[] = ' '.strtolower($object).".date_modified <= '".$query['end']."' "; } if (isset($query['email'])) { $filter[] = ['email' => ['$equals' => $query['email']]]; // $qry[] = " leads.id IN (SELECT bean_id FROM email_addr_bean_rel eabr JOIN email_addresses ea ON (eabr.email_address_id = ea.id) WHERE bean_module = 'Leads' AND ea.email_address = '".$query['email']."' AND eabr.deleted=0) "; $fields[] = 'contact_id'; } if (isset($query['checkemail'])) { $filter[] = ['email' => ['$in' => $query['checkemail']]]; $filter[] = ['deleted' => '0']; $fields = []; // Do not need previous fields $fields[] = 'contact_id'; $fields[] = 'deleted'; } if (isset($query['checkemail_contacts'])) { $filter[] = ['email' => ['$in' => $query['checkemail_contacts']]]; $filter[] = ['deleted' => '0']; $fields = []; // Do not need previous fields $fields[] = 'deleted'; } $fields[] = 'id'; $fields[] = 'date_modified'; $fields[] = 'date_entered'; $fields[] = 'assigned_user_id'; $fields[] = 'email1'; if ('Accounts' != $object) { $fields[] = 'account_id'; } // $filter_args = ['filter' => [['$and' => $filter]]]; // $fields_arg = implode(',', $fields); $parameters = [ // 'order_by' => '', 'filter' => [['$and' => $filter]], 'offset' => $query['offset'], 'fields' => implode(',', $fields), 'max_num' => $query['max_results'], // 'deleted' => 0, // 'favorites' => false, ]; return $this->request("$object/filter", $parameters, 'GET', $object); } } } }