- Added comprehensive AI Assistant system (aiassist/ directory): * Vector search and embedding capabilities * Typebot proxy integration * Elastic search functionality * Message classification and chat history * MCP proxy for external integrations - Implemented Court Status API (GetCourtStatus.php): * Real-time court document status checking * Integration with external court systems * Comprehensive error handling and logging - Enhanced S3 integration: * Improved file backup system with metadata * Batch processing capabilities * Enhanced error logging and recovery * Copy operations with URL fixing - Added Telegram contact creation API - Improved error logging across all modules - Enhanced callback system for AI responses - Extensive backup file storage with timestamps - Updated documentation and README files - File storage improvements: * Thousands of backup files with proper metadata * Fix operations for broken file references * Project-specific backup and recovery systems * Comprehensive file integrity checking Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
1433 lines
48 KiB
PHP
1433 lines
48 KiB
PHP
<?php
|
|
/* * *******************************************************************************
|
|
* The content of this file is subject to the ITS4YouEmailMarketing license.
|
|
* ("License"); You may not use this file except in compliance with the License
|
|
* The Initial Developer of the Original Code is IT-Solutions4You s.r.o.
|
|
* Portions created by IT-Solutions4You s.r.o. are Copyright(C) IT-Solutions4You s.r.o.
|
|
* All Rights Reserved.
|
|
* ****************************************************************************** */
|
|
|
|
class ITS4YouEmailMarketing_Record_Model extends Vtiger_Record_Model
|
|
{
|
|
public static $EMAILS_MODULE = 'ITS4YouEmails';
|
|
public static $OLD_EMAILS_MODULE = 'Emails';
|
|
public static $statusField = 'emailmarketingstatus';
|
|
public static $statusError = 'Error';
|
|
public static $VALID_EMAIL_STATUS = 'ValidEmail';
|
|
public static $EMPTY_EMAIL_STATUS = 'EmptyEmail';
|
|
public static $INVALID_EMAIL_STATUS = 'InvalidEmail';
|
|
public static $USED_EMAIL_STATUS = 'UsedEmail';
|
|
public static $UNSUBSCRIBED_EMAIL_STATUS = 'UnsubscribedUser';
|
|
public static $DUPLICATE_EMAIL_STATUS = 'DuplicateUser';
|
|
public static $SELECTED_EMAIL_STATUS = 'SelectedEmail';
|
|
protected $usedEmails = array();
|
|
protected $usedSubscribers = array();
|
|
protected $unSubscribedEmails;
|
|
protected $relatedRecords;
|
|
protected $emailTrack;
|
|
protected $previewEmail = false;
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $campaignTables = array(
|
|
'Contacts' => array(
|
|
'table' => 'vtiger_campaigncontrel',
|
|
'name' => 'contactid',
|
|
),
|
|
'Leads' => array(
|
|
'table' => 'vtiger_campaignleadrel',
|
|
'name' => 'leadid',
|
|
),
|
|
'Accounts' => array(
|
|
'table' => 'vtiger_campaignaccountrel',
|
|
'name' => 'accountid',
|
|
),
|
|
);
|
|
protected $templateSourceModules = array(
|
|
'Newsletter' => 'ITS4YouNewsletter',
|
|
'EMAILMaker' => 'EMAILMaker',
|
|
);
|
|
protected $sendToEmail = array();
|
|
protected $moduleModels = array();
|
|
protected $recordModels = array();
|
|
protected $content;
|
|
|
|
public static function getProcessedContent($content)
|
|
{
|
|
// remove script tags from whole html content
|
|
return preg_replace('#<script(.*?)>(.*?)</script>#is', '', $content);
|
|
}
|
|
|
|
public static function copyConfig($fromRecord, $toRecord)
|
|
{
|
|
/**
|
|
* @var ITS4YouEmailMarketing_Record_Model $duplicateRecord
|
|
* @var ITS4YouEmailMarketing_Record_Model $record
|
|
*/
|
|
$duplicateRecord = Vtiger_Record_Model::getInstanceById($fromRecord);
|
|
$modules = $duplicateRecord->getConfig();
|
|
|
|
$record = Vtiger_Record_Model::getInstanceById($toRecord);
|
|
|
|
foreach ($modules as $module => $fields) {
|
|
foreach ($fields as $field => $config) {
|
|
$record->setConfig($module, $field);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function setConfig($module, $field)
|
|
{
|
|
$recordId = $this->getId();
|
|
$adb = PearDatabase::getInstance();
|
|
$adb->pquery('INSERT INTO its4you_emailmarketing_config (crmid, module, field) VALUES (?,?,?)', array($recordId, $module, $field));
|
|
}
|
|
|
|
/**
|
|
* @param string $mode
|
|
* @param int $fromRecordId
|
|
* @param int $toRecordId
|
|
* @return void
|
|
*/
|
|
public static function copyRecipients($mode, $fromRecordId, $toRecordId)
|
|
{
|
|
/** @var ITS4YouEmailMarketing_Record_Model $toRecord */
|
|
$toRecord = Vtiger_Record_Model::getInstanceById($toRecordId);
|
|
$toModule = $toRecord->getModule();
|
|
$subModules = $toRecord->getSubscribersModules();
|
|
|
|
$sql = 'SELECT * FROM vtiger_crmentityrel WHERE module=? AND crmid=? AND relmodule IN (' . generateQuestionMarks($subModules) . ') ';
|
|
$params = ['ITS4YouEmailMarketing', $fromRecordId, $subModules];
|
|
|
|
if ('NotOpened' === $mode) {
|
|
$sql .= ' AND relcrmid NOT IN (' . self::getAccessedRecipientIdsQuery($fromRecordId, false) . ') ';
|
|
}
|
|
|
|
if ('OpenRecipients' === $mode) {
|
|
$sql .= ' AND relcrmid IN (' . self::getAccessedRecipientIdsQuery($fromRecordId, false) . ') ';
|
|
}
|
|
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery($sql, $params);
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
$recipientId = intval($row['relcrmid']);
|
|
|
|
if (!$recipientId || !isRecordExists($recipientId)) {
|
|
continue;
|
|
}
|
|
|
|
$recipientRecord = Vtiger_Record_Model::getInstanceById($recipientId, $row['relmodule']);
|
|
/** @var Vtiger_Relation_Model $recipientRelation */
|
|
$recipientRelation = Vtiger_Relation_Model::getInstance($toModule, $recipientRecord->getModule());
|
|
|
|
if ($recipientRelation) {
|
|
$recipientRelation->addRelation($toRecord->getId(), $recipientRecord->getId());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $marketingId
|
|
* @return string
|
|
*/
|
|
public static function getAccessedRecipientIdsQuery($marketingId, $accessCount = true)
|
|
{
|
|
$marketingId = intval($marketingId);
|
|
$accessCountQuery = $accessCount ? ', COUNT(recipient_id) as access_count' : '';
|
|
|
|
return 'SELECT recipient_id' . $accessCountQuery . '
|
|
FROM its4you_emails
|
|
INNER JOIN its4you_emails_access ON its4you_emails_access.mail_id=its4you_emails.its4you_emails_id
|
|
INNER JOIN vtiger_shorturls ON vtiger_shorturls.uid=its4you_emails_access.access_id
|
|
WHERE its4you_emails.related_to=' . $marketingId . ' AND vtiger_shorturls.handler_data LIKE "%open%" GROUP BY recipient_id';
|
|
}
|
|
|
|
public function setRelationsFromList($customViewId, $sourceModule, $entity)
|
|
{
|
|
$return = false;
|
|
$moduleModel = $this->getModule();
|
|
$recordId = $this->getId();
|
|
$recordIds = array();
|
|
|
|
if (vtlib_isModuleActive($sourceModule)) {
|
|
if ('Campaigns' == $sourceModule) {
|
|
if (isRecordExists($customViewId)) {
|
|
$recordIds = $this->getCampaignRelatedRecords($customViewId, $entity);
|
|
$sourceModule = $entity;
|
|
}
|
|
} else {
|
|
$customView = CustomView_Record_Model::getInstanceById($customViewId);
|
|
$recordIds = $customView->getRecordIds();
|
|
}
|
|
|
|
$sourceModel = Vtiger_Module_Model::getInstance($sourceModule);
|
|
$relationModel = Vtiger_Relation_Model::getInstance($moduleModel, $sourceModel);
|
|
|
|
foreach ($recordIds as $contactId) {
|
|
$relationModel->addRelation($recordId, $contactId);
|
|
}
|
|
|
|
$return = true;
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
public function getCampaignRelatedRecords($record, $module)
|
|
{
|
|
$related = array();
|
|
|
|
if (vtlib_isModuleActive($module)) {
|
|
$adb = PearDatabase::getInstance();
|
|
$sql = $this->getCampaignQuery($module);
|
|
$result = $adb->pquery($sql, array($record));
|
|
$name = $this->campaignTables[$module]['name'];
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
$related[] = $row[$name];
|
|
}
|
|
}
|
|
|
|
return $related;
|
|
}
|
|
|
|
/**
|
|
* @param string $module
|
|
* @return string
|
|
*/
|
|
public function getCampaignQuery($module)
|
|
{
|
|
return sprintf('SELECT * FROM %s WHERE campaignid=?', $this->campaignTables[$module]['table']);
|
|
}
|
|
|
|
/**
|
|
* @param Vtiger_Record_Model $recordModel
|
|
* @return void
|
|
*/
|
|
public function addRelation($recordModel)
|
|
{
|
|
$moduleModel = $this->getModule();
|
|
$relationModel = Vtiger_Relation_Model::getInstance($moduleModel, $recordModel->getModule());
|
|
|
|
if ($relationModel) {
|
|
$relationModel->addRelation($this->getId(), $recordModel->getId());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $relatedName
|
|
* @param int|false $campaignId
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function getCustomViews($relatedName, $campaignId = false)
|
|
{
|
|
$views = array();
|
|
$customViewsPageCount = 0;
|
|
$customViewsPage = $this->getCustomViewPage();
|
|
|
|
if ('Campaigns' == $relatedName) {
|
|
if (!!$campaignId && isRecordExists($campaignId)) {
|
|
$emailRelatedModules = getEmailRelatedModules();
|
|
$campaignModel = Vtiger_Module_Model::getInstance($relatedName);
|
|
$campaignRelations = $campaignModel->getRelations();
|
|
|
|
foreach ($campaignRelations as $relation) {
|
|
$relTabid = $relation->get('related_tabid');
|
|
$parentModule = $relation->get('modulename');
|
|
$parentLabel = vtranslate($parentModule, $parentModule);
|
|
|
|
if (in_array($parentModule, $emailRelatedModules)) {
|
|
$countIds = $this->getCampaignCount($campaignId, $parentModule);
|
|
|
|
if ($countIds > 0) {
|
|
$views[$relTabid] = array(
|
|
'cvid' => $campaignId,
|
|
'viewname' => $parentLabel,
|
|
'entitytype' => $parentModule,
|
|
'countids' => $countIds,
|
|
'loaded' => $this->getCampaignLoadedCount($campaignId, $parentModule),
|
|
'url' => 'index.php?module=' . $relatedName . '&relatedModule=' . $parentModule . '&view=Detail&record=' . $campaignId . '&mode=showRelatedList',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$views = 'NOT_RECORD';
|
|
}
|
|
} else {
|
|
ITS4YouEmailMarketing_CustomView_Model::$custom_views_page = $customViewsPage;
|
|
|
|
$customViewsPageCount = ITS4YouEmailMarketing_CustomView_Model::getAllCount($relatedName);
|
|
$customViews = ITS4YouEmailMarketing_CustomView_Model::getAll($relatedName);
|
|
|
|
foreach ($customViews as $customView) {
|
|
$data = $customView->getData();
|
|
$cvId = $data['cvid'];
|
|
$cvCount = $this->getCustomViewCount($customView);
|
|
$views[$cvId] = array(
|
|
'cvid' => $cvId,
|
|
'viewname' => $data['viewname'],
|
|
'entitytype' => $data['entitytype'],
|
|
'countids' => $cvCount,
|
|
'loaded' => $this->getLoadedCount($customView),
|
|
'url' => 'index.php?module=' . $relatedName . '&view=List&viewname=' . $cvId,
|
|
);
|
|
}
|
|
}
|
|
|
|
if (empty($views)) {
|
|
$views = 'NOT_VIEWS';
|
|
}
|
|
|
|
return array(
|
|
'total_records' => $this->getSubscribersCount(),
|
|
'custom_views_pages' => ceil($customViewsPageCount / 10),
|
|
'custom_views_page' => $customViewsPage,
|
|
'views' => $views,
|
|
);
|
|
}
|
|
|
|
public function getCustomViewPage()
|
|
{
|
|
$value = $this->get('custom_views_page');
|
|
|
|
return !empty($value) ? $value : 1;
|
|
}
|
|
|
|
/**
|
|
* @parma int $record
|
|
* @param string $module
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getCampaignCount($record, $module)
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery($this->getCampaignCountQuery($record, $module), array($record));
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
/**
|
|
* @param int $record
|
|
* @param string $module
|
|
* @return string
|
|
*/
|
|
public function getCampaignCountQuery($record, $module)
|
|
{
|
|
$tableId = implode('.', array($this->campaignTables[$module]['table'], $this->campaignTables[$module]['name']));
|
|
|
|
return sprintf('SELECT count(%s) as count FROM %s WHERE campaignid=?', $tableId, $this->campaignTables[$module]['table']);
|
|
}
|
|
|
|
/**
|
|
* @param int $record
|
|
* @param string $module
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getCampaignLoadedCount($record, $module)
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$tableId = implode('.', array($this->campaignTables[$module]['table'], $this->campaignTables[$module]['name']));
|
|
$query = $this->getCampaignCountQuery($record, $module);
|
|
$query .= ' AND ' . $tableId . ' IN (SELECT relcrmid FROM vtiger_crmentityrel WHERE module=? AND crmid=? AND relcrmid=' . $tableId . ')';
|
|
|
|
$result = $adb->pquery($query, array($record, $this->getModuleName(), $this->getId()));
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
/**
|
|
* @param object $view
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getCustomViewCount($view)
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery($this->getCustomViewCountQuery($view), array());
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
public function getCustomViewCountQuery($view)
|
|
{
|
|
$query = $this->getCustomViewQuery($view);
|
|
$split = preg_split('/\ FROM\ /', $query);
|
|
$split[0] = sprintf('SELECT count(%s.%s) as count', $view->getModule()->basetable, $view->getModule()->basetableid);
|
|
|
|
return implode(' FROM ', $split);
|
|
}
|
|
|
|
/**
|
|
* @param CustomView_Record_Model $view
|
|
* @return string
|
|
*/
|
|
public function getCustomViewQuery($view)
|
|
{
|
|
$cvId = $view->getId();
|
|
$moduleModel = $view->getModule();
|
|
$listViewModel = Vtiger_ListView_Model::getInstance($moduleModel->getName(), $cvId);
|
|
/** @var EnhancedQueryGenerator|QueryGenerator $queryGenerator */
|
|
$queryGenerator = $listViewModel->get('query_generator');
|
|
|
|
return $queryGenerator->getQuery();
|
|
}
|
|
|
|
/**
|
|
* @param object $view
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getLoadedCount($view)
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$query = $this->getCustomViewCountQuery($view);
|
|
$tableId = implode('.', array($view->getModule()->basetable, $view->getModule()->basetableid));
|
|
$query .= sprintf(' AND %s IN (SELECT relcrmid FROM vtiger_crmentityrel WHERE module=? AND crmid=? AND relcrmid=%s)', $tableId, $tableId);
|
|
$result = $adb->pquery($query, array($this->getModuleName(), $this->getId()));
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getSubscribersCount()
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$subscriberModules = $this->getSubscribersModules();
|
|
$query = 'SELECT count(vtiger_crmentityrel.relcrmid) AS count FROM vtiger_crmentityrel WHERE crmid=? AND module=? AND relmodule IN (' . generateQuestionMarks($subscriberModules) . ') ';
|
|
$params = [$this->getId(), $this->getModule()->getName(), $subscriberModules];
|
|
$result = $adb->pquery($query, $params);
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getSubscribersModules()
|
|
{
|
|
return [$this->getEmailMarketingModule()];
|
|
}
|
|
|
|
/**
|
|
* @param bool $emails
|
|
* @return true
|
|
*/
|
|
public function deleteRelations($emails = false)
|
|
{
|
|
if ($emails) {
|
|
$relatedModules = ['Emails', 'ITS4YouEmails'];
|
|
} else {
|
|
$relatedModules = $this->getEmailMarketingModules();
|
|
}
|
|
|
|
$this->deleteRelationsForModules($relatedModules);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getEmailMarketingModules()
|
|
{
|
|
$field = new ITS4YouEmailMarketing_Field_Model();
|
|
|
|
return $field->getEmailMarketingModules();
|
|
}
|
|
|
|
/**
|
|
* @param array $relatedModules
|
|
* @return void
|
|
*/
|
|
public function deleteRelationsForModules($relatedModules)
|
|
{
|
|
$module = $this->getModule()->getName();
|
|
$record = $this->getId();
|
|
|
|
$adb = PearDatabase::getInstance();
|
|
$adb->pquery('DELETE FROM vtiger_crmentityrel WHERE module=? AND crmid=? AND relmodule IN (' . generateQuestionMarks($relatedModules) . ') ', array($module, $record, $relatedModules));
|
|
}
|
|
|
|
public function getEmailFields()
|
|
{
|
|
$fields = array();
|
|
$emailRelated = getEmailRelatedModules();
|
|
|
|
foreach ($emailRelated as $moduleName) {
|
|
$emailFields = array();
|
|
$moduleModel = Vtiger_Module_Model::getInstance($moduleName);
|
|
$fieldModels = $moduleModel->getFields();
|
|
|
|
foreach ($fieldModels as $fieldName => $field) {
|
|
if ((strcasecmp($field->get('typeofdata'), 'e') === 0) || $field->get('uitype') === '13') {
|
|
$emailFields[$fieldName] = array(
|
|
'label' => vtranslate($field->get('label'), $moduleName),
|
|
'module' => $field->getModule()->getName(),
|
|
);
|
|
}
|
|
}
|
|
|
|
$fields[$moduleName] = $emailFields;
|
|
}
|
|
|
|
return $fields;
|
|
}
|
|
|
|
public function deleteConfig($module, $field)
|
|
{
|
|
$recordId = $this->getId();
|
|
$adb = PearDatabase::getInstance();
|
|
$adb->pquery('DELETE FROM its4you_emailmarketing_config WHERE crmid=? AND module=? AND field=?', array($recordId, $module, $field));
|
|
}
|
|
|
|
public function getEmailPreview($email)
|
|
{
|
|
$record = $this->getId();
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery('SELECT * FROM its4you_emailmarketing_emails WHERE emailmarketingid=? AND emailsid=?', array($record, $email));
|
|
|
|
$row = $adb->fetchByAssoc($result, 0);
|
|
|
|
return $row['description'];
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
* @var int $limitStart
|
|
*/
|
|
public function getSendEmailRecords($limitStart = 0)
|
|
{
|
|
$limitEnd = $limitStart + $this->getCronLimit();
|
|
$related = array();
|
|
$adb = PearDatabase::getInstance();
|
|
$record = $this->getId();
|
|
$module = $this->getModule()->getName();
|
|
$query = 'SELECT relcrmid,relmodule
|
|
FROM vtiger_crmentityrel,vtiger_crmentity
|
|
WHERE vtiger_crmentityrel.relcrmid=vtiger_crmentity.crmid AND
|
|
vtiger_crmentity.deleted=? AND
|
|
vtiger_crmentityrel.module=? AND
|
|
vtiger_crmentityrel.crmid=? AND
|
|
vtiger_crmentityrel.relmodule != ? AND
|
|
vtiger_crmentityrel.relcrmid NOT IN (
|
|
SELECT DISTINCT REPLACE(idlists, "@1|", "") as idlists
|
|
FROM vtiger_crmentityrel,vtiger_emaildetails
|
|
WHERE vtiger_crmentityrel.relcrmid=vtiger_emaildetails.emailid AND
|
|
vtiger_crmentityrel.crmid = ? AND
|
|
vtiger_crmentityrel.module = ? AND
|
|
vtiger_crmentityrel.relmodule = ?
|
|
)
|
|
LIMIT ' . $limitStart . ',' . $limitEnd;
|
|
|
|
$params = ['0', $module, $record, 'Emails', $record, $module, 'Emails'];
|
|
$result = $adb->pquery($query, $params);
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
$relId = $row['relcrmid'];
|
|
$related[$relId] = $row;
|
|
}
|
|
|
|
return $related;
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
*/
|
|
public function getCronLimit()
|
|
{
|
|
require_once 'vtlib/Vtiger/Cron.php';
|
|
$cron = Vtiger_Cron::getInstance($this->getModuleName());
|
|
|
|
if ($cron) {
|
|
$cronFrequency = $cron->getFrequency();
|
|
|
|
if ($cronFrequency) {
|
|
return ceil($cronFrequency / 3600 * $this->getSendHourly());
|
|
}
|
|
}
|
|
|
|
return $this->getSendHourly();
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
*/
|
|
public function getSendHourly()
|
|
{
|
|
return !$this->isEmpty('sendhourly') ? intval($this->get('sendhourly')) : 1000;
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getSendEmailCount()
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$query = str_replace('SELECT * ', 'SELECT count(relcrmid) as count ', $this->getEmailRelSql());
|
|
$result = $adb->pquery($query, [$this->getId(), $this->getEmailsModule()]);
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getEmailRelSql()
|
|
{
|
|
return 'SELECT * FROM vtiger_crmentityrel,its4you_emails,vtiger_crmentity
|
|
WHERE vtiger_crmentityrel.relcrmid=vtiger_crmentity.crmid
|
|
AND vtiger_crmentityrel.relcrmid=its4you_emails.its4you_emails_id
|
|
AND vtiger_crmentity.deleted=0
|
|
AND vtiger_crmentityrel.crmid=?
|
|
AND vtiger_crmentityrel.relmodule=? ';
|
|
}
|
|
|
|
public function getEmailsModule()
|
|
{
|
|
if ($this->isEmpty('emails_module')) {
|
|
$this->set('emails_module', self::$OLD_EMAILS_MODULE);
|
|
}
|
|
|
|
return $this->get('emails_module');
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function getToEmailInfo()
|
|
{
|
|
$this->sendToEmail = array();
|
|
$relatedRecords = $this->getRecipientRecords();
|
|
|
|
foreach ($relatedRecords as $relatedRecord) {
|
|
$relCrmId = $relatedRecord['relcrmid'];
|
|
$relModule = $relatedRecord['relmodule'];
|
|
$recipientRecord = $this->getRecordModel($relCrmId, $relModule);
|
|
|
|
$this->sendToEmail[$relCrmId] = [
|
|
'status' => self::$SELECTED_EMAIL_STATUS,
|
|
'module' => $relModule,
|
|
'id' => $relCrmId,
|
|
'email' => '',
|
|
];
|
|
|
|
if (!$this->validateSubscriber($relCrmId)) {
|
|
$this->sendToEmail[$relCrmId]['status'] = self::$DUPLICATE_EMAIL_STATUS;
|
|
$this->usedSubscribers[] = $relCrmId;
|
|
} elseif (!$recipientRecord->get('emailoptout')) {
|
|
foreach ($this->getConfig($relModule) as $fieldName => $singleConfig) {
|
|
$email = $recipientRecord->get($fieldName);
|
|
|
|
if (empty($email)) {
|
|
$this->sendToEmail[$relCrmId]['status'] = self::$EMPTY_EMAIL_STATUS;
|
|
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
$this->sendToEmail[$relCrmId]['status'] = self::$INVALID_EMAIL_STATUS;
|
|
} elseif (!$this->validateEmail($email)) {
|
|
$this->sendToEmail[$relCrmId]['status'] = self::$USED_EMAIL_STATUS;
|
|
} else {
|
|
$this->sendToEmail[$relCrmId]['status'] = self::$VALID_EMAIL_STATUS;
|
|
$this->sendToEmail[$relCrmId]['email'] = $email;
|
|
$this->usedEmails[] = $email;
|
|
$this->usedSubscribers[] = $relCrmId;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
$this->sendToEmail[$relCrmId]['status'] = self::$UNSUBSCRIBED_EMAIL_STATUS;
|
|
}
|
|
}
|
|
|
|
return $this->sendToEmail;
|
|
}
|
|
|
|
public function deleteAllRelations()
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$adb->pquery('DELETE FROM vtiger_crmentityrel WHERE crmid=?', [$this->getId()]);
|
|
}
|
|
|
|
public function delete()
|
|
{
|
|
$this->deleteAllRelations();
|
|
$this->getModule()->deleteRecord($this);
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function getRecipientRecordsLimit()
|
|
{
|
|
$cronLimit = $this->getCronLimit();
|
|
$sentEmailsThisHour = $this->getSentEmailsThisHour();
|
|
$sendHourly = $this->getSendHourly();
|
|
$limit = $cronLimit;
|
|
|
|
if ($cronLimit + $sentEmailsThisHour > $sendHourly) {
|
|
$limit = $sendHourly - $sentEmailsThisHour;
|
|
|
|
if (1 > $limit) {
|
|
$limit = 1;
|
|
}
|
|
}
|
|
|
|
return $limit;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
* @throws Exception
|
|
* @var int $limitStart
|
|
*/
|
|
public function getRecipientRecords()
|
|
{
|
|
$limit = $this->getRecipientRecordsLimit();
|
|
$related = array();
|
|
$adb = PearDatabase::getInstance();
|
|
$record = $this->getId();
|
|
$module = $this->getModule()->getName();
|
|
$subscribersModule = $this->getEmailMarketingModule();
|
|
$query = 'SELECT relcrmid,relmodule
|
|
FROM vtiger_crmentityrel as recipientRel
|
|
LEFT JOIN vtiger_crmentity as recipientDetail ON recipientRel.relcrmid=recipientDetail.crmid
|
|
WHERE recipientDetail.deleted=?
|
|
AND recipientRel.module=?
|
|
AND recipientRel.crmid=?
|
|
AND recipientRel.relmodule=?
|
|
AND recipientRel.relcrmid NOT IN (SELECT recipient_id FROM its4you_emails WHERE related_to=?)
|
|
LIMIT ' . $limit;
|
|
$params = ['0', $module, $record, $subscribersModule, $record];
|
|
$result = $adb->pquery($query, $params);
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
$relId = $row['relcrmid'];
|
|
$related[$relId] = $row;
|
|
}
|
|
|
|
return $related;
|
|
}
|
|
|
|
public function getEmailMarketingModule()
|
|
{
|
|
return $this->get('emailmarketingmodule');
|
|
}
|
|
|
|
public function validateSubscriber($record)
|
|
{
|
|
if (in_array($record, $this->usedSubscribers) || $this->isUsedSubscriber($record)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param int $record
|
|
* @return bool
|
|
*/
|
|
public function isUsedSubscriber($record)
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$query = 'SELECT recipient_id FROM its4you_emails WHERE related_to=? AND recipient_id = ?';
|
|
$params = [$this->getId(), $record];
|
|
$result = $adb->pquery($query, $params);
|
|
|
|
return (bool)$adb->num_rows($result);
|
|
}
|
|
|
|
public function getRecordModel($record, $module)
|
|
{
|
|
if (!isset($this->recordModels[$record])) {
|
|
$this->recordModels[$record] = Vtiger_Record_Model::getInstanceById($record, $this->getModuleModel($module));
|
|
}
|
|
|
|
return $this->recordModels[$record];
|
|
}
|
|
|
|
public function getModuleModel($module)
|
|
{
|
|
if (!isset($this->moduleModels[$module])) {
|
|
$this->moduleModels[$module] = Vtiger_Module_Model::getInstance($module);
|
|
}
|
|
|
|
return $this->moduleModels[$module];
|
|
}
|
|
|
|
/**
|
|
* @param string|bool $module
|
|
* @return array
|
|
*/
|
|
public function getConfig($module = false)
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$query = 'SELECT * FROM its4you_emailmarketing_config WHERE crmid=? ';
|
|
$params = [$this->getId()];
|
|
|
|
if ($module) {
|
|
$query .= ' AND module=? ';
|
|
array_push($params, $module);
|
|
}
|
|
|
|
$result = $adb->pquery($query, $params);
|
|
$config = [];
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
$config[$row['module']][$row['field']] = $row;
|
|
}
|
|
|
|
|
|
return $module ? $config[$module] : $config;
|
|
}
|
|
|
|
public function validateEmail($email)
|
|
{
|
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL) || in_array($email, $this->usedEmails) || $this->isUsedEmail($email)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param string $email
|
|
* @return bool
|
|
*/
|
|
public function isUsedEmail($email)
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$query = 'SELECT to_email FROM its4you_emails WHERE related_to=? AND to_email LIKE ? AND recipient_id > 0';
|
|
$params = [$this->getId(), '%' . $email . '%'];
|
|
$result = $adb->pquery($query, $params);
|
|
|
|
return (bool)$adb->num_rows($result);
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
public function isAllowedLimit()
|
|
{
|
|
return $this->getSendHourly() > $this->getSentEmailsThisHour();
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function getSentEmailsThisHour()
|
|
{
|
|
$recordId = $this->getId();
|
|
$adb = PearDatabase::getInstance();
|
|
$dateTo = date('Y-m-d H:i:s');
|
|
$dateFrom = date('Y-m-d H:i:s', strtotime('-1 hour'));
|
|
$sql = 'SELECT count(vtiger_crmentityrel.crmid) as count
|
|
FROM vtiger_crmentity,vtiger_crmentityrel
|
|
WHERE vtiger_crmentity.crmid=vtiger_crmentityrel.relcrmid
|
|
AND vtiger_crmentity.createdtime >= ?
|
|
AND vtiger_crmentity.createdtime <= ?
|
|
AND vtiger_crmentityrel.crmid=?
|
|
AND vtiger_crmentity.setype=?
|
|
GROUP BY vtiger_crmentityrel.crmid';
|
|
$result = $adb->pquery($sql, [$dateFrom, $dateTo, $recordId, $this->getEmailsModule()]);
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
public function isVtigerEmails()
|
|
{
|
|
return self::$EMAILS_MODULE !== $this->getEmailsModule();
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function getEmailTrack()
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$sql = 'SELECT access_count,click_count FROM its4you_emails WHERE related_to = ? AND recipient_id > 0';
|
|
$result = $adb->pquery($sql, [$this->getId()]);
|
|
|
|
$access = $unique = $click = 0;
|
|
$opened = array();
|
|
$subscribers = array();
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
if ($row['access_count'] >= 1) {
|
|
$unique += 1;
|
|
array_push($opened, $row['mailid']);
|
|
}
|
|
|
|
array_push($subscribers, $row['crmid']);
|
|
$access += $row['access_count'];
|
|
$click += $row['click_count'];
|
|
}
|
|
|
|
return array(
|
|
'unique' => $unique,
|
|
'access' => $access,
|
|
'click' => $click,
|
|
'open' => $opened,
|
|
'subscribers' => $subscribers,
|
|
'notopen' => $this->getSendEmailsCount() - $unique,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getSendEmailsCount()
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery(
|
|
'SELECT count(recipient_id) AS count FROM its4you_emails WHERE related_to = ? AND recipient_id > 0',
|
|
[$this->getId()]
|
|
);
|
|
|
|
return intval($adb->query_result($result, 0, 'count'));
|
|
}
|
|
|
|
/**
|
|
* @param string $email
|
|
* @param int $recipientId
|
|
* @param array $emailInfo
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function sendEmail($email, $recipientId, $emailInfo = array())
|
|
{
|
|
$recipientModule = getSalesEntityType($recipientId);
|
|
|
|
if ($this->isPreviewEmail()) {
|
|
$assignedUserId = Users_Record_Model::getCurrentUserModel()->getId();
|
|
} else {
|
|
$assignedUserId = $this->get('assigned_user_id');
|
|
}
|
|
|
|
$assignedUserId = $this->get('assigned_user_id');
|
|
$smtp = $this->get('emailmarketingsmtp');
|
|
$moduleModel = $this->getModule();
|
|
$moduleName = $moduleModel->getName();
|
|
$replyTo = $this->get('replyto');
|
|
$fromEmail = $this->get('fromemail');
|
|
$subject = $this->get('subject');
|
|
$images = array();
|
|
$content = '';
|
|
$success = true;
|
|
$message = vtranslate('LBL_SEND_EMAIL_ERROR', $moduleName);
|
|
|
|
/** Required include before EMAILMaker on multiple simple_html_dom*/
|
|
include_once 'modules/Emails/models/Mailer.php';
|
|
|
|
$recipientRecord = $this->getRecordModel($recipientId, $recipientModule);
|
|
$contentTemplate = ITS4YouEmailMarketing_Content_Template::getInstanceFromMarketing($this);
|
|
|
|
if ($contentTemplate) {
|
|
$content = $contentTemplate->getContent($recipientRecord);
|
|
$images = $contentTemplate->getImages();
|
|
} else {
|
|
$message = vtranslate('LBL_MISSING_CONTENT', $this->getModuleName());
|
|
|
|
$this->set(self::$statusField, self::$statusError);
|
|
$this->setErrorMessage(vtranslate('LBL_MISSING_CONTENT', $this->getModuleName()));
|
|
|
|
return array(
|
|
'success' => false,
|
|
'message' => $message,
|
|
);
|
|
}
|
|
|
|
$flag = self::$UNSUBSCRIBED_EMAIL_STATUS === $emailInfo['status'] ? 'UNSUBSCRIBED' : 'SAVED';
|
|
|
|
/** @var ITS4YouEmails_Record_Model $emailRecord */
|
|
$emailRecord = ITS4YouEmails_Record_Model::getCleanInstance(self::$EMAILS_MODULE);
|
|
$emailRecord->set('assigned_user_id', $assignedUserId);
|
|
$emailRecord->set('subject', $subject);
|
|
$emailRecord->set('body', $content);
|
|
$emailRecord->set('email_flag', $flag);
|
|
$emailRecord->set('related_to', $this->getId());
|
|
$emailRecord->set('smtp', $smtp);
|
|
|
|
if (!$this->isPreviewEmail()) {
|
|
$emailRecord->set('recipient_id', $recipientId);
|
|
}
|
|
|
|
$emailRecord->set('from_email', $fromEmail);
|
|
$emailRecord->set('from_email_ids', $assignedUserId . '|' . $fromEmail . '|Users');
|
|
|
|
if (!empty($replyTo)) {
|
|
$emailRecord->set('reply_email', $replyTo);
|
|
$emailRecord->set('reply_email_ids', $assignedUserId . '|' . $replyTo . '|Users');
|
|
}
|
|
|
|
$emailRecord->set('to_email', $email);
|
|
$emailRecord->set('to_email_ids', implode('|', [$recipientId, $email, $recipientModule]));
|
|
$emailRecord->set('result', vtranslate($emailInfo['status'], $this->getModuleName()));
|
|
$emailRecord->save();
|
|
|
|
$this->setDocumentsToEmails($emailRecord);
|
|
|
|
if (self::$VALID_EMAIL_STATUS === $emailInfo['status']) {
|
|
/** @var ITS4YouEmails_Record_Model $emailRecord */
|
|
$emailRecord = ITS4YouEmails_Record_Model::getInstanceById($emailRecord->getId(), self::$EMAILS_MODULE);
|
|
$emailRecord->set('images', $images);
|
|
$emailRecord->set('from_name', $this->getFromName());
|
|
$emailRecord->set('reply_name', $this->getFromName());
|
|
$emailRecord->set('skip_save_email_to_sent_folder', true);
|
|
|
|
$this->setUnsubscribeToEmails($emailRecord);
|
|
|
|
$emailRecord->send();
|
|
}
|
|
|
|
if ($this->isPreviewEmail()) {
|
|
$this->deleteRelation($emailRecord);
|
|
} else {
|
|
$this->addRelation($emailRecord);
|
|
}
|
|
|
|
$success = 'SENT' === (string)$emailRecord->get('email_flag');
|
|
$message = $emailRecord->get('result');
|
|
|
|
if (!$success) {
|
|
$this->setErrorMessage($message);
|
|
}
|
|
|
|
return array(
|
|
'success' => $success,
|
|
'message' => $message,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param ITS4YouEmails_Record_Model $emailRecord
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
public function setUnsubscribeToEmails($emailRecord)
|
|
{
|
|
if ($emailRecord->isEmpty('recipient_id')) {
|
|
return;
|
|
}
|
|
|
|
$emailRecord->getMailer()->addCustomHeader(
|
|
'List-Unsubscribe',
|
|
'<' . (new ITS4YouEmailMarketing_Module_Model())->getUnsubscribeLink($emailRecord->get('recipient_id')) . '>,<mailto:' . $this->get('from_email') . '?subject=Unsubscribe>'
|
|
);
|
|
$emailRecord->getMailer()->addCustomHeader(
|
|
'List-Unsubscribe-Post',
|
|
'List-Unsubscribe=One-Click'
|
|
);
|
|
}
|
|
|
|
public function isPreviewEmail()
|
|
{
|
|
return $this->previewEmail;
|
|
}
|
|
|
|
public function setPreviewEmail()
|
|
{
|
|
$this->previewEmail = true;
|
|
}
|
|
|
|
/**
|
|
* @return object|ITS4YouEmailMarketing_Content_Template
|
|
*/
|
|
public function getContent()
|
|
{
|
|
if (empty($this->content)) {
|
|
$this->retrieveContent();
|
|
}
|
|
|
|
return $this->content;
|
|
}
|
|
|
|
/**
|
|
* @param object|ITS4YouEmailMarketing_Content_Template $value
|
|
*/
|
|
public function setContent($value)
|
|
{
|
|
$this->content = $value;
|
|
}
|
|
|
|
public function retrieveContent()
|
|
{
|
|
$this->setContent(ITS4YouEmailMarketing_Content_Template::getInstanceFromMarketing($this));
|
|
}
|
|
|
|
public function setErrorMessage($message)
|
|
{
|
|
$oldMessage = !$this->isEmpty('errormessage') ? "\n" . $this->get('errormessage') : '';
|
|
|
|
$this->set('id', $this->getId());
|
|
$this->set('mode', 'edit');
|
|
$this->set('errormessage', print_r($message, true) . $oldMessage);
|
|
$this->save();
|
|
}
|
|
|
|
public function save()
|
|
{
|
|
$send = $this->get('emailmarketingsend');
|
|
$status = $this->get('emailmarketingstatus');
|
|
|
|
if ('Scheduled' === $send && 'Created' === $status) {
|
|
$this->set('emailmarketingstatus', 'Ready');
|
|
}
|
|
|
|
$this->getModule()->saveRecord($this);
|
|
}
|
|
|
|
/**
|
|
* @param ITS4YouEmails_Record_Model $emailRecord
|
|
* @return void
|
|
*/
|
|
public function setDocumentsToEmails($emailRecord)
|
|
{
|
|
foreach ($this->getDocumentIds() as $documentId) {
|
|
$emailRecord->saveDocumentRelation($documentId);
|
|
}
|
|
}
|
|
|
|
public function getDocumentIds()
|
|
{
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery(
|
|
'SELECT vtiger_crmentity.crmid AS document_id FROM vtiger_senotesrel
|
|
INNER JOIN vtiger_crmentity ON vtiger_senotesrel.notesid = vtiger_crmentity.crmid AND vtiger_senotesrel.crmid = ?
|
|
INNER JOIN vtiger_notes ON vtiger_notes.notesid = vtiger_senotesrel.notesid
|
|
INNER JOIN vtiger_seattachmentsrel ON vtiger_seattachmentsrel.crmid = vtiger_notes.notesid
|
|
INNER JOIN vtiger_attachments ON vtiger_attachments.attachmentsid = vtiger_seattachmentsrel.attachmentsid
|
|
WHERE vtiger_crmentity.deleted = 0',
|
|
array($this->getId())
|
|
);
|
|
$documentIds = [];
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
$documentIds[] = $row['document_id'];
|
|
}
|
|
|
|
return $documentIds;
|
|
}
|
|
|
|
public function getFromName()
|
|
{
|
|
return decode_html($this->get('fromname'));
|
|
}
|
|
|
|
/**
|
|
* @param Vtiger_Record_Model $recordModel
|
|
* @return void
|
|
*/
|
|
public function deleteRelation($recordModel)
|
|
{
|
|
$moduleModel = $this->getModule();
|
|
/** @var Vtiger_Relation_Model $relationModel */
|
|
$relationModel = Vtiger_Relation_Model::getInstance($moduleModel, $recordModel->getModule());
|
|
|
|
if ($relationModel) {
|
|
$relationModel->deleteRelation($this->getId(), $recordModel->getId());
|
|
}
|
|
}
|
|
|
|
public function retrieveSourceTemplateDocuments()
|
|
{
|
|
$contentTemplate = ITS4YouEmailMarketing_Content_Template::getInstanceFromMarketing($this);
|
|
|
|
if ($contentTemplate) {
|
|
$documentsIds = $contentTemplate->getDocumentsIds();
|
|
|
|
foreach ($documentsIds as $documentId) {
|
|
$documentRecord = Vtiger_Record_Model::getInstanceById($documentId);
|
|
|
|
if ($documentRecord) {
|
|
$this->addRelation($documentRecord);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function deleteRelationByModule()
|
|
{
|
|
$relatedModules = array_diff($this->getEmailMarketingModules(), [$this->get('emailmarketingmodule')]);
|
|
|
|
$this->deleteRelationsForModules($relatedModules);
|
|
}
|
|
|
|
public function updateEmailFlag($emailRecordId, $flag = 'Error')
|
|
{
|
|
$db = PearDatabase::getInstance();
|
|
$query = 'UPDATE vtiger_emaildetails SET email_flag=? WHERE emailid=?';
|
|
$db->pquery($query, array($flag, $emailRecordId));
|
|
}
|
|
|
|
/**
|
|
* @param string $value
|
|
* @return bool
|
|
*/
|
|
public function isStatus($value)
|
|
{
|
|
return $value === $this->get('emailmarketingstatus');
|
|
}
|
|
|
|
public function updateStatus($status = false)
|
|
{
|
|
$this->set('id', $this->getId());
|
|
$this->set('mode', 'edit');
|
|
|
|
if ($status !== false) {
|
|
$newStatus = $status;
|
|
} elseif ($this->isReadyToSendEmail()) {
|
|
$newStatus = 'Stop';
|
|
} else {
|
|
$newStatus = 'Ready';
|
|
}
|
|
|
|
$deliveryDate = $this->get('deliverydate');
|
|
$deliveryTime = $this->get('deliverytime');
|
|
|
|
if (!$deliveryDate || !$deliveryTime) {
|
|
$dateNow = $this->getDateNow();
|
|
$date = date('Y-m-d', $dateNow);
|
|
$time = date('H:i:s', $dateNow);
|
|
|
|
$this->set('deliverydate', $date);
|
|
$this->set('deliverytime', $time);
|
|
}
|
|
|
|
$this->set('emailmarketingstatus', $newStatus);
|
|
$this->save();
|
|
}
|
|
|
|
public function isReadyToSendEmail()
|
|
{
|
|
$ready = false;
|
|
$time = $this->get('deliverytime');
|
|
$date = $this->get('deliverydate');
|
|
|
|
if (!empty($time) && !empty($date)) {
|
|
$status = $this->get('emailmarketingstatus');
|
|
$dateNow = $this->getDateNow();
|
|
$start = $date . ' ' . $time;
|
|
$dateStart = strtotime($start);
|
|
|
|
if (in_array($status, ['Sending', 'Ready'])) {
|
|
if ($dateNow >= $dateStart) {
|
|
$ready = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $ready;
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
*/
|
|
public function getDateNow()
|
|
{
|
|
$dateNow = date('Y-m-d H:i:s');
|
|
$DateTimeField = new DateTimeField($dateNow);
|
|
$dateNow = $DateTimeField->getDisplayDateTimeValue();
|
|
|
|
return strtotime($dateNow);
|
|
}
|
|
|
|
public function getErrorMessage()
|
|
{
|
|
return $this->get('errormessage');
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function getKeyMetrics()
|
|
{
|
|
$track = $this->getEmailTrack();
|
|
$emailsCount = $this->getSendEmailsCount();
|
|
$progressOpen = $emailsCount > 0 ? round($track['unique'] / $emailsCount * 100) : 0;
|
|
$keyMetric = array(
|
|
'subscribers' => array(
|
|
'LBL_STATUS' => vtranslate($this->get('emailmarketingstatus'), $this->getModuleName()),
|
|
'LBL_SELECT_SUBSCRIBERS' => $this->getSubscribersCount(),
|
|
'LBL_SENT_EMAILS' => $emailsCount,
|
|
'LBL_UNSUBSCRIBED' => $this->getUnsubscribed(),
|
|
),
|
|
'emailsinfo' => array(
|
|
'LBL_UNIQUE_OPEN' => $track['unique'],
|
|
'LBL_CLICK_COUNT' => $track['click'],
|
|
'LBL_ACCESS_COUNT' => $track['access'],
|
|
'LBL_NOT_OPEN' => $track['notopen'],
|
|
),
|
|
);
|
|
|
|
if (6 === intval(Vtiger_Version::current())) {
|
|
$keyMetric['emailsinfo']['LBL_EMAIL_PER_OPEN'] = $progressOpen . ' %';
|
|
unset($keyMetric['emailsinfo']['LBL_CLICK_COUNT']);
|
|
}
|
|
|
|
return $keyMetric;
|
|
}
|
|
|
|
/**
|
|
* @param bool $module
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getUnsubscribed($module = false)
|
|
{
|
|
$unsubscribed = 0;
|
|
|
|
if ($module) {
|
|
$moduleModel = Vtiger_Module_Model::getInstance($module);
|
|
$field = Vtiger_Field_Model::getInstance('emailoptout', $moduleModel);
|
|
|
|
if ($field) {
|
|
$adb = PearDatabase::getInstance();
|
|
$query = 'SELECT count(recipient_id) as count FROM its4you_emails WHERE email_flag = ? AND related_to = ? AND recipient_id > 0';
|
|
$result = $adb->pquery($query, ['UNSUBSCRIBED', $this->getId()]);
|
|
$unsubscribed = $adb->query_result($result, 0, 'count');
|
|
}
|
|
} else {
|
|
$modules = $this->getRelatedRecordsModules();
|
|
|
|
foreach ($modules as $module) {
|
|
$unsubscribed += $this->getUnsubscribed($module);
|
|
}
|
|
}
|
|
|
|
return intval($unsubscribed);
|
|
}
|
|
|
|
public function getRelatedRecordsModules()
|
|
{
|
|
$related = array();
|
|
$adb = PearDatabase::getInstance();
|
|
$record = $this->getId();
|
|
$query = 'SELECT DISTINCT relmodule FROM vtiger_crmentityrel WHERE crmid=? AND relmodule NOT IN (?,?)';
|
|
$result = $adb->pquery($query, array($record, 'Emails', 'ITS4YouEmails'));
|
|
|
|
while ($row = $adb->fetchByAssoc($result)) {
|
|
array_push($related, $row['relmodule']);
|
|
}
|
|
|
|
return $related;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function getProgress()
|
|
{
|
|
$progress = $openEmails = false;
|
|
$emails = $this->getSendEmailsCount();
|
|
$status = [1 => 'Ready', 2 => 'Sending', 3 => 'Finish'];
|
|
$status_num = 1;
|
|
|
|
if ($emails) {
|
|
$subscribers = $this->getSubscribersCount();
|
|
$emailTrack = $this->getEmailTrack();
|
|
|
|
if ($subscribers) {
|
|
$emStatus = $this->get('emailmarketingstatus');
|
|
$status_num = array_search($emStatus, $status) ?: 1;
|
|
$progress = 'Finish' === $emStatus ? 100 : ceil($emails / $subscribers * 100);
|
|
}
|
|
|
|
if ($emailTrack['unique']) {
|
|
$openEmails = 100 / $emails * intval($emailTrack['unique']);
|
|
}
|
|
}
|
|
|
|
return [
|
|
'already_sent' => $progress,
|
|
'open_emails' => ceil($openEmails),
|
|
'status' => $status,
|
|
'status_num' => $status_num,
|
|
];
|
|
}
|
|
|
|
public function isFinished()
|
|
{
|
|
return 'Finish' === $this->get('emailmarketingstatus');
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getBreadCrumbLabels()
|
|
{
|
|
$breadCrumbLabels = [
|
|
'CampaignDetails' => 'LBL_CAMPAIGN_DETAILS',
|
|
'SelectSubscribers' => 'LBL_SELECT_SUBSCRIBERS',
|
|
'SelectTemplate' => 'LBL_SELECT_TEMPLATE',
|
|
'TemplateRecords' => 'LBL_TEMPLATE_RECORDS',
|
|
'Schedule' => 'LBL_SEND_CAMPAIGN',
|
|
];
|
|
|
|
if (!$this->isRecordBlockTemplate()) {
|
|
unset($breadCrumbLabels['TemplateRecords']);
|
|
}
|
|
|
|
return $breadCrumbLabels;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function isRecordBlockTemplate()
|
|
{
|
|
return $this->getContent() ? $this->getContent()->isAllowedRecordsBlock() : false;
|
|
}
|
|
|
|
/**
|
|
* @return array|false
|
|
*/
|
|
public function getRecordsBlockModules()
|
|
{
|
|
if ($this->getContent()) {
|
|
$blocks = $this->getContent()->getBlockData('recordsblock');
|
|
$modules = array();
|
|
|
|
foreach ($blocks as $block) {
|
|
if (vtlib_isModuleActive($block['data-module'])) {
|
|
array_push($modules, $block['data-module']);
|
|
}
|
|
}
|
|
|
|
return array_unique($modules);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function retrieveTemplateSource()
|
|
{
|
|
if (!$this->isEmpty('templatesource')) {
|
|
return;
|
|
}
|
|
|
|
foreach ($this->templateSourceModules as $source => $module) {
|
|
if (vtlib_isModuleActive($module)) {
|
|
$this->set('templatesource', $source);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function retrieveTemplateRelation()
|
|
{
|
|
if (!$this->isEmpty('templatesource') && !$this->isEmpty('template')) {
|
|
$this->set('templaterelation', $this->get('templatesource') . ':' . $this->get('template'));
|
|
}
|
|
}
|
|
} |