2021-04-28 20:10:26 +02:00

2202 lines
81 KiB
PHP

<?php
/*************************************
* SPDX-FileCopyrightText: 2009-2020 Vtenext S.r.l. <info@vtenext.com>
* SPDX-License-Identifier: AGPL-3.0-only
************************************/
// crmv@161554 cmrv@163697
require_once('include/BaseClasses.php');
require_once('modules/Morphsuit/utils/RSA/Crypt/Random.php');
require_once('vtlib/Vtecrm/SettingsBlock.php');
require_once('vtlib/Vtecrm/SettingsField.php');
require_once('modules/Update/Update.php');
class GDPRWS extends SDKExtendableUniqueClass {
public static $supportedModules = array('Contacts', 'Leads');
public $availableFields = array(
'Contacts' => array(
'salutation', 'firstname', 'phone', 'lastname', 'mobile', 'homephone',
'otherphone', 'title', 'fax', 'department', 'birthday', 'assistant',
'assistantphone', 'mailingstreet', 'mailingcity', 'mailingzip', 'mailingstate',
'mailingcountry', 'mailingpobox', 'otherstreet', 'othercity', 'otherzip',
'otherstate', 'othercountry', 'otherpobox',
),
'Leads' => array(
'firstname', 'lastname', 'mobile', 'company', 'designation', 'website', 'annualrevenue',
'noofemployees', 'lane', 'city', 'code', 'state', 'country', 'pobox'
),
);
public $gdprFields = array(
'gdpr_privacypolicy', 'gdpr_personal_data', 'gdpr_marketing', 'gdpr_thirdparties',
'gdpr_profiling', 'gdpr_restricted', 'gdpr_notifychange',
);
public $emailFields = array();
protected $cid = null;
protected $cidData = null;
protected $authTable = null;
protected $logTable = null;
protected $confirmTable = null;
protected $senderName = null;
protected $senderEmail = null;
protected $templates = null;
protected $noconfirm_deletion_months = null;
public $default_noconfirm_deletion_months = 12;
public function __construct() {
global $table_prefix;
$this->emailFields = array(
'Accounts' => array('fieldname' => 'email1', 'tablename' => $table_prefix.'_account', 'columnname' => 'email1'),
'Contacts' => array('fieldname' => 'email', 'tablename' => $table_prefix.'_contactdetails', 'columnname' => 'email'),
'Leads' => array('fieldname' => 'email', 'tablename' => $table_prefix.'_leaddetails', 'columnname' => 'email'),
);
$this->authTable = $table_prefix.'_gdpr_auth';
$this->logTable = $table_prefix.'_gdpr_log';
$this->confirmTable = $table_prefix.'_gdpr_confirm_queue';
}
public function install() {
global $adb, $table_prefix, $site_URL, $HELPDESK_SUPPORT_EMAIL_ID, $HELPDESK_SUPPORT_NAME;
$vteProp = VTEProperties::getInstance();
$BU = BusinessUnit::getInstance();
$businessList = $BU->getBusinessList();
$prop = $vteProp->get('services.gdpr.general_settings');
if ($prop === null) {
$generalSettings = array();
$generalSettings['default_business'] = $businessList[0]['organizationid'];
$vteProp->set('services.gdpr.general_settings', $generalSettings);
}
foreach ($businessList as $business) {
$bid = $business['organizationid'];
$prop = $vteProp->get("services.gdpr.config.business.{$bid}");
if ($prop === null) {
$config = array();
$config['webservice_endpoint'] = $site_URL;
$user = Users::getActiveAdminUser();
$username = $user->column_fields['user_name'];
$accesskey = $user->column_fields['accesskey'];
$config['webservice_username'] = $username;
$config['webservice_accesskey'] = $accesskey;
$config['default_language'] = 'en';
$config['sender_name'] = $HELPDESK_SUPPORT_NAME;
$config['sender_email'] = $HELPDESK_SUPPORT_EMAIL_ID;
$config['noconfirm_deletion_months'] = $this->default_noconfirm_deletion_months;
$logo = '';
$companyDetailsResult = $adb->pquery("SELECT logoname FROM {$table_prefix}_organizationdetails WHERE organizationid = ?", array($bid));
if ($companyDetailsResult && $adb->num_rows($companyDetailsResult)) {
$companyDetails = $adb->fetchByAssoc($companyDetailsResult, -1, false);
$logo = $companyDetails['logoname'];
$logo = $site_URL.'/storage/logo/'.$logo;
}
$config['website_logo'] = $logo;
$vteProp->set("services.gdpr.config.business.{$bid}", $config);
}
$prop = $vteProp->get("services.gdpr.templates.business.{$bid}");
if ($prop === null) {
$templates = array();
$templates['support_request_template'] = $this->createTemplateEmail('support_request_template', 'GDPR - Support request template - EN', 'New support request', 'Template used for support request', 'en');
$this->createTemplateEmail('support_request_template', 'GDPR - Template richiesta supporto - IT', 'Nuova richiesta di supporto', 'Template utilizzato per le richieste di supporto', 'it');
$templates['access_template'] = $this->createTemplateEmail('access_template', 'GDPR - Access template - EN', 'Access to manage your contact', 'Template used for sending the access details to the contact', 'en');
$this->createTemplateEmail('access_template', 'GDPR - Template accesso - IT', 'Accesso per la gestione del tuo contatto', 'Template utilizzato per l\'invio dell\'accesso al contatto', 'it');
$templates['confirm_update_template'] = $this->createTemplateEmail('confirm_update_template', 'GDPR - Confirm update template - EN', 'Confirm your contact\'s changes', 'Template used for confirming the contact update', 'en');
$this->createTemplateEmail('confirm_update_template', 'GDPR - Template conferma modifiche - IT', 'Conferma le modifiche del tuo contatto', 'Template utilizzato per la conferma dell\'aggiornamento del contatto', 'it');
$templates['contact_updated_template'] = $this->createTemplateEmail('contact_updated_template', 'GDPR - Contact updated template - EN', 'Contact update', 'Template used for sending update notifications to the contact', 'en');
$this->createTemplateEmail('contact_updated_template', 'GDPR - Template dati contatto aggiornati - IT', 'Aggiornamento contatto', 'Template utilizzato per inviare le notifiche di cambio dati al contatto', 'it');
$vteProp->set("services.gdpr.templates.business.{$bid}", $templates);
}
$PPU = PrivacyPolicyUtils::getInstance();
$ok = $PPU->save($bid, 'Company', file_get_contents('include/utils/GDPRWS/templates/privacy_policy.html'));
}
$this->checkTables();
$this->createTemplateEmail('gdpr_verify_newsletter', 'GDPR - Default newsletter - EN', 'Verify your contact', 'The default template used for sending GDPR newsletter', 'en', 'Newsletter');
$this->createTemplateEmail('gdpr_verify_newsletter', 'GDPR - Default newsletter - IT', 'Verifica il tuo contatto', 'Template di default utilizzato per l\'invio della newsletter GDPR', 'it', 'Newsletter');
$translations = array();
$gdprModules = self::$supportedModules;
$GDPRFields = array('gdpr_privacypolicy', 'gdpr_personal_data', 'gdpr_marketing', 'gdpr_thirdparties', 'gdpr_profiling', 'gdpr_restricted', 'gdpr_notifychange', 'gdpr_deleted');
foreach ($gdprModules as $module) {
$moduleInstance = Vtecrm_Module::getInstance($module);
$blockInstance = Vtecrm_Block::getInstance('LBL_GDPR_INFORMATION', $moduleInstance);
if (!$blockInstance) {
$blockInstance = new Vtecrm_Block();
$blockInstance->label = 'LBL_GDPR_INFORMATION';
$moduleInstance->addBlock($blockInstance);
}
$fields = array();
foreach ($GDPRFields as $field) {
$label = 'LBL_'.strtoupper($field);
$fields[] = array('module' => $module, 'block' => 'LBL_GDPR_INFORMATION', 'name' => $field, 'label' => $label, 'uitype' => '56', 'readonly' => '99', 'columntype' => 'CHAR(1)', 'typeofdata' => 'C~O', 'quickcreate' => 1); // crmv@187404
$fields[] = array('module' => $module, 'block' => 'LBL_GDPR_INFORMATION', 'name' => $field.'_checkedtime', 'label' => $label.'_CHECKEDTIME', 'uitype' => '1', 'readonly' => '99', 'columntype' => 'DATETIME', 'typeofdata' => 'V~O', 'quickcreate' => 1); // crmv@187404
$fields[] = array('module' => $module, 'block' => 'LBL_GDPR_INFORMATION', 'name' => $field.'_remote_addr', 'label' => $label.'_REMOTE_ADDRESS', 'uitype' => '1', 'readonly' => '99', 'columntype' => 'C(45)', 'typeofdata' => 'V~O', 'quickcreate' => 1); // crmv@187404
}
$fields[] = array('module' => $module, 'block' => 'LBL_GDPR_INFORMATION', 'name' => 'gdpr_sentdate', 'label' => 'LBL_GDPR_SENTTIME', 'uitype' => '1', 'readonly' => '99', 'columntype' => 'DATETIME', 'typeofdata' => 'V~O', 'quickcreate' => 1); // crmv@187404
Update::create_fields($fields);
$translations[$module]['it_it'] = array(
'LBL_GDPR_INFORMATION' => 'Informazioni GDPR',
'LBL_GDPR_PRIVACYPOLICY' => 'Visione Informativa',
'LBL_GDPR_PRIVACYPOLICY_CHECKEDTIME' => 'Data Visione Informativa',
'LBL_GDPR_PRIVACYPOLICY_REMOTE_ADDRESS' => 'Indirizzo IP Visione Informativa',
'LBL_GDPR_PERSONAL_DATA' => 'Consenso Dati Personali',
'LBL_GDPR_PERSONAL_DATA_CHECKEDTIME' => 'Data Consenso Dati Personali',
'LBL_GDPR_PERSONAL_DATA_REMOTE_ADDRESS' => 'Indirizzo IP Dati Personali',
'LBL_GDPR_MARKETING' => 'Consenso Marketing',
'LBL_GDPR_MARKETING_CHECKEDTIME' => 'Data Consenso Marketing',
'LBL_GDPR_MARKETING_REMOTE_ADDRESS' => 'Indirizzo IP Consenso Marketing',
'LBL_GDPR_THIRDPARTIES' => 'Consenso Terze Parti',
'LBL_GDPR_THIRDPARTIES_CHECKEDTIME' => 'Data Consenso Terze Parti',
'LBL_GDPR_THIRDPARTIES_REMOTE_ADDRESS' => 'Indirizzo IP Consenso Terze Parti',
'LBL_GDPR_PROFILING' => 'Consenso Profilazione',
'LBL_GDPR_PROFILING_CHECKEDTIME' => 'Data Consenso Profilazione',
'LBL_GDPR_PROFILING_REMOTE_ADDRESS' => 'Indirizzo IP Consenso Profilazione',
'LBL_GDPR_RESTRICTED' => 'Consenso Comunicazione Dati Ambiti Informativa',
'LBL_GDPR_RESTRICTED_CHECKEDTIME' => 'Data Consenso Comunicazione Dati Ambiti Informativa',
'LBL_GDPR_RESTRICTED_REMOTE_ADDRESS' => 'Indirizzo IP Consenso Comunicazione Dati Ambiti Informativa',
'LBL_GDPR_NOTIFYCHANGE' => 'Avvisa Cambio Dati',
'LBL_GDPR_NOTIFYCHANGE_CHECKEDTIME' => 'Data Consenso Avvisa Cambio Dati',
'LBL_GDPR_NOTIFYCHANGE_REMOTE_ADDRESS' => 'Indirizzo IP Avvisa Cambio Dati',
'LBL_GDPR_DELETED' => 'Eliminato',
'LBL_GDPR_DELETED_CHECKEDTIME' => 'Data Eliminazione',
'LBL_GDPR_DELETED_REMOTE_ADDRESS' => 'Indirizzo IP Eliminazione',
'LBL_GDPR_SENTTIME' => 'Data Invio GDPR',
);
$translations[$module]['en_us'] = array(
'LBL_GDPR_INFORMATION' => 'GDPR Information',
'LBL_GDPR_PRIVACYPOLICY' => 'Privacy Policy',
'LBL_GDPR_PRIVACYPOLICY_CHECKEDTIME' => 'Privacy Policy - Date',
'LBL_GDPR_PRIVACYPOLICY_REMOTE_ADDRESS' => 'Privacy Policy - IP Address',
'LBL_GDPR_PERSONAL_DATA' => 'Consent to Personal Data',
'LBL_GDPR_PERSONAL_DATA_CHECKEDTIME' => 'Consent to Personal Data - Date',
'LBL_GDPR_PERSONAL_DATA_REMOTE_ADDRESS' => 'Consent to Personal Data - IP Address',
'LBL_GDPR_MARKETING' => 'Consent to Marketing',
'LBL_GDPR_MARKETING_CHECKEDTIME' => 'Consent to Marketing - Date',
'LBL_GDPR_MARKETING_REMOTE_ADDRESS' => 'Consent to Marketing - IP Address',
'LBL_GDPR_THIRDPARTIES' => 'Consent to Third Parties',
'LBL_GDPR_THIRDPARTIES_CHECKEDTIME' => 'Consent to Third Parties - Date',
'LBL_GDPR_THIRDPARTIES_REMOTE_ADDRESS' => 'Consent to Third Parties - IP Address',
'LBL_GDPR_PROFILING' => 'Consent to Profiling',
'LBL_GDPR_PROFILING_CHECKEDTIME' => 'Consent to Profiling - Date',
'LBL_GDPR_PROFILING_REMOTE_ADDRESS' => 'Consent to Profiling - IP Address',
'LBL_GDPR_RESTRICTED' => 'Consent only to specified institutions',
'LBL_GDPR_RESTRICTED_CHECKEDTIME' => 'Consent only to specified institutions - Date',
'LBL_GDPR_RESTRICTED_REMOTE_ADDRESS' => 'Consent only to specified institutions - IP Address',
'LBL_GDPR_NOTIFYCHANGE' => 'Notify contact changes',
'LBL_GDPR_NOTIFYCHANGE_CHECKEDTIME' => 'Notify contact changes - Date',
'LBL_GDPR_NOTIFYCHANGE_REMOTE_ADDRESS' => 'Notify contact changes - IP Address',
'LBL_GDPR_DELETED' => 'Deleted',
'LBL_GDPR_DELETED_CHECKEDTIME' => 'Deleted - Date',
'LBL_GDPR_DELETED_REMOTE_ADDRESS' => 'Deleted - IP Address',
'LBL_GDPR_SENTTIME' => 'GDPR Sent Date',
);
}
$block = Vtecrm_SettingsBlock::getInstance('LBL_COMMUNICATION_TEMPLATES');
$res = $adb->pquery("SELECT fieldid FROM {$table_prefix}_settings_field WHERE name = ?", array('LBL_GDPR'));
if ($block && $res && $adb->num_rows($res) == 0) {
$field = new Vtecrm_SettingsField();
$field->name = 'LBL_GDPR';
$field->iconpath = 'themes/images/PrivacySettings.png';
$field->description = 'LBL_GDPR_DESCRIPTION';
$field->linkto = 'index.php?module=Settings&action=GDPRConfig&parenttab=Settings';
$block->addField($field);
}
$result = $adb->pquery("SELECT campaigntype FROM {$table_prefix}_campaigntype WHERE campaigntype = ?", array('GDPR'));
if ($result && $adb->num_rows($result) < 1) {
$field = Vtecrm_Field::getInstance('campaigntype', Vtecrm_Module::getInstance('Campaigns'));
if ($field) {
$field->setPicklistValues(array('GDPR'));
}
}
$translations['Newsletter'] = array(
'it_it' => array(
'LBL_GDPR_AND_PRICAY_POLICY' => 'GDPR e informativa privacy',
'LBL_GDPR_VERIFY_LINK' => 'GDPR Accesso - Link di verifica',
'LBL_GDPR_ACCESS_LINK' => 'GDPR Accesso - Link di accesso',
'LBL_GDPR_CONFIRM_LINK' => 'GDPR Aggiornamento - Link di conferma',
'LBL_GDPR_SUPPORT_REQUEST_SENDER' => 'GDPR Richiesta supporto - Mittente',
'LBL_GDPR_SUPPORT_REQUEST_SUBJECT' => 'GDPR Richiesta supporto - Oggetto',
'LBL_GDPR_SUPPORT_REQUEST_DESC' => 'GDPR Richiesta supporto - Descrizione',
),
'en_us' => array(
'LBL_GDPR_AND_PRICAY_POLICY' => 'GDPR and privacy policy',
'LBL_GDPR_VERIFY_LINK' => 'GDPR Access - Verify link',
'LBL_GDPR_ACCESS_LINK' => 'GDPR Access - Access link',
'LBL_GDPR_CONFIRM_LINK' => 'GDPR Update - Confirm link',
'LBL_GDPR_SUPPORT_REQUEST_SENDER' => 'GDPR Support Request - Sender',
'LBL_GDPR_SUPPORT_REQUEST_SUBJECT' => 'GDPR Support Request - Subject',
'LBL_GDPR_SUPPORT_REQUEST_DESC' => 'GDPR Support Request - Description',
),
);
$translations['APP_STRINGS'] = array(
'it_it' => array(
'LBL_GDPR_ANONYMIZE' => 'Anonimizza',
),
'en_us' => array(
'LBL_GDPR_ANONYMIZE' => 'Anonymize',
),
);
$translations['Settings'] = array(
'it_it' => array(
'GDPR' => 'GDPR',
'LBL_GDPR' => 'GDPR',
'LBL_GDPR_DESCRIPTION' => 'Configura le impostazioni del GDPR',
'LBL_WEBSERVICE' => 'Webservice',
'LBL_WEBSERVICE_ENDPOINT' => 'Webservice endpoint',
'LBL_WEBSERVICE_USERNAME' => 'Webservice username',
'LBL_WEBSERVICE_ACCESSKEY' => 'Webservice accesskey',
'LBL_DEFAULT_LANGUAGE' => 'Lingua di default',
'LBL_WEBSITE_LOGO' => 'Logo di default',
'LBL_SENDER_NAME' => 'Nome mittente',
'LBL_SENDER_EMAIL' => 'Email mittente',
'LBL_TEMPLATES' => 'Template',
'LBL_PRIVACY_POLICY' => 'Informativa Privacy',
'LBL_WEBSERVICE_ENDPOINT_DESC' => 'L\'URL dove &egrave; installato il CRM',
'LBL_WEBSERVICE_USERNAME_DESC' => 'Utente utilizzato per le chiamate Webservice',
'LBL_WEBSERVICE_ACCESSKEY_DESC' => 'Accesskey dell\'utente utilizzato per le chiamate Webservice',
'LBL_WEBSITE_LOGO_DESC' => 'Il logo di default utilizzato nell\'app',
'LBL_SENDER_NAME_DESC' => 'Il nome del mittente utilizzato per le comunicazioni GDPR',
'LBL_SENDER_EMAIL_DESC' => 'L\'email del mittente utilizzata per le comunicazioni GDPR',
'LBL_ENGLISH_LANG' => 'EN English',
'LBL_ITALIAN_LANG' => 'IT Italiano',
'LBL_DEFAULT_LANGUAGE_DESC' => 'La lingua di default utilizzata nell\'app',
'LBL_SUPPORT_REQUEST_TEMPLATE' => 'Template richiesta supporto',
'LBL_SUPPORT_REQUEST_TEMPLATE_DESC' => 'Template utilizzato per le richieste di supporto',
'LBL_ACCESS_TEMPLATE' => 'Template accesso',
'LBL_ACCESS_TEMPLATE_DESC' => 'Template utilizzato per l\'invio dell\'accesso al contatto',
'LBL_CONFIRM_UPDATE_TEMPLATE' => 'Template di richiesta conferma',
'LBL_CONFIRM_UPDATE_TEMPLATE_DESC' => 'Template utilizzato per la conferma dell\'aggiornamento del contatto',
'LBL_CONTACT_UPDATED_TEMPLATE' => 'Template modifiche contatto',
'LBL_CONTACT_UPDATED_TEMPLATE_DESC' => 'Template utilizzato per inviare le notifiche di cambio dati al contatto',
'LBL_GDPR_VERIFY_LINK' => 'GDPR Accesso - Link di verifica',
'LBL_GDPR_ACCESS_LINK' => 'GDPR Accesso - Link di accesso',
'LBL_GDPR_CONFIRM_LINK' => 'GDPR Aggiornamento - Link di conferma',
'LBL_GDPR_SUPPORT_REQUEST_SENDER' => 'GDPR Richiesta supporto - Mittente',
'LBL_GDPR_SUPPORT_REQUEST_SUBJECT' => 'GDPR Richiesta supporto - Oggetto',
'LBL_GDPR_SUPPORT_REQUEST_DESC' => 'GDPR Richiesta supporto - Descrizione',
'CompanyDetails' => 'Dettagli societa`',
'LBL_ANONYMOUS' => 'Anonymous',
'LBL_GDPR_NOTIFY_ANONYMIZE_SUBJECT'=>'Anonimizzazione contatto',
'LBL_GDPR_NOTIFY_ANONYMIZE_BODY'=>'E\' stata effettuata l\'anonimizzazione di %s, %s, %s.<br>Entro il %s devi assicurarti che vengano eliminati i suoi dati anche da eventuali supporti cartacei o esterni.<br>Ricordati di cancellare anche questa email!',
'LBL_NOCONFIRM_DELETION_MOTHS' => 'Mesi attesa conferma',
'LBL_NOCONFIRM_DELETION_MOTHS_DESC' => 'Il numero di mesi dopo il quale il contatto verra` anonimizzato',
'LBL_GENERAL_SETTINGS' => 'Impostazioni generali',
'LBL_DEFAULT_BUSINESS_UNIT' => 'Default Business Unit',
'LBL_DEFAULT_BUSINESS_UNIT_DESC' => 'La business unit di default utilizzata come fallback',
),
'en_us' => array(
'GDPR' => 'GDPR',
'LBL_GDPR' => 'GDPR',
'LBL_GDPR_DESCRIPTION' => 'Configure the GDPR settings',
'LBL_WEBSERVICE' => 'Webservice',
'LBL_WEBSERVICE_ENDPOINT' => 'Webservice endpoint',
'LBL_WEBSERVICE_USERNAME' => 'Webservice username',
'LBL_WEBSERVICE_ACCESSKEY' => 'Webservice access key',
'LBL_DEFAULT_LANGUAGE' => 'Default language',
'LBL_WEBSITE_LOGO' => 'Default logo',
'LBL_SENDER_NAME' => 'Sender name',
'LBL_SENDER_EMAIL' => 'Sender email',
'LBL_TEMPLATES' => 'Template',
'LBL_PRIVACY_POLICY' => 'Privacy Policy',
'LBL_WEBSERVICE_ENDPOINT_DESC' => 'The URL where CRM is installed',
'LBL_WEBSERVICE_USERNAME_DESC' => 'User employed for the Webservice calls',
'LBL_WEBSERVICE_ACCESSKEY_DESC' => 'User Access key used for the Webservice calls',
'LBL_WEBSITE_LOGO_DESC' => 'The default logo used in the app',
'LBL_SENDER_NAME_DESC' => 'The sender name used for GDPR communication',
'LBL_SENDER_EMAIL_DESC' => 'The sender email used for GDPR communication',
'LBL_ENGLISH_LANG' => 'EN English',
'LBL_ITALIAN_LANG' => 'IT Italiano',
'LBL_DEFAULT_LANGUAGE_DESC' => 'The default language used in the app',
'LBL_SUPPORT_REQUEST_TEMPLATE' => 'Support request Template',
'LBL_SUPPORT_REQUEST_TEMPLATE_DESC' => 'Template used for support request',
'LBL_ACCESS_TEMPLATE' => 'Access Template',
'LBL_ACCESS_TEMPLATE_DESC' => 'Template used for sending the access details to the contact',
'LBL_CONFIRM_UPDATE_TEMPLATE' => 'Confirm update template',
'LBL_CONFIRM_UPDATE_TEMPLATE_DESC' => 'Template used for confirming the contact update',
'LBL_CONTACT_UPDATED_TEMPLATE' => 'Contact updated template',
'LBL_CONTACT_UPDATED_TEMPLATE_DESC' => 'Template used for sending update notifications to the contact',
'LBL_GDPR_VERIFY_LINK' => 'GDPR Access - Verify link',
'LBL_GDPR_ACCESS_LINK' => 'GDPR Access - Access link',
'LBL_GDPR_CONFIRM_LINK' => 'GDPR Update - Confirm link',
'LBL_GDPR_SUPPORT_REQUEST_SENDER' => 'GDPR Support Request - Sender',
'LBL_GDPR_SUPPORT_REQUEST_SUBJECT' => 'GDPR Support Request - Subject',
'LBL_GDPR_SUPPORT_REQUEST_DESC' => 'GDPR Support Request - Description',
'CompanyDetails' => 'Company details',
'LBL_ANONYMOUS' => 'Anonymous',
'LBL_GDPR_NOTIFY_ANONYMIZE_SUBJECT'=>'Contact anonymization',
'LBL_GDPR_NOTIFY_ANONYMIZE_BODY'=>'Has been made the anonymization of %s, %s and %s was made.<br>Within the %s you must ensure that your data is also deleted from any paper or external media.<br>Remember to also delete this email!',
'LBL_NOCONFIRM_DELETION_MOTHS' => 'Number of waiting months for confirm',
'LBL_NOCONFIRM_DELETION_MOTHS_DESC' => 'The number of months after which the contact will be anonymised',
'LBL_GENERAL_SETTINGS' => 'General settings',
'LBL_DEFAULT_BUSINESS_UNIT' => 'Default Business Unit',
'LBL_DEFAULT_BUSINESS_UNIT_DESC' => 'The default business unit used as fallback',
),
);
$languages = vtlib_getToggleLanguageInfo();
foreach ($translations as $module => $modlang) {
foreach ($modlang as $lang => $translist) {
if (array_key_exists($lang, $languages)) {
foreach ($translist as $label => $translabel) {
SDK::setLanguageEntry($module, $lang, $label, $translabel);
}
}
}
}
$this->initCustomWebserviceOperations();
if (Vtecrm_Event::hasSupport()) {
Vtecrm_Event::register('', 'vte.entity.beforesave', 'GDPRHandler', 'include/utils/GDPRWS/handlers/GDPRHandler.php');//crmv@207852
}
$focus = ModNotifications::getInstance(); // crmv@164122
$focus->addNotificationType('GDPR_INSTALLED', 'GDPR_INSTALLED', 0);
$notifications = array(
'it_it' => "E' stato installato un importante aggiornamento relativo alla gestione del GDPR. Scopri come permettere ai tuoi contatti la tutela delle loro informazioni personali in tuo possesso consultando la <a href=\"http://www.vtenext.com/utilizzo-del-modulo-gdpr-vtenext/\">guida online</a>. Per maggiori informazioni sul GDPR in generale <a href=\"https://en.wikipedia.org/wiki/General_Data_Protection_Regulation\">clicca qui</a>.",
'en_us' => "An important update concerning the management of the GDPR has been installed. Find out how to allow your contacts to protect their personal information in your possession by consulting the <a href=\"http://www.vtenext.com/en/utilizzo-del-modulo-gdpr-vtenext/\">online guide</a>. For more information on GDPR in general <a href=\"https://en.wikipedia.org/wiki/General_Data_Protection_Regulation\">click here</a>.",
);
$subjects = array(
'it_it' => "E' stato installato un importante aggiornamento relativo alla gestione del GDPR.",
'en_us' => "An important update concerning the management of the GDPR has been installed.",
);
SDK::setLanguageEntry('ModNotifications', 'it_it', 'GDPR_INSTALLED', $notifications['it_it']);
SDK::setLanguageEntry('ModNotifications', 'en_us', 'GDPR_INSTALLED', $notifications['en_us']);
$users = array();
$usersLang = array();
$userListResult = $adb->pquery("SELECT id, default_language FROM {$table_prefix}_users WHERE status = ? AND is_admin = ?", array('Active', 'on'));
if ($userListResult && $adb->num_rows($userListResult)) {
while ($row = $adb->fetchByAssoc($userListResult, -1, false)) {
$users[] = $row['id'];
$usersLang[$row['id']] = $row['default_language'];
}
}
$focus = ModNotifications::getInstance(); // crmv@164122
if (!empty($users)) {
$alreadyNotifiedUsers = array();
foreach ($users as $user) {
if (in_array($user, $alreadyNotifiedUsers)) {
continue;
}
$LU = LanguageUtils::getInstance();
$LU->changeCurrentLanguage($usersLang[$user]);
$notifiedUsers = $focus->saveFastNotification(array(
'assigned_user_id' => $user,
'related_to' => '',
'mod_not_type' => 'GDPR_INSTALLED',
'subject' => $subjects[$usersLang[$user]],
'description' => getTranslatedString('GDPR_INSTALLED', 'ModNotifications'),
'createdtime' => date('Y-m-d H:i:s'),
'modifiedtime' => date('Y-m-d H:i:s'),
));
$LU->restoreCurrentLanguage($usersLang[$user]);
if (!empty($notifiedUsers)) {
foreach ($notifiedUsers as $notifiedUser) {
$alreadyNotifiedUsers[] = $notifiedUser;
}
}
}
}
$contactsInstance = Vtecrm_Module::getInstance('Contacts');
Vtecrm_Link::addLink($contactsInstance->id, 'DETAILVIEWBASIC', 'LBL_GDPR_ANONYMIZE', 'javascript:gdprAnonymize(\'$MODULE$\',$RECORD$);');
$leadsInstance = Vtecrm_Module::getInstance('Leads');
Vtecrm_Link::addLink($leadsInstance->id, 'DETAILVIEWBASIC', 'LBL_GDPR_ANONYMIZE', 'javascript:gdprAnonymize(\'$MODULE$\',$RECORD$);');
$result = $adb->pquery("SELECT * FROM {$table_prefix}_cronjobs WHERE cronname = ?", array('GDPR'));
if ($adb->num_rows($result) == 0) {
require_once('include/utils/CronUtils.php');
$CU = CronUtils::getInstance();
$cj = new CronJob();
$cj->name = 'GDPR';
$cj->active = 1;
$cj->singleRun = false;
$cj->fileName = 'cron/modules/Newsletter/GDPR.service.php';
$cj->timeout = 5400;
$cj->repeat = 14400; // repeat every 4 hours
$CU->insertCronJob($cj);
}
$this->updateConvertLead(); // crmv@194712
}
public function createTemplateEmail($name, $label, $subject, $description, $language, $type = 'Email') {
global $adb, $table_prefix;
$emailTemplatesResult = $adb->pquery("SELECT * FROM {$table_prefix}_emailtemplates WHERE templatename = ? AND deleted = 0", array($label));
if ($emailTemplatesResult && $adb->num_rows($emailTemplatesResult)) {
$row = $adb->fetchByAssoc($emailTemplatesResult, -1, false);
return $row['templateid'];
}
$templateFile = 'include/utils/GDPRWS/templates/'.$name.'_'.$language.'.html';
if (!(file_exists($templateFile) && is_readable($templateFile))) {
return false;
}
$id = $adb->getUniqueID($table_prefix . '_emailtemplates');
$body = file_get_contents($templateFile);
$params = array(
'foldername' => 'Public',
'templatename' => $label,
'subject' => $subject,
'description' => $description,
'body' => $adb->getEmptyClob(false),
'deleted' => 0,
'templateid' => $id,
'templatetype' => $type,
'overwrite_message' => 1,
);
$columns = array_keys($params);
$adb->format_columns($columns);
$adb->pquery("INSERT INTO {$table_prefix}_emailtemplates (" . implode(',', $columns) . ") VALUES (" . generateQuestionMarks($params) . ")", $params);
$adb->updateClob($table_prefix . '_emailtemplates', 'body', "templateid=$id", $body);
return $id;
}
public function checkTables() {
global $adb, $table_prefix;
$schema_table = '<schema version="0.3">
<table name="' . $this->authTable . '">
<opt platform="mysql">ENGINE=InnoDB</opt>
<field name="contactid" type="R" size="19">
<KEY/>
</field>
<field name="authtoken" type="C" size="63">
<KEY/>
</field>
<field name="authtoken_expire" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="authtoken_createdtime" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="authtoken_remote_addr" type="C" size="45" />
<field name="authtoken_confirmed" type="I" size="1" />
<field name="authtoken_confirmedtime" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="accesstoken" type="C" size="63" />
<field name="accesstoken_expire" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="accesstoken_createdtime" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="accesstoken_remote_addr" type="C" size="45" />
<field name="accesstoken_confirmed" type="I" size="1" />
<field name="accesstoken_confirmedtime" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<index name="authtoken_expire_idx">
<col>authtoken_expire</col>
</index>
<index name="accesstoken_expire_idx">
<col>accesstoken_expire</col>
</index>
</table>
</schema>';
if (!Vtecrm_Utils::CheckTable($this->authTable)) {
$schema_obj = new adoSchema($adb->database);
$schema_obj->ExecuteSchema($schema_obj->ParseSchemaString($schema_table));
}
$schema_table = '<schema version="0.3">
<table name="' . $this->logTable . '">
<opt platform="mysql">ENGINE=InnoDB</opt>
<field name="logid" type="R" size="19">
<KEY/>
</field>
<field name="contactid" type="I" size="19" />
<field name="timestamp" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="operation" type="C" size="63" />
<field name="operation_remote_addr" type="C" size="45" />
<field name="data" type="XL" />
<index name="timestamp_idx">
<col>timestamp</col>
</index>
<index name="operation_idx">
<col>operation</col>
</index>
</table>
</schema>';
if (!Vtecrm_Utils::CheckTable($this->logTable)) {
$schema_obj = new adoSchema($adb->database);
$schema_obj->ExecuteSchema($schema_obj->ParseSchemaString($schema_table));
}
$schema_table = '<schema version="0.3">
<table name="' . $this->confirmTable . '">
<opt platform="mysql">ENGINE=InnoDB</opt>
<field name="queueid" type="R" size="19">
<KEY/>
</field>
<field name="contactid" type="I" size="19" />
<field name="accesstoken" type="C" size="63" />
<field name="timestamp" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="operation" type="C" size="63" />
<field name="operation_remote_addr" type="C" size="45" />
<field name="data" type="XL" />
<field name="token" type="C" size="63" />
<field name="token_expire" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="token_createdtime" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
<field name="token_remote_addr" type="C" size="45" />
<field name="token_confirmed" type="I" size="1" />
<field name="token_confirmedtime" type="T">
<DEFAULT value="0000-00-00 00:00:00"/>
</field>
</table>
</schema>';
if (!Vtecrm_Utils::CheckTable($this->confirmTable)) {
$schema_obj = new adoSchema($adb->database);
$schema_obj->ExecuteSchema($schema_obj->ParseSchemaString($schema_table));
}
}
public static function isEnabledForModule($module) {
return in_array($module, self::$supportedModules);
}
public function validateContactId($cid, &$error) {
global $adb, $table_prefix, $current_user;
$contactid = $module = $email = null;
if (!is_numeric($cid)) {
list($msgtype, $email, $module) = explode('|', base64_decode(urldecode($cid)));
} else {
$contactid = $cid;
$module = getSalesEntityType($contactid);
}
if (!self::isEnabledForModule($module)) {
return $this->validateUnsupportedModule($cid, $module, $email, $error);
}
if (empty($contactid)) {
$column = $this->emailFields[$module]['tablename'].'.'.$this->emailFields[$module]['columnname'];
$qg = QueryGenerator::getInstance($module, $current_user);
$idcol = $qg->getSQLColumn('id', false);
$qg->initForAllCustomView();
$qg->addField('id');
$qg->addFieldAlias('id', 'crmid');
$query = $qg->getQuery();
$query .= " AND $column = ? AND COALESCE(gdpr_deleted, 0) <> 1 ORDER BY crmid";
$contactResult = $adb->limitpquery($query, 0, 1, array($email));
if ($contactResult && $adb->num_rows($contactResult)) {
$contactid = intval($adb->query_result($contactResult, 0, 'crmid'));
} else {
$error = 'RECORD_NOT_FOUND';
return false;
}
}
$focus = CRMEntity::getInstance($module);
$ret = $focus->retrieve_entity_info_no_html($contactid, $module, false);
$focus->id = $contactid;
if ($ret == 'LBL_RECORD_DELETE') {
$error = 'RECORD_DELETED';
return false;
} elseif ($ret == 'LBL_RECORD_NOT_FOUND') {
$error = 'RECORD_NOT_FOUND';
return false;
}
if ($focus->column_fields['gdpr_deleted'] === '1') {
$error = 'RECORD_DELETED';
return false;
}
$emailField = $this->emailFields[$module]['fieldname'];
$availableData = array();
$fields = array_flip($this->getAvailableFields($module));
$columnFields = $focus->column_fields;
foreach ($columnFields as $fieldname => $value) {
if (isset($fields[$fieldname])) {
$availableData[$fieldname] = $value;
}
}
$email = $columnFields[$emailField];
$gdprws = GDPRWS::getInstance();
$bid = $gdprws->getBusinessId($contactid, $module, $email);
$this->initBusinessData($bid);
$newsletterFocus = CRMEntity::getInstance('Newsletter');
//$availableData['gdpr_marketing'] = $newsletterFocus->receivingNewsletter($email); // crmv@181193
$cid = urlencode(base64_encode("C|".$email."|".$module));
$this->cid = $cid;
$this->cidData = array();
$this->cidData['email'] = $email;
$this->cidData['module'] = $module;
$contactData = array(
'module' => $module,
'contactid' => $contactid,
'email' => $email,
'focus' => $focus,
'email_field' => $this->emailFields[$module],
'available_data' => $availableData,
'business_id' => $bid,
);
// crmv@164120
global $current_auth_record;
if (empty($current_auth_record)) $current_auth_record = array('module' => $module, 'id' => $contactid);
// crmv@164120e
return $contactData;
}
public function validateAccess($accesstoken, &$error) {
global $adb, $table_prefix;
$error = null;
$contactid = $this->validateAccessToken($accesstoken, $error);
if (!empty($error)) return false;
$contactid = intval($contactid);
$error = null;
$contactData = $this->validateContactId($contactid, $error);
if (!empty($error)) return false;
return $contactData;
}
public function validateUnsupportedModule($cid, $module, $email, &$error) {
global $adb, $table_prefix, $current_user;
$this->cid = $cid;
$this->cidData = array();
$this->cidData['email'] = $email;
$this->cidData['module'] = $module;
$contactData = array();
$contactData['module'] = $module;
$contactData['email'] = $email;
$contactData['business_id'] = false;
$contactData['contactid'] = false;
if (isset($this->emailFields[$module])) {
$crmid = null;
$column = $this->emailFields[$module]['tablename'].'.'.$this->emailFields[$module]['columnname'];
$qg = QueryGenerator::getInstance($module, $current_user);
$idcol = $qg->getSQLColumn('id', false);
$qg->initForAllCustomView();
$qg->addField('id');
$qg->addFieldAlias('id', 'crmid');
$query = $qg->getQuery();
$query .= " AND $column = ? ORDER BY crmid";
$result = $adb->limitpquery($query, 0, 1, array($email));
if ($result && $adb->num_rows($result)) {
$crmid = intval($adb->query_result($result, 0, 'crmid'));
}
$contactData['contactid'] = $crmid;
$bid = $this->getBusinessId($crmid, $module, $email);
$contactData['business_id'] = $bid;
$this->initBusinessData($bid);
}
$error = 'OPERATION_DENIED';
return $contactData;
}
protected function initBusinessData($bid) {
$vteProp = VTEProperties::getInstance();
$config = $vteProp->get("services.gdpr.config.business.{$bid}");
$this->senderName = $config['sender_name'];
$this->senderEmail = $config['sender_email'];
$this->noconfirm_deletion_months = $config['noconfirm_deletion_months'];
$templates = $vteProp->get("services.gdpr.templates.business.{$bid}");
$this->templates = $templates;
}
public function generateAuthToken($cid) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateContactId($cid, $error);
if (!empty($error)) return $this->error($error);
$contactid = $contactData['contactid'];
$contractEmail = $contactData['email'];
$authToken = $this->generateToken(32);
$servertime = time();
$expireTime = time() + (60*5);
$params = array(
'contactid' => $contactid,
'authtoken' => $authToken,
'authtoken_expire' => date('Y-m-d H:i:s', $expireTime),
'authtoken_createdtime' => date('Y-m-d H:i:s'),
'authtoken_remote_addr' => getIp(),
'authtoken_confirmed' => 0,
);
$columns = array_keys($params);
$adb->format_columns($columns);
$adb->pquery("INSERT INTO {$this->authTable} (" . implode(',', $columns) . ") VALUES (" . generateQuestionMarks($params) . ")", $params);
$this->log($contactid, 'AUTHTOKEN_GENERATED', array());
return $this->success(array('email' => $contractEmail, 'token' => $authToken, 'servertime' => $servertime, 'expiretime' => $expireTime));
}
public function generateAccessToken($cid, $authtoken) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateContactId($cid, $error);
if (!empty($error)) return $this->error($error);
$contactid = $contactData['contactid'];
$contractEmail = $contactData['email'];
if ($this->validateAuthToken($contactid, $authtoken)) {
if ($this->countActiveAccessToken($contactid) >= 4) {
$this->log($contactid, 'ACCESSTOKEN_LIMIT_REACHED', array());
return $this->error('ACCESSTOKEN_LIMIT_REACHED');
}
} else {
$this->log($contactid, 'AUTHTOKEN_EXPIRED', array());
return $this->error('AUTHTOKEN_EXPIRED');
}
$params = array(
'authtoken_confirmed' => 1,
'authtoken_confirmedtime' => date('Y-m-d H:i:s'),
);
$upd = array();
foreach ($params as $col => $value) {
$upd[] = "$col = ?";
}
$sql = "UPDATE {$this->authTable} SET " . implode(',', $upd) . " WHERE contactid = ? AND authtoken = ?";
$adb->pquery($sql, array($params, $contactid, $authtoken));
$this->log($contactid, 'AUTHTOKEN_CONFIRMED', array());
// Let's create accesstoken
$accessToken = $this->generateToken(32);
$servertime = time();
$expireTime = time() + (60*60*2);
$params = array(
'accesstoken' => $accessToken,
'accesstoken_expire' => date('Y-m-d H:i:s', $expireTime),
'accesstoken_createdtime' => date('Y-m-d H:i:s'),
'accesstoken_remote_addr' => getIp(),
'accesstoken_confirmed' => 0,
);
$upd = array();
foreach ($params as $col => $value) {
$upd[] = "$col = ?";
}
$sql = "UPDATE {$this->authTable} SET " . implode(',', $upd) . " WHERE contactid = ? AND authtoken = ?";
$adb->pquery($sql, array($params, $contactid, $authtoken));
$this->deleteOrphanToken($contactid);
$this->log($contactid, 'ACCESSTOKEN_GENERATED', array());
return $this->success(array('email' => $contractEmail, 'token' => $accessToken, 'servertime' => $servertime, 'expiretime' => $expireTime));
}
public function sendVerify($cid, $authtoken) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateContactId($cid, $error);
if (!empty($error)) return $this->error($error);
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$contactEmail = $contactData['email'];
$requestAccesstoken = $this->generateAccessToken($cid, $authtoken);
if ($requestAccesstoken['success']) {
$accesstoken = $requestAccesstoken['token'];
$emailStatus = $this->sendAccessEmail($contactData, $accesstoken);
if (!$emailStatus) {
return $this->error('SEND_EMAIL_FAILED');
}
} else {
return $this->error($requestAccesstoken['error']);
}
return $this->success(array('email' => $contactEmail));
}
public function checkAccessToken($accesstoken, $options = array()) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateAccess($accesstoken, $error);
if (!empty($error)) return $this->error($error);
$output = $this->formatOutputData(array(), $contactData, $options);
return $this->success($output);
}
public function updateContact($accesstoken, $data, $options = array()) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateAccess($accesstoken, $error);
if (!empty($error)) return $this->error($error);
$module = $contactData['module'];
$fields = array_flip($this->getAvailableFields($module));
foreach ($data as $fieldname => $value) {
if (!isset($fields[$fieldname])) {
unset($data[$fieldname]);
}
}
$error = null;
$success = $this->enqueueUpdate($contactData, $accesstoken, 'UPDATE_CONTACT', $data, $error);
if (!empty($error)) return $this->error($error);
$output = $this->formatOutputData(array(), $contactData, $options);
return $this->success($output);
}
public function deleteContact($accesstoken, $options = array()) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateAccess($accesstoken, $error);
if (!empty($error)) return $this->error($error);
$error = null;
$success = $this->enqueueUpdate($contactData, $accesstoken, 'DELETE_CONTACT', array(), $error);
if (!empty($error)) return $this->error($error);
$output = $this->formatOutputData(array(), $contactData, $options);
return $this->success($output);
}
public function confirmUpdate($accesstoken, $token, $options = array()) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateAccess($accesstoken, $error);
if (!empty($error)) return $this->error($error);
$contactid = $contactData['contactid'];
if (!$this->validateConfirmToken($contactid, $accesstoken, $token)) {
$this->log($contactid, 'CONFIRMTOKEN_EXPIRED', array());
return $this->error('CONFIRMTOKEN_EXPIRED');
}
$params = array(
'token_confirmed' => 1,
'token_confirmedtime' => date('Y-m-d H:i:s'),
);
$upd = array();
foreach ($params as $col => $value) {
$upd[] = "$col = ?";
}
$sql = "UPDATE {$this->confirmTable} SET " . implode(',', $upd) . " WHERE contactid = ? AND accesstoken = ? AND token = ?";
$adb->pquery($sql, array($params, $contactid, $accesstoken, $token));
$this->log($contactid, 'CONFIRMTOKEN_CONFIRMED', array());
$this->deleteOrphanConfirmToken($contactid);
$error = null;
$changes = $this->applyContactChanges($contactData, $accesstoken, $token, $error);
if (!empty($error)) return $this->error($error);
$output = $this->formatOutputData(array(), $contactData, $options);
return $this->success($output);
}
public function mergeContactData($accesstoken, $maincontact, $otherids, $options = array()) {
global $adb, $table_prefix, $current_user;
$error = null;
$contactData = $this->validateAccess($accesstoken, $error);
if (!empty($error)) return $this->error($error);
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$contactEmail = $contactData['email'];
$column = $contactData['email_field']['tablename'].'.'.$contactData['email_field']['columnname'];
// 1. Validate ids
$otherids = array_filter(array_map('intval', $otherids));
$otherids = array_filter($otherids, function($v1) use($module) {
return in_array(getSalesEntityType($v1), array($module));
});
// 2. Get all duplicate contacts data
$qg = QueryGenerator::getInstance($module, $current_user);
$idcol = $qg->getSQLColumn('id', false);
$qg->initForAllCustomView();
$qg->addField('id');
$qg->addFieldAlias('id', 'crmid');
$fields = $this->getAvailableFields($module, false);
foreach ($fields as $field) {
$qg->addField($field);
$qg->addFieldAlias($field, $field);
}
$query = $qg->getQuery();
$query .= " AND $column = ? AND COALESCE(gdpr_deleted, 0) <> 1 AND $idcol IN (".generateQuestionMarks($otherids).")";
$duplicates = array();
$duplicateResult = $adb->pquery($query, array($contactEmail, $otherids));
if ($duplicateResult && $adb->num_rows($duplicateResult)) {
while ($row = $adb->fetchByAssoc($duplicateResult, -1, false)) {
$duplicates[] = $row;
}
}
// 3. Merge contacts data and send confirm
$obj1 = CRMEntity::getInstance($module);
$obj1->id = $maincontact;
$obj1->mode = 'edit';
$obj1->retrieve_entity_info_no_html($maincontact, $module);
// crmv@164120
$changeLogQuery = "SELECT parent_id, changelogid, description, modified_date
FROM {$table_prefix}_changelog
WHERE parent_id IN (".generateQuestionMarks($otherids).") AND description NOT LIKE '%_Relation%'
ORDER BY modified_date ASC";
// crmv@164120e
$changeLogResult = $adb->pquery($changeLogQuery, array($otherids));
$changeLogInfo = array();
if ($changeLogResult && $adb->num_rows($changeLogResult) > 0) {
while ($row = $adb->fetchByAssoc($changeLogResult, -1, false)) {
$descriptionInfo = Zend_Json::decode($row['description']);
for ($i = 0; $i < count($descriptionInfo); $i++) {
if (!empty($descriptionInfo[$i][2])) {
if ($descriptionInfo[$i][3] == 'assigned_user_id') {
$changeLogInfo[$descriptionInfo[$i][3]] = getIdfromUsername($descriptionInfo[$i][2]);
} else {
$changeLogInfo[$descriptionInfo[$i][3]] = $descriptionInfo[$i][2];
}
}
}
}
}
$mergedRecord = array();
$emptyValues = array('', null, '0', '0000-00-00 00:00:00', '--None--', '--Nessuno--');
foreach ($duplicates as $duplicate) {
$duplicateId = $duplicate['crmid'];
$obj2 = CRMEntity::getInstance($module);
$obj2->id = $duplicateId;
$obj2->mode = 'edit';
$obj2->retrieve_entity_info_no_html($duplicateId, $module);
$colFields = array_keys($obj1->column_fields);
foreach ($colFields as $key) {
if (!in_array($key, array('firstname', 'lastname', 'email', 'bu_mc'))) { // crmv@163697
if (!isset($changeLogInfo[$key])) {
if (!in_array($obj1->column_fields[$key], $emptyValues)) {
$mergedRecord[$key] = $obj1->column_fields[$key];
} elseif (!in_array($obj2->column_fields[$key], $emptyValues)) {
$mergedRecord[$key] = $obj2->column_fields[$key];
} else {
$mergedRecord[$key] = $obj1->column_fields[$key];
}
} elseif (!in_array($changeLogInfo[$key], $emptyValues)) {
$mergedRecord[$key] = $changeLogInfo[$key];
} else {
$mergedRecord[$key] = $obj1->column_fields[$key];
}
} else {
if ($key === 'bu_mc') {
if (empty($mergedRecord['bu_mc'])) {
$bumc1 = $obj1->column_fields['bu_mc'];
} else {
$bumc1 = $mergedRecord[$key];
}
$bumc2 = $obj2->column_fields['bu_mc'];
$bumc = implode(' |##| ', array_unique(array_merge(explode(' |##| ', $bumc1), explode(' |##| ', $bumc2))));
$mergedRecord[$key] = $bumc;
} else {
$mergedRecord[$key] = $obj1->column_fields[$key];
}
}
}
unset($obj2);
}
unset($obj1);
// Unset useless fields
unset($mergedRecord['record_id']);
unset($mergedRecord['record_module']);
unset($mergedRecord['createdtime']);
unset($mergedRecord['modifiedtime']);
unset($mergedRecord['creator']);
unset($mergedRecord['assigned_user_id']);
$mergedRecord['transfer_relations'] = $otherids;
$mergedRecord['main_contact'] = $maincontact;
$error = null;
$success = $this->enqueueUpdate($contactData, $accesstoken, 'MERGE_CONTACT', $mergedRecord, $error);
if (!empty($error)) return $this->error($error);
$output = $this->formatOutputData(array(), $contactData, $options);
return $this->success($output);
}
public function getFields($accesstoken, $options = array()) {
global $adb, $table_prefix, $current_user;
$error = null;
$contactData = $this->validateAccess($accesstoken, $error);
if (!empty($error)) return $this->error($error);
$module = $contactData['module'];
$structure = $this->calculateFieldStructure($module);
$output = $this->formatOutputData(array('structure' => $structure), $contactData, $options);
return $this->success($output);
}
public function sendSupportRequest($cid, $subject, $description, $options = array()) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateContactId($cid, $error);
if (!empty($error)) {
if ($error === 'OPERATION_DENIED') {
if (empty($contactData['business_id'])) {
return $this->error($error);
}
} else {
return $this->error($error);
}
}
if (empty($subject)) {
return $this->error('INVALID_SUBJECT');
}
if (empty($description)) {
return $this->error('INVALID_DESCRIPTION');
}
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$contactEmail = $contactData['email'];
$templateid = $this->templates['support_request_template'];
$r = array(
'$custom||gdpr_support_request_sender$' => $contactEmail,
'$custom||gdpr_support_request_subject$' => $subject,
'$custom||gdpr_support_request_description$' => $description
);
$status = $this->sendEmailTemplate($module, $contactid, $this->senderEmail, $templateid, $r);
if ($status) {
$this->log($contactid, 'SUPPORT_REQUEST_SENT', array());
} else {
$this->log($contactid, 'SUPPORT_REQUEST_NOT_SENT', array());
}
return $status ? $this->success(array()) : $this->error('SEND_EMAIL_FAILED');
}
public function getPrivacyPolicy($cid, $options = array()) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateContactId($cid, $error);
if (!empty($error)) {
if ($error === 'OPERATION_DENIED') {
if (empty($contactData['business_id'])) {
return $this->error($error);
}
} else {
return $this->error($error);
}
}
$bid = $contactData['business_id'];
$PPU = PrivacyPolicyUtils::getInstance();
$companyPrivacyPolicy = $PPU->get($bid, 'Company');
$output = array('privacy_policy' => $companyPrivacyPolicy);
return $this->success($output);
}
public function sendPrivacyPolicy($cid, $options = array()) {
global $adb, $table_prefix;
$error = null;
$contactData = $this->validateContactId($cid, $error);
if (!empty($error)) {
if ($error === 'OPERATION_DENIED') {
if (empty($contactData['business_id'])) {
return $this->error($error);
}
} else {
return $this->error($error);
}
}
$bid = $contactData['business_id'];
$PPU = PrivacyPolicyUtils::getInstance();
$companyPrivacyPolicy = $PPU->get($bid, 'Company');
$contactEmail = $contactData['email'];
$success = send_mail('', $contactEmail, $this->senderName, $this->senderEmail, 'Privacy Policy', $companyPrivacyPolicy);
return $success ? $this->success(array()) : $this->error('SEND_EMAIL_FAILED');
}
protected function sendAccessEmail($contactData, $accesstoken) {
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$email = $contactData['email'];
$templateid = $this->templates['access_template'];
$newsletterFocus = CRMEntity::getInstance('Newsletter');
$gdprLink = $newsletterFocus->gdpr_link;
$r = array(
'$custom||gdpr_access_login_link$' => $gdprLink.'?action=detailview&accesstoken='.urlencode($accesstoken),
);
$status = $this->sendEmailTemplate($module, $contactid, $email, $templateid, $r);
if ($status) {
$this->log($contactid, 'ACCESSTOKEN_SENT', array());
} else {
$this->log($contactid, 'ACCESSTOKEN_NOT_SENT', array());
}
return $status;
}
protected function deleteOrphanToken($contactid) {
global $adb, $table_prefix;
// Clean old expired authtoken
$sql = "DELETE FROM {$this->authTable} WHERE contactid = ? AND authtoken_confirmed = 0 AND authtoken_expire <= ?";
$adb->pquery($sql, array($contactid, date('Y-m-d H:i:s')));
// Clean old expired accesstoken
$sql = "DELETE FROM {$this->authTable} WHERE contactid = ? AND accesstoken_expire <= ?";
$adb->pquery($sql, array($contactid, date('Y-m-d H:i:s')));
}
protected function deleteOrphanConfirmToken($contactid) {
global $adb, $table_prefix;
// Clean old expired token
$sql = "DELETE FROM {$this->confirmTable} WHERE contactid = ? AND token_expire <= ?";
$adb->pquery($sql, array($contactid, date('Y-m-d H:i:s')));
}
protected function validateAuthToken($contactid, $authtoken) {
global $adb, $table_prefix;
$checkQuery = "SELECT 1 FROM {$this->authTable} WHERE contactid = ? AND authtoken = ? AND authtoken_confirmed = 0 AND authtoken_expire > ?";
$checkResult = $adb->pquery($checkQuery, array($contactid, $authtoken, date('Y-m-d H:i:s')));
return $checkResult && $adb->num_rows($checkResult) > 0;
}
protected function countActiveAccessToken($contactid) {
global $adb, $table_prefix;
$checkQuery = "SELECT 1 FROM {$this->authTable} WHERE contactid = ? AND accesstoken_confirmed = 1 AND accesstoken_expire > ?";
$checkResult = $adb->pquery($checkQuery, array($contactid, date('Y-m-d H:i:s')));
return $adb->num_rows($checkResult);
}
protected function validateAccessToken($accesstoken, &$error) {
global $adb, $table_prefix;
$contactid = null;
if ($this->checkFirstAccess($accesstoken, $contactid)) return $contactid;
if (!$this->checkAccessTokenExpire($accesstoken, $contactid)) {
$error = 'SESSION_EXPIRED';
}
return $contactid;
}
protected function checkAccessTokenExpire($accesstoken, &$contactid = null) {
global $adb, $table_prefix;
$checkQuery = "SELECT contactid FROM {$this->authTable} WHERE accesstoken = ? AND accesstoken_confirmed = 1 AND accesstoken_expire > ?";
$checkResult = $adb->pquery($checkQuery, array($accesstoken, date('Y-m-d H:i:s')));
if ($checkResult && $adb->num_rows($checkResult) > 0) {
$contactid = intval($adb->query_result($checkResult, 0, 'contactid'));
return true;
}
return false;
}
protected function checkFirstAccess($accesstoken, &$contactid = null) {
global $adb, $table_prefix;
$checkQuery = "SELECT contactid FROM {$this->authTable} WHERE accesstoken = ? AND accesstoken_confirmed = 0 AND accesstoken_expire > ?";
$checkResult = $adb->pquery($checkQuery, array($accesstoken, date('Y-m-d H:i:s')));
if ($checkResult && $adb->num_rows($checkResult) > 0) {
$contactid = intval($adb->query_result($checkResult, 0, 'contactid'));
$adb->pquery("UPDATE {$this->authTable} SET accesstoken_confirmed = 1, accesstoken_confirmedtime = ? WHERE accesstoken = ?", array(date('Y-m-d H:i:s'), $accesstoken));
return true;
}
return false;
}
protected function updateAccessTokenContact($contactid, $accesstoken, $maincontact) {
global $adb, $table_prefix;
if (!$this->checkAccessTokenExpire($accesstoken)) {
return false;
}
$adb->pquery("UPDATE {$this->authTable} SET contactid = ? WHERE contactid = ? AND accesstoken = ?", array($maincontact, $contactid, $accesstoken));
return true;
}
protected function invalidateContactTokens($contactid) {
global $adb, $table_prefix;
$adb->pquery("DELETE FROM {$this->authTable} WHERE contactid = ?", array($contactid));
return true;
}
protected function validateConfirmToken($contactid, $accesstoken, $token) {
global $adb, $table_prefix;
$checkQuery = "SELECT 1 FROM {$this->confirmTable} WHERE contactid = ? AND accesstoken = ? AND token = ? AND token_confirmed = 0 AND token_expire > ?";
$checkResult = $adb->pquery($checkQuery, array($contactid, $accesstoken, $token, date('Y-m-d H:i:s')));
return $checkResult && $adb->num_rows($checkResult) > 0;
}
protected function getContactDuplicates($module, $contactid, $column, $value) {
global $adb, $table_prefix, $current_user;
$RM = RelationManager::getInstance();
$qg = QueryGenerator::getInstance($module, $current_user);
$idcol = $qg->getSQLColumn('id', false);
$qg->initForAllCustomView();
$qg->addField('id');
$qg->addFieldAlias('id', 'crmid');
$fields = $this->getAvailableFields($module, false);
foreach ($fields as $field) {
$qg->addField($field);
$qg->addFieldAlias($field, $field);
}
$query = $qg->getQuery();
$query .= " AND $column = ? AND COALESCE(gdpr_deleted, 0) <> 1";
$duplicates = array();
$duplicateResult = $adb->pquery($query, array($value));
if ($duplicateResult && $adb->num_rows($duplicateResult)) {
while ($row = $adb->fetchByAssoc($duplicateResult, -1, false)) {
$contact = array();
$contact['crmid'] = $row['crmid'];
$contact['entityname'] = getEntityName($module, array($row['crmid']), true);
$contact['details'] = array();
foreach ($fields as $field) {
$fieldWS = WebserviceField::fromCachedWS($module, $field);
$contact['details'][] = array(
'fieldname' => $field,
'fieldlabel' => getTranslatedString($fieldWS->getFieldLabelKey(), $module),
'value' => $row[$field],
);
}
$relids = $RM->getRelatedIds($module, $row['crmid']);
$contact['relids'] = count($relids);
$contact['suggested'] = false;
$duplicates[] = $contact;
}
}
if (count($duplicates) < 2) $duplicates = array();
if (!empty($duplicates)) {
$suggestedDuplicate = $duplicates[0];
foreach ($duplicates as $duplicate) {
if ($duplicate['relids'] > $maxRelations) {
$suggestedDuplicate = $duplicate;
}
}
foreach ($duplicates as &$duplicate) {
if ($duplicate['crmid'] !== $suggestedDuplicate['crmid']) continue;
$duplicate['suggested'] = true;
}
}
return $duplicates;
}
protected function getAvailableFields($module, $gdprFields = true) {
$fields = array();
if (is_array($this->availableFields[$module])) {
$fields = array_merge($fields, $this->availableFields[$module]);
}
if ($gdprFields && is_array($this->gdprFields)) {
$fields = array_merge($fields, $this->gdprFields);
}
return $fields;
}
protected function calculateFieldStructure($module) {
global $adb, $table_prefix;
$structure = array();
$blocks = array();
$fields = $this->getAvailableFields($module, false);
foreach ($fields as $fieldname) {
$fieldWS = WebserviceField::fromCachedWS($module, $fieldname);
$fld = array();
$fld['name'] = $fieldWS->getFieldName();
$fld['blockid'] = $fieldWS->getBlockId();
$fld['label'] = strtolower(preg_replace('/\s+/', '_', $fieldWS->getFieldLabelKey()));
$fld['type'] = array('name' => $fieldWS->getFieldDataType());
$fld['uitype'] = $fieldWS->getUIType();
$blockid = $fieldWS->getBlockId();
if ($blockid > 0) {
if (!is_array($blocks[$blockid])) {
$res = $adb->pquery("SELECT * FROM {$table_prefix}_blocks WHERE blockid = ?", array($blockid));
if ($res && $adb->num_rows($res) > 0) {
$row = $adb->fetchByAssoc($res, -1, false);
$block = array(
'blockid' => $blockid,
'module' => $module,
'tabid' => getTabid($module),
'label' => strtolower(str_replace('LBL_', '', $row['blocklabel'])),
'sequence' => $row['sequence'],
);
$blocks[$blockid] = $block;
}
}
$blocks[$blockid]['fields'][] = $fld;
}
}
foreach ($blocks as $blockid => $binfo) {
usort($blocks[$blockid]['fields'], function($v1,$v2) {
return ($v1["sequence"] > $v2["sequence"] ? +1 : ($v1["sequence"] < $v2["sequence"] ? -1 : 0));
});
$blocks[$blockid]['fields'] = $blocks[$blockid]['fields'];
}
$structure = array_values($blocks);
usort($structure, function($v1,$v2) {
return ($v1["sequence"] > $v2["sequence"] ? +1 : ($v1["sequence"] < $v2["sequence"] ? -1 : 0));
});
return $structure;
}
protected function enqueueUpdate($contactData, $accesstoken, $operation, $data, &$error) {
global $adb, $table_prefix;
$contactid = $contactData['contactid'];
$token = $this->generateToken(32);
$servertime = time();
$expireTime = time() + (60*60*2);
$params = array(
'queueid' => $adb->getUniqueID($this->confirmTable),
'contactid' => $contactid,
'accesstoken' => $accesstoken,
'timestamp' => date('Y-m-d H:i:s'),
'operation' => $operation,
'operation_remote_addr' => getIp(),
'data' => Zend_Json::encode($data),
'token' => $token,
'token_expire' => date('Y-m-d H:i:s', $expireTime),
'token_createdtime' => date('Y-m-d H:i:s'),
'token_remote_addr' => getIp(),
'token_confirmed' => 0,
);
$columns = array_keys($params);
$adb->format_columns($columns);
$adb->pquery("INSERT INTO {$this->confirmTable} (" . implode(',', $columns) . ") VALUES (" . generateQuestionMarks($params) . ")", $params);
$this->log($contactid, 'REQUEST_CONTACT_UPDATE', array());
$error = null;
$success = $this->sendConfirmEmail($contactData, $accesstoken, $token, $error);
if (!$success) $error = "SEND_EMAIL_FAILED";
return $success;
}
protected function applyContactChanges($contactData, $accesstoken, $token, &$error) {
global $adb, $table_prefix;
$output = array();
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$email = $contactData['email'];
$changesQuery = "SELECT * FROM {$this->confirmTable} WHERE contactid = ? AND accesstoken = ? AND token = ? AND token_confirmed = 1";
$changesResult = $adb->pquery($changesQuery, array($contactid, $accesstoken, $token));
if ($changesResult && $adb->num_rows($changesResult)) {
$row = $adb->fetchByAssoc($changesResult, -1, false);
$operation = $row['operation'];
$data = Zend_Json::decode($row['data']);
if ($operation === 'UPDATE_CONTACT') {
$this->applyContactUpdate($contactData, $accesstoken, $data);
} elseif ($operation === 'DELETE_CONTACT') {
$this->applyContactDelete($contactData, $accesstoken, $data);
} elseif ($operation === 'MERGE_CONTACT') {
$this->applyContactMerge($contactData, $accesstoken, $data);
}
$this->log($contactid, $operation, array());
}
return $output;
}
public function applyContactUpdate($contactData, $accesstoken, $data) {
global $adb, $table_prefix;
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$email = $contactData['email'];
$focus = CRMEntity::getInstance($module);
$focus->retrieve_entity_info_no_html($contactid, $module, false);
$focus->mode = 'edit';
$focus->id = $contactid;
$gdprFields = $this->gdprFields;
foreach ($data as $fieldname => $value) {
if (in_array($fieldname, $gdprFields)) {
$value = $value === 'true' ? '1' : '0';
$focus->column_fields[$fieldname] = $value;
$focus->column_fields[$fieldname.'_checkedtime'] = date('Y-m-d H:i:s');
$focus->column_fields[$fieldname.'_remote_addr'] = getIp();
} else {
if (isset($focus->column_fields[$fieldname])) {
$focus->column_fields[$fieldname] = $value;
}
}
}
$focus->save($module);
$newsletterFocus = CRMEntity::getInstance('Newsletter');
if ($focus->column_fields['gdpr_marketing'] === '0') {
$newsletterFocus->lockReceivingNewsletter($email, 'lock');
} else {
$newsletterFocus->lockReceivingNewsletter($email, 'unlock');
}
$this->log($contactid, 'CONTACT_UPDATED', array($data));
}
public function applyContactDelete($contactData, $accesstoken, $data) {
global $adb, $table_prefix;
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$email = $contactData['email'];
$focus = CRMEntity::getInstance($module);
$err = $focus->retrieve_entity_info_no_html($contactid, $module, false); // crmv@182782
$focus->mode = 'edit';
$focus->id = $contactid;
$RM = RelationManager::getInstance();
$fields = $this->getAvailableFields($module);
$gdprFields = $this->gdprFields;
// 0. Notify
$this->notifyAnonymize($focus);
// 1. Empty fields
foreach ($fields as $fieldname) {
if (in_array($fieldname, $gdprFields)) {
$focus->column_fields[$fieldname] = '0';
$focus->column_fields[$fieldname.'_checkedtime'] = date('Y-m-d H:i:s');
$focus->column_fields[$fieldname.'_remote_addr'] = getIp();
} else {
if ($fieldname === 'gdpr_sentdate') continue;
if (isset($focus->column_fields[$fieldname])) {
$focus->column_fields[$fieldname] = getTranslatedString('LBL_ANONYMOUS', 'Settings');
}
}
}
// 2. Set contact as GDPR deleted
$focus->column_fields['gdpr_deleted'] = '1';
$focus->column_fields['gdpr_deleted_checkedtime'] = date('Y-m-d H:i:s');
$focus->column_fields['gdpr_deleted_remote_addr'] = getIp();
$emailField = $this->emailFields[$module]['fieldname'];
$focus->column_fields[$emailField] = getTranslatedString('LBL_ANONYMOUS', 'Settings');
// crmv@182782
if ($err == 'LBL_RECORD_DELETE') {
$focus->save($module,false,false,false);
} else {
$focus->save($module);
}
// crmv@182782e
// 3. Turn off the automatic emails
$newsletterFocus = CRMEntity::getInstance('Newsletter');
$newsletterFocus->lockReceivingNewsletter($email, 'lock');
// 4. Empty changelog history
// crmv@164120
$changeLogFocus = ChangeLog::getInstance();
$changeLogFocus->deleteforRecord($module, $contactid);
// crmv@164120e
// 5. Invalidate accesstoken
$this->invalidateContactTokens($contactid);
$this->log($contactid, 'CONTACT_DELETED', array());
}
public function applyContactMerge($contactData, $accesstoken, $data) {
global $adb, $table_prefix;
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$email = $contactData['email'];
$RM = RelationManager::getInstance();
$maincontact = $data['main_contact'];
$focus = CRMEntity::getInstance($module);
$focus->retrieve_entity_info_no_html($maincontact, $module, false);
$focus->mode = 'edit';
$focus->id = $maincontact;
foreach ($data as $fieldname => $value) {
if (isset($focus->column_fields[$fieldname])) {
$focus->column_fields[$fieldname] = $value;
}
}
global $global_skip_notifications;
$tmp_global_skip_notifications = $global_skip_notifications;
$global_skip_notifications = true;
$focus->save($module);
$global_skip_notifications = $tmp_global_skip_notifications;
$transferRelations = $data['transfer_relations'];
foreach ($transferRelations as $transferid) {
$relatedIds = $RM->getRelatedIds($module, $transferid); // crmv@164120
// Transfer all relations
foreach ($relatedIds as $id) {
$RM->relate($module, $maincontact, getSalesEntityType($id), $id);
}
$transferFocus = CRMEntity::getInstance($module);
$transferFocus->retrieve_entity_info_no_html($transferid, $module, false);
$transferFocus->mode = 'edit';
$transferFocus->id = $transferid;
$transferFocus->mark_deleted($transferid);
}
// Update access token with selected contact
$this->updateAccessTokenContact($contactid, $accesstoken, $maincontact);
$this->log($contactid, 'CONTACT_MERGED', array());
}
public function lockContact($email) {
global $adb;
foreach ($this->emailFields as $module => $field) {
if (self::isEnabledForModule($module)) {
$focus = CRMEntity::getInstance($module);
$update = array('gdpr_sentdate = ?' => date('Y-m-d H:i:s'));
foreach ($this->gdprFields as $gdprField) {
$update["$gdprField = ?"] = 0;
}
$adb->pquery("UPDATE {$field['tablename']} SET " . implode(',', array_keys($update)) . " WHERE {$field['columnname']} = ?", array(array_values($update), $email));
}
}
$newsletterFocus = CRMEntity::getInstance('Newsletter');
$newsletterFocus->lockReceivingNewsletter($email, 'lock');
}
protected function sendConfirmEmail($contactData, $accesstoken, $token, &$error) {
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$email = $contactData['email'];
$templateid = $this->templates['confirm_update_template'];
$newsletterFocus = CRMEntity::getInstance('Newsletter');
$gdprLink = $newsletterFocus->gdpr_link;
$r = array(
'$custom||gdpr_update_confirm_link$' => $gdprLink.'?action=confirm-update&accesstoken='.urlencode($accesstoken).'&token='.urlencode($token),
);
$status = $this->sendEmailTemplate($module, $contactid, $email, $templateid, $r);
if ($status) {
$this->log($contactid, 'CONFIRM_EMAIL_SENT', array());
} else {
$this->log($contactid, 'CONFIRM_EMAIL_NOT_SENT', array());
}
return $status;
}
public function sendContactNotifyChangeEmail($module, $contactid) {
$templateid = $this->templates['contact_updated_template'];
$focus = CRMEntity::getInstance($module);
$ret = $focus->retrieve_entity_info_no_html($contactid, $module, false);
$focus->id = $contactid;
$emailField = $this->emailFields[$module]['fieldname'];
$email = $focus->column_fields[$emailField];
$newsletterFocus = CRMEntity::getInstance('Newsletter');
$gdprLink = $newsletterFocus->gdpr_link;
$cid = urlencode(base64_encode("C|".$email."|".$module));
$r = array(
'$custom||gdpr_verify_link$' => $gdprLink.'?action=verify&cid='.$cid,
);
$status = $this->sendEmailTemplate($module, $contactid, $email, $templateid, $r);
if ($status) {
$this->log($contactid, 'NOTIFY_CHANGE_EMAIL_SENT', array());
} else {
$this->log($contactid, 'NOTIFY_CHANGE_EMAIL_NOT_SENT', array());
}
return $status;
}
protected function sendEmailTemplate($module, $contactid, $email, $templateid, $replacements = array()) {
global $adb, $table_prefix;
$emailTemplateId = $templateid;
$result = $adb->pquery("SELECT subject, body FROM {$table_prefix}_emailtemplates WHERE templateid = ?", array($emailTemplateId));
$tsubject = $adb->query_result_no_html($result, 0, 'subject');
$tdescription = $adb->query_result_no_html($result, 0, 'body');
if (empty($tsubject) || empty($tdescription) || empty($emailTemplateId)) return false;
$r = $replacements;
$tdescription = str_replace(array_keys($r), array_values($r), $tdescription);
$tdescription = getMergedDescription($tdescription, $contactid, $module);
$success = send_mail('', $email, $this->senderName, $this->senderEmail, $tsubject, $tdescription);
return $success;
}
protected function formatOutputData($data, $contactData, $options = array()) {
$out = array_merge(array(), $data);
$options = array_merge(array('include_contacts_data' => true), $options);
if ($options && $options['include_contacts_data']) {
$module = $contactData['module'];
$contactid = $contactData['contactid'];
$contactEmail = $contactData['email'];
$column = $contactData['email_field']['tablename'].'.'.$contactData['email_field']['columnname'];
$value = $contactEmail;
$duplicates = $this->getContactDuplicates($module, $contactid, $column, $value);
$out = array_merge(array('email' => $contactEmail, 'contact' => $contactData['available_data'], 'duplicates' => $duplicates, 'business_id' => $contactData['business_id']), $out);
}
return $out;
}
protected function log($contactid, $operation, $data = array()) {
global $adb, $table_prefix;
if (empty($operation)) return;
$params = array(
'logid' => $adb->getUniqueID($this->logTable),
'contactid' => $contactid,
'timestamp' => date('Y-m-d H:i:s'),
'operation' => $operation,
'operation_remote_addr' => getIp(),
'data' => Zend_Json::encode($data),
);
$columns = array_keys($params);
$adb->format_columns($columns);
$adb->pquery("INSERT INTO {$this->logTable} (" . implode(',', $columns) . ") VALUES (" . generateQuestionMarks($params) . ")", $params);
}
public function generateToken($length = 32) {
return base64_encode(crypt_random_string($length));
}
public function error($message, $data = array()) {
$out = array_merge(array('success' => false, 'error' => $message, 'cid' => $this->cid, 'cid_data' => $this->cidData), $data);
return $out;
}
public function success($data = array()) {
$out = array_merge(array('success' => true, 'cid' => $this->cid, 'cid_data' => $this->cidData), $data);
return $out;
}
protected function initCustomWebserviceOperations() {
$operations = array();
$parameters = array('contactid' => 'string');
$operations['gdpr_authtoken'] = array('file' => 'include/utils/GDPRWS/webservices/AuthToken.php', 'handler' => 'gdpr_authtoken', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('contactid' => 'string', 'authtoken' => 'string');
$operations['gdpr_sendverify'] = array('file' => 'include/utils/GDPRWS/webservices/SendVerify.php', 'handler' => 'gdpr_sendverify', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('contactid' => 'string', 'authtoken' => 'string');
$operations['gdpr_accesstoken'] = array('file' => 'include/utils/GDPRWS/webservices/AccessToken.php', 'handler' => 'gdpr_accesstoken', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('accesstoken' => 'string');
$operations['gdpr_checkaccesstoken'] = array('file' => 'include/utils/GDPRWS/webservices/CheckAccessToken.php', 'handler' => 'gdpr_checkaccesstoken', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('accesstoken' => 'string', 'data' => 'encoded');
$operations['gdpr_update'] = array('file' => 'include/utils/GDPRWS/webservices/Update.php', 'handler' => 'gdpr_update', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('accesstoken' => 'string', 'maincontact' => 'int', 'otherids' => 'encoded');
$operations['gdpr_mergecontact'] = array('file' => 'include/utils/GDPRWS/webservices/Merge.php', 'handler' => 'gdpr_mergecontact', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('accesstoken' => 'string');
$operations['gdpr_fields'] = array('file' => 'include/utils/GDPRWS/webservices/Fields.php', 'handler' => 'gdpr_fields', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('accesstoken' => 'string', 'token' => 'string');
$operations['gdpr_confirmupdate'] = array('file' => 'include/utils/GDPRWS/webservices/ConfirmUpdate.php', 'handler' => 'gdpr_confirmupdate', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('accesstoken' => 'string');
$operations['gdpr_delete'] = array('file' => 'include/utils/GDPRWS/webservices/Delete.php', 'handler' => 'gdpr_delete', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('contactid' => 'string');
$operations['gdpr_privacypolicy'] = array('file' => 'include/utils/GDPRWS/webservices/PrivacyPolicy.php', 'handler' => 'gdpr_privacypolicy', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('contactid' => 'string', 'subject' => 'string', 'description' => 'string');
$operations['gdpr_supportrequest'] = array('file' => 'include/utils/GDPRWS/webservices/SupportRequest.php', 'handler' => 'gdpr_supportrequest', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$parameters = array('contactid' => 'string');
$operations['gdpr_sendprivacypolicy'] = array('file' => 'include/utils/GDPRWS/webservices/SendPrivacyPolicy.php', 'handler' => 'gdpr_sendprivacypolicy', 'reqtype' => 'POST', 'prelogin' => '0', 'parameters' => $parameters);
$this->registerCustomWebservices($operations);
}
protected function registerCustomWebservices($operations) {
global $adb, $table_prefix;
foreach ($operations as $operationName => $operationInfo) {
$exists = $adb->pquery("SELECT operationid FROM {$table_prefix}_ws_operation WHERE name = ?", array($operationName));
if ($exists && $adb->num_rows($exists) < 1) {
$operationId = $adb->getUniqueId($table_prefix . '_ws_operation');
$params = array(
'operationid' => $operationId,
'name' => $operationName,
'handler_path' => $operationInfo['file'],
'handler_method' => $operationInfo['handler'],
'type' => $operationInfo['reqtype'],
'prelogin' => $operationInfo['prelogin']
);
$columns = array_keys($params);
$adb->format_columns($columns);
$adb->pquery("INSERT INTO {$table_prefix}_ws_operation (" . implode(',', $columns) . ") VALUES (" . generateQuestionMarks($params) . ")", $params);
$parameters = $operationInfo['parameters'];
$parameterIndex = 0;
foreach ($parameters as $parameterName => $parameterType) {
$params = array(
'operationid' => $operationId,
'name' => $parameterName,
'type' => $parameterType,
'sequence' => ($parameterIndex + 1)
);
$columns = array_keys($params);
$adb->format_columns($columns);
$adb->pquery("INSERT INTO {$table_prefix}_ws_operation_parameters (" . implode(',', $columns) . ") VALUES (" . generateQuestionMarks($params) . ")", $params);
++$parameterIndex;
}
}
}
}
// crmv@194712
public function updateConvertLead() {
global $adb, $table_prefix;
$gdprFieldMappingList = $this->getGdprFieldMappingList();
$fieldMap = array();
$fieldIds = array('Leads' => array(), 'Accounts' => array(), 'Contacts' => array(), 'Potentials' => array());
foreach ($gdprFieldMappingList as $gdprField) {
$fieldMap[] = $gdprField;
if (!empty($gdprField[0])) {
$fieldIds['Leads'][$gdprField[0]] = null;
}
if (!empty($gdprField[1])) {
$fieldIds['Accounts'][$gdprField[1]] = null;
}
if (!empty($gdprField[2])) {
$fieldIds['Contacts'][$gdprField[2]] = null;
}
if (!empty($gdprField[3])) {
$fieldIds['Potentials'][$gdprField[3]] = null;
}
}
foreach ($fieldIds as $module => $fields) {
if (!empty($fields)) {
$fieldQuery = "SELECT fieldname, fieldid FROM {$table_prefix}_field WHERE tabid = ? AND fieldname IN (" . generateQuestionMarks($fields) . ")";
$fieldRes = $adb->pquery($fieldQuery, array(getTabid($module), array_keys($fields)));
if (!!$fieldRes && $adb->num_rows($fieldRes) > 0) {
while ($row = $adb->fetchByAssoc($fieldRes, -1, false)) {
$fieldIds[$module][$row['fieldname']] = $row['fieldid'];
}
}
}
}
foreach ($fieldMap as $values) {
$leadfid = $fieldIds['Leads'][$values[0]];
if (empty($leadfid)) continue;
$checkMappingQuery = "SELECT 1 FROM {$table_prefix}_convertleadmapping WHERE leadfid = ?";
$checkMappingRes = $adb->pquery($checkMappingQuery, array($leadfid));
if (!!$checkMappingRes && $adb->num_rows($checkMappingRes) > 0) {
continue;
}
$accountfid = $fieldIds['Accounts'][$values[1]];
if (empty($accountfid)) $accountfid = null;
$contactfid = $fieldIds['Contacts'][$values[2]];
if (empty($contactfid)) $contactfid = null;
$potentialfid = $fieldIds['Potentials'][$values[3]];
if (empty($potentialfid)) $potentialfid = null;
$insertQuery = "INSERT INTO {$table_prefix}_convertleadmapping (cfmid, leadfid, accountfid, contactfid, potentialfid) VALUES (?, ?, ?, ?, ?)";
$adb->pquery($insertQuery, array($adb->getUniqueID($table_prefix . "_convertleadmapping"), $leadfid, $accountfid, $contactfid, $potentialfid));
}
}
// crmv@194712e
public function checkNoConfirmDeletion() {
global $adb, $table_prefix;
if (empty($this->noconfirm_deletion_months)) $this->noconfirm_deletion_months = $this->default_noconfirm_deletion_months;
$deletion_time = date('Y-m-d H:i:s', strtotime("-{$this->noconfirm_deletion_months} months"));
foreach ($this->emailFields as $module => $field) {
if (self::isEnabledForModule($module)) {
$focus = CRMEntity::getInstance($module);
$result = $adb->pquery("SELECT {$focus->tab_name_index[$field['tablename']]} as \"crmid\", {$field['columnname']} as \"email\" FROM {$field['tablename']} WHERE gdpr_privacypolicy = ? and gdpr_deleted = ? and gdpr_sentdate is not null and gdpr_sentdate <> ? and gdpr_sentdate < ?", array(0,0, '0000-00-00 00:00:00', $adb->formatDate($deletion_time, true))); // crmv@182782
if ($result && $adb->num_rows($result) > 0) {
while ($row = $adb->fetchByAssoc($result)) {
$this->applyContactDelete(array('module' => $module, 'contactid' => $row['crmid'], 'email' => $row['email']), null, null);
}
}
}
}
}
protected function notifyAnonymize($focus) {
$subject = getTranslatedString('LBL_GDPR_NOTIFY_ANONYMIZE_SUBJECT', 'Settings');
$description = getTranslatedString('LBL_GDPR_NOTIFY_ANONYMIZE_BODY', 'Settings');
$description = sprintf($description, $focus->column_fields['firstname'], $focus->column_fields['lastname'], $focus->column_fields['email'], date('Y-m-d', strtotime("+{$this->noconfirm_deletion_months} months")));
$success = send_mail('', $this->senderEmail, $this->senderName, $this->senderEmail, $subject, $description);
return $success;
}
public function getBusinessId($crmid, $module, $email = '') {
global $adb, $table_prefix, $current_user;
$BU = BusinessUnit::getInstance();
if ($module === 'Contacts' && !BusinessUnit::isEnabledForModule($module)) {
$contactFocus = CRMEntity::getInstance('Contacts');
$contactFocus->id = $crmid;
$s = $contactFocus->retrieve_entity_info($crmid, 'Contacts', false);
if (empty($s)) {
$accountId = intval($contactFocus->column_fields['account_id']);
if ($accountId > 0) {
$module = 'Accounts';
$crmid = $accountId;
}
}
}
$business = BusinessUnit::getBusinessForId($crmid);
$useDefaultBusiness = false;
if (!empty($email)) {
if (BusinessUnit::isEnabledForModule($module) && isset($this->emailFields[$module])) {
$focus = CRMEntity::getInstance($module);
$tableIndex = $focus->table_index;
$column = $this->emailFields[$module]['tablename'].'.'.$this->emailFields[$module]['columnname'];
$businessByEmail = $adb->pquery("SELECT DISTINCT(bu_mc) FROM {$this->emailFields[$module]['tablename']} INNER JOIN {$table_prefix}_crmentity ON {$this->emailFields[$module]['tablename']}.{$tableIndex} = {$table_prefix}_crmentity.crmid WHERE {$table_prefix}_crmentity.deleted = 0 AND {$column} = ?", array($email));
if ($businessByEmail && $adb->num_rows($businessByEmail) > 1) {
$useDefaultBusiness = true;
}
}
}
$businessId = 0;
if ($business) {
$vteProp = VTEProperties::getInstance();
$generalSettings = $vteProp->get('services.gdpr.general_settings');
$businessId = $generalSettings['default_business'];
if ((count($business) === 1 && !empty($business[0])) && !$useDefaultBusiness) {
$businessInfo = $BU->getBusinessInfoByName($business[0]);
$businessId = $businessInfo['organizationid'];
} else {
$businessId = $generalSettings['default_business'];
}
} else {
$businessList = $BU->getBusinessList();
if (!empty($businessList)) {
$businessId = $businessList[0]['organizationid'];
}
}
return $businessId;
}
// crmv@194712
public function getGdprFieldMappingList() {
$fields = array();
$gdprFields = $this->gdprFields;
foreach ($gdprFields as $gdprField) {
$fields[] = array($gdprField, null, $gdprField, null);
$fields[] = array($gdprField.'_checkedtime', null, $gdprField.'_checkedtime', null);
$fields[] = array($gdprField.'_remote_addr', null, $gdprField.'_remote_addr', null);
}
$fields[] = array('gdpr_deleted', null, 'gdpr_deleted', null);
$fields[] = array('gdpr_deleted_checkedtime', null, 'gdpr_deleted_checkedtime', null);
$fields[] = array('gdpr_deleted_remote_addr', null, 'gdpr_deleted_remote_addr', null);
$fields[] = array('gdpr_sentdate', null, 'gdpr_sentdate', null);
return $fields;
}
// crmv@194712e
}