%PDF- %PDF-
| Direktori : /home/bitrix/www/bitrix/modules/sender/lib/integration/crm/connectors/ |
| Current File : //home/bitrix/www/bitrix/modules/sender/lib/integration/crm/connectors/helper.php |
<?php
/**
* Bitrix Framework
* @package bitrix
* @subpackage sender
* @copyright 2001-2012 Bitrix
*/
namespace Bitrix\Sender\Integration\Crm\Connectors;
use Bitrix\Main\Config\Option;
use Bitrix\Main\DB\SqlExpression;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Entity;
use Bitrix\Main\Page\Asset;
use Bitrix\Main\UI\Filter\Type as UiFilterType;
use Bitrix\Main\UI\Filter\AdditionalDateType;
use Bitrix\Crm\CompanyTable;
use Bitrix\Crm\LeadTable;
use Bitrix\Crm\ContactTable;
use Bitrix\Sender\Recipient;
use Bitrix\Sender\Connector;
use Bitrix\Sender\Integration;
Loc::loadMessages(__FILE__);
/**
* Class Helper
* @package Bitrix\Sender\Integration\Crm\Connectors
*/
class Helper
{
public static $runtimeByEntity = [];
/**
* Get personalize field list.
*
* @return array
*/
public static function getPersonalizeList()
{
return array(
array('CODE' => 'CRM_ENTITY_TYPE_ID'),
array('CODE' => 'CRM_ENTITY_ID'),
);
}
/**
* Get filter user fields.
*
* @param integer $entityTypeId Entity type ID.
* @return array
*/
public static function getFilterUserFields($entityTypeId)
{
$list = array();
$ufManager = is_object($GLOBALS['USER_FIELD_MANAGER']) ? $GLOBALS['USER_FIELD_MANAGER'] : null;
if (!$ufManager)
{
return $list;
}
$ufEntityId = \CCrmOwnerType::resolveUserFieldEntityID($entityTypeId);
$crmUserType = new \CCrmUserType($ufManager, $ufEntityId);
$logicFilter = array();
$crmUserType->prepareListFilterFields($list, $logicFilter);
$originalList = $crmUserType->getFields();
$restrictedTypes = ['address', 'file', 'crm'];
$list = array_filter(
$list,
function ($field) use ($originalList, $restrictedTypes)
{
if (empty($originalList[$field['id']]))
{
return false;
}
$type = $originalList[$field['id']]['USER_TYPE']['USER_TYPE_ID'];
return !in_array($type, $restrictedTypes);
}
);
foreach ($list as $index => $field)
{
if ($field['type'] === 'date')
{
$list[$index]['include'] = [
AdditionalDateType::CUSTOM_DATE,
AdditionalDateType::PREV_DAY,
AdditionalDateType::NEXT_DAY,
AdditionalDateType::MORE_THAN_DAYS_AGO,
AdditionalDateType::AFTER_DAYS,
];
if (!isset($list[$index]['allow_years_switcher']))
{
$list[$index]['allow_years_switcher'] = true;
}
}
if ($field['type'] === 'custom_entity' && !empty($field['selector']) && $field['selector']['TYPE'] == 'user')
{
$list[$index]['sender_segment_callback'] = function ($field) use ($entityTypeId)
{
return Helper::getFilterFieldUserSelector(
$field['selector']['DATA'],
'crm_segment_' . ($entityTypeId === \CCrmOwnerType::Lead ? 'lead' : 'client')
);
};
$list[$index]['params'] = ['multiple' => 'Y'];
}
}
return $list;
}
/**
* Prepare query select.
*
* @param Entity\Query $query Query.
* @param integer $dataTypeId Data type ID.
* @return Entity\Query
*/
public static function prepareQuery(Entity\Query $query, $dataTypeId = null)
{
$map = array(
Recipient\Type::EMAIL => [
'name' => 'HAS_EMAIL',
'operator' => '=',
'value' => 'Y'
],
Recipient\Type::PHONE => [
'name' => 'HAS_PHONE',
'operator' => '=',
'value' => 'Y'
],
Recipient\Type::IM => [
'name' => 'HAS_IMOL',
'operator' => '=',
'value' => 'Y'
],
Recipient\Type::CRM_CONTACT_ID => [
'name' => 'CONTACT_ID',
'operator' => '>',
'value' => 0
],
Recipient\Type::CRM_COMPANY_ID => [
'name' => 'COMPANY_ID',
'operator' => '>',
'value' => 0
],
);
$entityName = strtoupper($query->getEntity()->getName());
if ($dataTypeId)
{
if (!isset($map[$dataTypeId]))
{
return $query;
}
$field = $map[$dataTypeId];
if ($dataTypeId == Recipient\Type::CRM_COMPANY_ID && in_array($entityName, ['CONTACT']))
{
$field['name'] = 'CRM_COMPANY_ID';
}
$query->where($field['name'], $field['operator'], $field['value']);
if ($dataTypeId === Recipient\Type::IM)
{
$query->whereExists(self::getImSqlExpression($query));
}
}
else if (!in_array($entityName, ['CONTACT', 'COMPANY']))
{
$filter = Entity\Query::filter();
foreach ($map as $dataTypeId => $field)
{
if ($dataTypeId === Recipient\Type::IM)
{
$filter->where(
Entity\Query::filter()
->where($field['name'], $field['operator'], $field['value'])
->whereExists(self::getImSqlExpression($query))
);
}
else
{
$filter->where($field['name'], $field['operator'], $field['value']);
}
}
if (count($filter->getConditions()) > 0)
{
$filter->logic('or');
$query->where($filter);
}
}
return $query;
}
protected static function getImSqlExpression(Entity\Query $query)
{
$codes = Integration\Im\Service::getExcludedChannelCodes();
if (empty($codes))
{
$codes = array('livechat', 'network');
}
$entityTypeName = strtoupper($query->getEntity()->getName());
$filterImolSql = "SELECT FM.VALUE " .
"FROM b_crm_field_multi FM " .
"WHERE FM.ENTITY_ID = '$entityTypeName' AND FM.ELEMENT_ID = ?#.ID " .
"AND FM.TYPE_ID = 'IM' " .
"AND FM.VALUE NOT REGEXP '^imol\\\\|(" . implode('|', $codes) . ")' " .
"ORDER BY FM.ID LIMIT 1";
return new SqlExpression($filterImolSql, $query->getInitAlias());
}
/**
* Get runtime by entity.
*
* @param string $entityTypeName Entity type name.
* @return Entity\ExpressionField[]
*/
public static function getRuntimeByEntity($entityTypeName = '')
{
if (isset(self::$runtimeByEntity[$entityTypeName]))
{
return self::$runtimeByEntity[$entityTypeName];
}
return [];
}
protected static function processRuntimeFilter(array &$filter, $entityTypeName = '')
{
foreach ($filter as $key => $item)
{
if (!($item instanceof Connector\Filter\RuntimeFilter))
{
continue;
}
unset($filter[$key]);
$filter[$item->getKey()] = $item->getValue();
if (empty(self::$runtimeByEntity[$entityTypeName]))
{
self::$runtimeByEntity[$entityTypeName] = [];
}
self::$runtimeByEntity[$entityTypeName] = array_merge(
self::$runtimeByEntity[$entityTypeName],
array_map(
function ($item) use ($entityTypeName)
{
$search = $entityTypeName ? $entityTypeName . '_' : '';
$runtimeName = $entityTypeName ? $entityTypeName . '.' : '';
$item['expression'] = str_replace(
$search,
$runtimeName,
$item['expression']
);
$item['buildFrom'] = array_map(
function ($from) use ($search, $runtimeName)
{
return str_replace($search, $runtimeName, $from);
},
$item['buildFrom']
);
return $item;
},
$item->getRuntime()
)
);
}
}
/**
* Get filter by entity.
*
* @param array $fields Fields.
* @param array $values Values.
* @param array $entityTypeNames Entity type names.
* @return array
*/
public static function getFilterByEntity(array $fields = array(), array $values = array(), array $entityTypeNames = array())
{
$map = array();
foreach ($entityTypeNames as $entityTypeName)
{
$map[$entityTypeName] = array($entityTypeName);
}
$map['CLIENT'] = array(\CCrmOwnerType::CompanyName, \CCrmOwnerType::ContactName);
$map[\CCrmOwnerType::CompanyName] = array(\CCrmOwnerType::CompanyName);
$map[\CCrmOwnerType::ContactName] = array(\CCrmOwnerType::ContactName);
$result = array();
foreach ($fields as $field)
{
if (!self::isFieldFilterable($field, $values))
{
continue;
}
$id = $field['id'];
foreach ($map as $prefix => $entityTypes)
{
$search = $prefix . '_';
if (strpos($id, $search) !== 0)
{
continue;
}
foreach ($entityTypes as $entityTypeName)
{
$filterKey = "$entityTypeName." . substr($id, strlen($search));
if (!self::isFieldTypeFilter($field['type']))
{
$filterKey = "=$filterKey";
}
$field['sender_segment_filter'] = $filterKey;
if (!isset($result[$entityTypeName]))
{
$result[$entityTypeName] = array();
}
$result[$entityTypeName][] = $field;
}
break;
}
}
self::$runtimeByEntity = [];
foreach ($result as $entityTypeName => $fields)
{
$items = self::getFilterByFields($fields, $values, $entityTypeName);
$result[$entityTypeName] = $items;
}
return $result;
}
private static function isFieldFilterable(array $field = array(), array $values = array())
{
$id = $field['id'];
$codeKey = 'sender_segment_filter';
if (isset($field[$codeKey]) && $field[$codeKey] === false)
{
return false;
}
if (!isset($values[$id]) || (!$values[$id] && !is_numeric($values[$id])))
{
return false;
}
return true;
}
/**
* Get filter by fields.
*
* @param array $fields Fields.
* @param array $values Values.
* @param string $entityTypeName Entity type name.
* @return array
*/
public static function getFilterByFields(array $fields = array(), array $values = array(), $entityTypeName = '')
{
if ($entityTypeName)
{
if (!empty(self::$runtimeByEntity[$entityTypeName]))
{
self::$runtimeByEntity[$entityTypeName] = [];
}
}
else
{
self::$runtimeByEntity = [];
}
$filter = array();
foreach ($fields as $field)
{
if (!self::isFieldFilterable($field, $values))
{
continue;
}
$isMultiple = false;
if (isset($field['params']) && is_array($field['params']))
{
if (isset($field['params']['multiple']) && $field['params']['multiple'])
{
$isMultiple = true;
}
}
$id = $field['id'];
$value = $values[$id];
$value = $isMultiple && !is_array($value) ? array($value) : $value;
$field['value'] = $value;
if (strpos($field['id'], 'COMMUNICATION_TYPE') !== false)
{
self::getCommunicationTypeFilter($value, $filter);
continue;
}
$filterKey = self::getFilterFieldKey($field);
if (is_array($filterKey))
{
foreach ($filterKey as $fieldValue => $fieldFilter)
{
if ($value !== $fieldValue)
{
continue;
}
$filter[$fieldFilter[0]] = $fieldFilter[1];
}
}
elseif (self::isFieldTypeFilter($field['type']))
{
self::setFieldTypeFilter($filterKey, $field, $filter);
self::processRuntimeFilter($filter, $entityTypeName);
}
else
{
$filter[$filterKey] = $value;
}
}
return $filter;
}
protected static function getFilterFieldKey(array $field)
{
$codeKey = 'sender_segment_filter';
$id = $field['id'];
if (isset($field[$codeKey]) && $field[$codeKey])
{
return $field[$codeKey];
}
if (self::isFieldTypeFilter($field['type']))
{
return "$id";
}
return "=$id";
}
protected static function isFieldTypeFilter($type)
{
$types = array(
UiFilterType::DATE,
UiFilterType::NUMBER
);
return in_array(strtoupper($type), $types);
}
protected static function setFieldTypeFilter($filterKey, array $fieldData, &$filter)
{
$fieldData['filter-key'] = $filterKey;
switch (strtoupper($fieldData['type']))
{
case UiFilterType::DATE:
Connector\Filter\DateField::create($fieldData)->applyFilter($filter);
break;
case UiFilterType::NUMBER:
Connector\Filter\NumberField::create($fieldData)->applyFilter($filter);
break;
}
}
protected static function getCommunicationTypeFilter(array $commTypes, &$filter)
{
if (in_array(\CCrmFieldMulti::PHONE, $commTypes))
{
$filter['=HAS_PHONE'] = 'Y';
}
if (in_array(\CCrmFieldMulti::EMAIL, $commTypes))
{
$filter['=HAS_EMAIL'] = 'Y';
}
if (in_array(\CCrmFieldMulti::IM, $commTypes))
{
$filter['=HAS_IMOL'] = 'Y';
}
}
/**
* Get "user selector" filter field
*
* @param array $userSelector User-selector.
* @param string $filterID ID of filter.
* @return string
*/
public static function getFilterFieldUserSelector(array $userSelector, $filterID)
{
if(empty($userSelector))
{
return '';
}
$userSelectors = array($userSelector);
Asset::getInstance()->addJs('/bitrix/js/crm/common.js');
ob_start();
$componentName = "{$filterID}_FILTER_USER";
/** @var \CAllMain $GLOBALS['APPLICATION'] */
if (true)
{
foreach($userSelectors as $userSelector)
{
$selectorID = $userSelector['ID'];
$fieldID = $userSelector['FIELD_ID'];
Loader::includeModule('socialnetwork');
$GLOBALS['APPLICATION']->includeComponent(
"bitrix:main.ui.selector",
".default",
array(
'ID' => $selectorID,
'ITEMS_SELECTED' => array(),
'CALLBACK' => array(
'select' => 'BX.CrmUIFilterUserSelector.processSelection',
'unSelect' => '',
'openDialog' => 'BX.CrmUIFilterUserSelector.processDialogOpen',
'closeDialog' => 'BX.CrmUIFilterUserSelector.processDialogClose',
'openSearch' => ''
),
'OPTIONS' => array(
'eventInit' => 'BX.Crm.FilterUserSelector:openInit',
'eventOpen' => 'BX.Crm.FilterUserSelector:open',
'context' => 'FEED_FILTER_CREATED_BY',
'contextCode' => 'U',
'useSearch' => 'N',
'useClientDatabase' => 'Y',
'allowEmailInvitation' => 'N',
'enableDepartments' => 'Y',
'enableSonetgroups' => 'N',
'departmentSelectDisable' => 'Y',
'allowAddUser' => 'N',
'allowAddCrmContact' => 'N',
'allowAddSocNetGroup' => 'N',
'allowSearchEmailUsers' => 'N',
'allowSearchCrmEmailUsers' => 'N',
'allowSearchNetworkUsers' => 'N',
'allowSonetGroupsAjaxSearchFeatures' => 'N'
)
),
false,
array("HIDE_ICONS" => "Y")
);
?><script type="text/javascript"><?
?>BX.ready(
function()
{
BX.CrmUIFilterUserSelector.create(
"<?=\CUtil::jsEscape($selectorID)?>",
{
filterId: "<?=\CUtil::jsEscape($filterID)?>",
fieldId: "<?=\CUtil::jsEscape($fieldID)?>"
}
);
}
);<?
?></script><?
}
}
else
{
$GLOBALS['APPLICATION']->includeComponent(
'bitrix:intranet.user.selector.new',
'',
array(
'MULTIPLE' => 'N',
'NAME' => $componentName,
'INPUT_NAME' => strtolower($componentName),
'SHOW_EXTRANET_USERS' => 'NONE',
'POPUP' => 'Y',
'SITE_ID' => SITE_DIR,
//'NAME_TEMPLATE' => $nameTemplate
),
null,
array('HIDE_ICONS' => 'Y')
);
?><script type="text/javascript"><?
foreach($userSelectors as $userSelector)
{
$selectorID = $userSelector['ID'];
$fieldID = $userSelector['FIELD_ID'];
?>
BX.ready(
function()
{
BX.FilterUserSelector.create(
"<?=\CUtil::JSEscape($selectorID)?>",
{
fieldId: "<?=\CUtil::JSEscape($fieldID)?>",
componentName: "<?=\CUtil::JSEscape($componentName)?>"
}
);
}
);
<?
}
?></script><?
}
return ob_get_clean();
}
/**
* Callback on draw of result view.
*
* @param array &$row Row.
* @return void
*/
public function onResultViewDraw(array &$row)
{
switch ($row['CRM_ENTITY_TYPE_ID'])
{
case \CCrmOwnerType::Company:
$crmRow = CompanyTable::getRowById($row['CRM_ENTITY_ID']);
$row['~NAME'] = self::getResultViewTitle(
$row['CRM_ENTITY_TYPE_ID'],
$row['CRM_ENTITY_ID'],
$row['NAME'],
\CCrmOwnerType::GetDescription($row['CRM_ENTITY_TYPE_ID']),
self::getCrmStatusName('COMPANY_TYPE', $crmRow['COMPANY_TYPE'])
);
break;
case \CCrmOwnerType::Contact:
$crmRow = ContactTable::getRowById($row['CRM_ENTITY_ID']);
$row['~NAME'] = self::getResultViewTitle(
$row['CRM_ENTITY_TYPE_ID'],
$row['CRM_ENTITY_ID'],
$row['NAME'],
\CCrmOwnerType::GetDescription($row['CRM_ENTITY_TYPE_ID']),
self::getCrmStatusName('SOURCE', $crmRow['SOURCE_ID'])
);
break;
case \CCrmOwnerType::Lead:
$crmRow = LeadTable::getRowById($row['CRM_ENTITY_ID']);
$row['CRM_LEAD'] = $row['~CRM_LEAD'] = self::getResultViewTitle(
$row['CRM_ENTITY_TYPE_ID'],
$row['CRM_ENTITY_ID'],
$crmRow['TITLE'],
self::getCrmStatusName('SOURCE', $crmRow['SOURCE_ID']),
$crmRow['IS_RETURN_CUSTOMER'] === 'Y' ? Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_LEAD_FIELD_RC_LEAD') : null
);
break;
}
}
protected function getCrmStatusName($statusType, $statusId)
{
if (!$statusId)
{
return null;
}
$sources = \CCrmStatus::GetStatus($statusType);
if (empty($sources[$statusId]))
{
return $statusId;
}
return $sources[$statusId]['NAME'];
}
protected function getResultViewTitle($entityTypeId, $entityId, $title, $secondTitle = null, $thirdTitle = null)
{
$url = self::getPathToDetail($entityTypeId, $entityId);
$title = htmlspecialcharsbx($title);
if ($url && \CCrmAuthorizationHelper::checkReadPermission($entityTypeId, $entityId))
{
$title = '<a href="' . $url . '">' . $title . '</a>';
}
if ($secondTitle)
{
$title .= "<br><span style=\"color:grey; font-size: 12px;\">";
$title .= htmlspecialcharsbx($secondTitle);
$title .= "</span>";
}
if ($thirdTitle)
{
$title .= "<br><span style=\"color:grey; font-size: 12px;\">";
$title .= htmlspecialcharsbx($thirdTitle);
$title .= "</span>";
}
return $title;
}
protected function getPathToDetail($entityTypeId, $entityId)
{
switch ($entityTypeId)
{
case \CCrmOwnerType::Company:
$optionName = 'path_to_company_details';
break;
case \CCrmOwnerType::Contact:
$optionName = 'path_to_contact_details';
break;
case \CCrmOwnerType::Lead:
$optionName = 'path_to_lead_details';
break;
default:
$optionName = null;
}
$url = $optionName ? Option::get('crm', $optionName) : null;
if ($url)
{
$url = str_replace(
['#company_id#', '#contact_id#', '#lead_id#'],
$entityId,
$url
);
}
return $url;
}
}