1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
contact.php
См. документацию.
1<?php
8namespace Bitrix\Sender;
9
10use Bitrix\Main\Entity;
11use Bitrix\Main\Application;
12use Bitrix\Main\Localization\Loc;
13use Bitrix\Main\ORM\Query\Query;
14use Bitrix\Main\Type as MainType;
15use Bitrix\Main\DB\SqlExpression;
16use Bitrix\Sender\Internals\Dto\UpdateContactDtoCollection;
17use Bitrix\Sender\Internals\Factory\UpdateContactDtoFactory;
18use Bitrix\Sender\Recipient;
19use Bitrix\Sender\Service\ContactListUpdateService;
20use Bitrix\Sender\Service\ContactUpdateService;
21
22Loc::loadMessages(__FILE__);
23
43{
45 const CONSENT_STATUS_NEW = 'N';
53 public static function getTableName()
54 {
55 return 'b_sender_contact';
56 }
57
63 public static function getMap()
64 {
65 return array(
66 'ID' => array(
67 'data_type' => 'integer',
68 'primary' => true,
69 'autocomplete' => true,
70 ),
71 'DATE_INSERT' => array(
72 'data_type' => 'datetime',
73 'default_value' => new MainType\DateTime(),
74 'required' => true,
75 ),
76 'DATE_UPDATE' => array(
77 'data_type' => 'datetime',
78 'default_value' => new MainType\DateTime(),
79 ),
80 'TYPE_ID' => array(
81 'data_type' => 'integer',
82 'default_value' => Recipient\Type::EMAIL,
83 'required' => true,
84 ),
85 'CODE' => array(
86 'data_type' => 'string',
87 'required' => true,
88 ),
89 'NAME' => array(
90 'data_type' => 'string',
91 'save_data_modification' => array('\Bitrix\Main\Text\Emoji', 'getSaveModificator'),
92 'fetch_data_modification' => array('\Bitrix\Main\Text\Emoji', 'getFetchModificator'),
93 ),
94 'USER_ID' => array(
95 'data_type' => 'integer',
96 ),
97 'BLACKLISTED' => array(
98 'data_type' => 'boolean',
99 'values' => array('N', 'Y'),
100 'default_value' => 'N',
101 'required' => true,
102 ),
103 'IS_READ' => array(
104 'data_type' => 'boolean',
105 'values' => array('N', 'Y'),
106 'default_value' => 'N',
107 'required' => true,
108 ),
109 'IS_CLICK' => array(
110 'data_type' => 'boolean',
111 'values' => array('N', 'Y'),
112 'default_value' => 'N',
113 'required' => true,
114 ),
115 'IS_UNSUB' => array(
116 'data_type' => 'boolean',
117 'values' => array('N', 'Y'),
118 'default_value' => 'N',
119 'required' => true,
120 ),
121 'IS_SEND_SUCCESS' => array(
122 'data_type' => 'boolean',
123 'values' => array('N', 'Y'),
124 'default_value' => 'N',
125 'required' => true,
126 ),
127 'CONSENT_STATUS' => array(
128 'data_type' => 'string',
129 'default_value' => static::CONSENT_STATUS_NEW,
130 'required' => true,
131 ),
132 'CONSENT_REQUEST' => array(
133 'data_type' => 'integer',
134 'required' => true,
135 'default_value' => 0
136 ),
137 'IP' => array(
138 'data_type' => 'string',
139 ),
140 'AGENT' => array(
141 'data_type' => 'integer',
142 ),
143 'CONTACT_LIST' => array(
144 'data_type' => 'Bitrix\Sender\ContactListTable',
145 'reference' => array('=this.ID' => 'ref.CONTACT_ID'),
146 ),
147 'MAILING_SUBSCRIPTION' => array(
148 'data_type' => 'Bitrix\Sender\MailingSubscriptionTable',
149 'reference' => array('=this.ID' => 'ref.CONTACT_ID', 'ref.IS_UNSUB' => new SqlExpression('?', 'N')),
150 ),
151 'MAILING_UNSUBSCRIPTION' => array(
152 'data_type' => 'Bitrix\Sender\MailingSubscriptionTable',
153 'reference' => array('=this.ID' => 'ref.CONTACT_ID', 'ref.IS_UNSUB' => new SqlExpression('?', 'Y')),
154 ),
155 );
156 }
157
158
164 public static function validateEmail(): array
165 {
166 return array(
167 new Entity\Validator\Length(1, 255),
168 array(__CLASS__, 'checkEmail'),
169 new Entity\Validator\Unique
170 );
171 }
172
179 public static function checkEmail(?string $value)
180 {
181 if(empty($value) || check_email($value))
182 {
183 return true;
184 }
185 else
186 {
187 return Loc::getMessage('SENDER_ENTITY_CONTACT_VALID_EMAIL');
188 }
189 }
190
198 {
200 $data = $event->getParameters();
201 if(isset($data['fields']['EMAIL']))
202 {
203 $result->modifyFields(array('EMAIL' => Recipient\Normalizer::normalizeEmail($data['fields']['EMAIL'])));
204 }
205
206 if(isset($data['fields']['CODE']))
207 {
208 $typeId = $data['fields']['TYPE_ID'] ?? null;
209 $isValid = Recipient\Validator::validate($data['fields']['CODE'], $typeId);
210 if (!$isValid)
211 {
212 $result->addError(new Entity\EntityError(Loc::getMessage('SENDER_ENTITY_CONTACT_VALID_CODE')));
213 }
214 else
215 {
216 $result->modifyFields(array(
217 'CODE' => Recipient\Normalizer::normalize($data['fields']['CODE'], $typeId)
218 ));
219 }
220 }
221
222 return $result;
223 }
224
232 {
234 $data = $event->getParameters();
235 $modify = [];
236 if(isset($data['fields']['EMAIL']))
237 {
238 $modify += array('EMAIL' => Recipient\Normalizer::normalizeEmail($data['fields']['EMAIL']));
239 $modify += array('CONSENT_STATUS' => 'N');
240 }
241
242 if(isset($data['fields']['CODE']))
243 {
244 $modify += array( 'CONSENT_STATUS' => 'N' );
245 $typeId = $data['fields']['TYPE_ID'] ?? null;
246 if (!$typeId)
247 {
248 $row = static::getRowById($data['primary']['ID']);
249 $typeId = $row['TYPE_ID'];
250 }
251 $isValid = Recipient\Validator::validate($data['fields']['CODE'], $typeId);
252 if (!$isValid)
253 {
254 $result->addError(new Entity\EntityError(Loc::getMessage('SENDER_ENTITY_CONTACT_VALID_CODE')));
255 }
256 else
257 {
258 $modify += array('CODE' => Recipient\Normalizer::normalize($data['fields']['CODE'], $typeId));
259 }
260 }
261 $result->modifyFields($modify);
262
263 return $result;
264 }
265
274 {
276 $data = $event->getParameters();
277
278 $primary = array('CONTACT_ID' => $data['primary']['ID']);
281
282 return $result;
283 }
284
292 public static function deleteList(array $filter): \Bitrix\Main\DB\Result
293 {
294 $entity = static::getEntity();
295 $connection = $entity->getConnection();
296
297 \CTimeZone::disable();
298 $sql = sprintf(
299 'DELETE FROM %s WHERE %s',
300 $connection->getSqlHelper()->quote($entity->getDbTableName()),
301 Query::buildFilterSql($entity, $filter)
302 );
303 $res = $connection->query($sql);
304 \CTimeZone::enable();
305
306 return $res;
307 }
308
314 public static function updateConsentStatus($primary, string $contactStatus)
315 {
316 ContactTable::update($primary,[
317 'CONSENT_STATUS' => $contactStatus,
318 'DATE_UPDATE' => new MainType\DateTime(),
319 'CONSENT_REQUEST' => new SqlExpression("CONSENT_REQUEST+1"),
320 ]);
321 }
322
332 public static function addIfNotExist(array $ar)
333 {
334 $id = false;
335 $listId = false;
336
337 if(array_key_exists('LIST_CODE', $ar) && array_key_exists('LIST_NAME', $ar))
338 {
339 $listId = ListTable::addIfNotExist($ar['LIST_CODE'], $ar['LIST_NAME']);
340 unset($ar['LIST_CODE'], $ar['LIST_NAME']);
341 }
342
343 $ar['EMAIL'] = mb_strtolower($ar['EMAIL']);
344 $contactDb = ContactTable::getList(array(
345 'select' => array('ID'),
346 'filter' => array(
347 '=CODE' => $ar['EMAIL'],
348 '=TYPE_ID' => Recipient\Type::EMAIL
349 )
350 ));
351 if($contact = $contactDb->fetch())
352 {
353 $id = $contact['ID'];
354 }
355 else
356 {
357 $ar['TYPE_ID'] = Recipient\Type::EMAIL;
358 $ar['CODE'] = $ar['EMAIL'];
359 unset($ar['EMAIL']);
360
361 $resultAdd = static::add($ar);
362 if($resultAdd->isSuccess())
363 $id = $resultAdd->getId();
364 }
365
366 if($listId && $id)
367 {
369 }
370
371 return $id;
372 }
373
380 public static function checkConnectors()
381 {
382 $connectorList = Connector\Manager::getConnectorList();
383 foreach($connectorList as $connector)
384 {
385 if($connector->requireConfigure()) continue;
386 static::addFromConnector($connector);
387 }
388 }
389
399 public static function addFromConnector(Connector\Base $connector, ?int $pageNumber = null, int $timeout = 0): array
400 {
401 $startTime = microtime(true);
402 $withoutNav = empty($pageNumber);
403 $result = false;
404 $onlyOneLoop = false;
405 $rowsInPage = 5;
406
407 $countAll = 0;
408 $countProcessed = 0;
409 $countUpdated = 0;
410 $countAdded = 0;
411 $countError = 0;
412
413 $dataDb = $connector->getResult();
414 if($dataDb->resourceCDBResult)
415 {
416 $dataDb = $dataDb->resourceCDBResult;
417 }
418 elseif($dataDb->resource)
419 {
420 $dataDb = new \CDBResult($dataDb->resource);
421 }
422 else
423 {
424 $dataDb = new \CDBResult();
425 $dataDb->initFromArray(array());
426 }
427
428 if(!is_subclass_of($dataDb, 'CDBResultMysql'))
429 {
430 $rowsInPage = 50;
431 $onlyOneLoop = true;
432 }
433
434 while($timeout==0 || microtime(true)-$startTime < $timeout)
435 {
436 if(!$withoutNav)
437 {
438 $dataDb->navStart($rowsInPage, false, $pageNumber);
439 $countAll = $dataDb->selectedRowsCount();
440 }
441
442 $listId = null;
443 while ($row = $dataDb->fetch())
444 {
445 if($withoutNav)
446 {
447 $countAll++;
448 }
449
450 $countProcessed++;
451
452 if(!$listId)
453 {
454 $listId = ListTable::addIfNotExist(
455 $connector->getModuleId() . '_' . $connector->getCode(),
456 Loc::getMessage('CONTACT_PULL_LIST_PREFIX').$connector->getName()
457 );
458 }
459
460 $id = null;
461 $contactDb = ContactTable::getList(array(
462 'select' => array('ID'),
463 'filter' => array('EMAIL' => $row['EMAIL'])
464 ));
465 if($contactRow = $contactDb->fetch())
466 {
467 $id = $contactRow['ID'];
468 $countUpdated++;
469 }
470 else
471 {
472 $resultAdd = static::add(array(
473 'NAME' => $row['NAME'],
474 'EMAIL' => $row['EMAIL'],
475 'USER_ID' => $row['USER_ID']
476 ));
477 if ($resultAdd->isSuccess())
478 {
479 $id = $resultAdd->getId();
480 $countAdded++;
481 } else
482 {
483 $countError++;
484 }
485 }
486
487 if($id)
489
490 }
491
492
493 if($withoutNav)
494 {
495 $result = false;
496 break;
497 }
498
499 if ($dataDb->NavPageCount <= $pageNumber)
500 {
501 $result = false;
502 break;
503 }
504 else
505 {
506 $pageNumber++;
507 $result = $pageNumber;
508 }
509
510 if($onlyOneLoop)
511 {
512 break;
513 }
514 }
515
516 if($withoutNav)
517 {
518 $countProgress = $countAll;
519 }
520 else
521 {
522 $countProgress = ($pageNumber-1) * $dataDb->NavPageSize;
523 if (!$result || $countProgress > $countAll) $countProgress = $countAll;
524 }
525
526 return array(
527 'STATUS' => $result,
528 'COUNT_ALL' => $countAll,
529 'COUNT_PROGRESS' => $countProgress,
530 'COUNT_PROCESSED' => $countProcessed,
531 'COUNT_NEW' => $countAdded,
532 'COUNT_ERROR' => $countError,
533 );
534 }
535
549 public static function upload(array $list, bool $isBlacklist = false, ?int $listId = null)
550 {
551 $updateCollection = new UpdateContactDtoCollection();
552 $updateItemFactory = new UpdateContactDtoFactory($isBlacklist);
553 foreach ($list as $item)
554 {
555 if (is_string($item))
556 {
557 $item = ['CODE' => $item];
558 }
559
560 if (empty($item['CODE']))
561 {
562 continue;
563 }
564 $code = trim((string)$item['CODE']);
565
566 $updateItem = $updateItemFactory->make($code, $item['NAME'] ?? null);
567 if ($updateItem)
568 {
569 $updateCollection->append($updateItem);
570 }
571 }
572
573 // insert contacts
574 if ($updateCollection->count() === 0)
575 {
576 return 0;
577 }
578
579 $listHash = hash('sha256', serialize($updateCollection->all()));
580 $lockKey = 'b_sender_contact_' . $listHash;
581
582 if (!Application::getConnection()->lock($lockKey))
583 {
584 return 0;
585 }
586
587 try
588 {
589 (new ContactUpdateService())->updateByCollection($updateCollection);
590
591 if (!$listId)
592 {
593 return $updateCollection->count();
594 }
595
596 $row = ListTable::getRowById($listId);
597 if (!$row)
598 {
599 return false;
600 }
601
602 // insert contacts & lists
603 (new ContactListUpdateService())->updateByCollection($updateCollection, $listId);
604
605 return ContactListTable::getCount(array('=LIST_ID' => $listId));
606 }
607 finally
608 {
609 Application::getConnection()->unlock($lockKey);
610 }
611 }
612
618 public static function getConflictFields(): array
619 {
620 return [
621 'TYPE_ID',
622 'CODE',
623 ];
624 }
625}
$connection
Определения actionsdefinitions.php:38
Определения result.php:20
Определения event.php:5
static getRowById($id, array $parameters=[])
Определения datamanager.php:380
static getList(array $parameters=array())
Определения datamanager.php:431
static getCount($filter=array(), array $cache=array())
Определения datamanager.php:516
static update($primary, array $data)
Определения datamanager.php:1256
static deleteList(array $filter)
Определения contactlist.php:105
static addIfNotExist($contactId, $listId)
Определения contactlist.php:79
const CONSENT_STATUS_WAIT
Определения contact.php:44
static onBeforeUpdate(Entity\Event $event)
Определения contact.php:231
static checkConnectors()
Определения contact.php:380
static getMap()
Определения contact.php:63
static getConflictFields()
Определения contact.php:618
static deleteList(array $filter)
Определения contact.php:292
static upload(array $list, bool $isBlacklist=false, ?int $listId=null)
Определения contact.php:549
static updateConsentStatus($primary, string $contactStatus)
Определения contact.php:314
const CONSENT_STATUS_DENY
Определения contact.php:46
static addIfNotExist(array $ar)
Определения contact.php:332
static checkEmail(?string $value)
Определения contact.php:179
static onBeforeAdd(Entity\Event $event)
Определения contact.php:197
const CONSENT_STATUS_NEW
Определения contact.php:45
const CONSENT_STATUS_ACCEPT
Определения contact.php:47
static onAfterDelete(Entity\Event $event)
Определения contact.php:273
static validateEmail()
Определения contact.php:164
static addFromConnector(Connector\Base $connector, ?int $pageNumber=null, int $timeout=0)
Определения contact.php:399
static getTableName()
Определения contact.php:53
static addIfNotExist($code, $name)
Определения list.php:122
static deleteList(array $filter)
Определения mailing.php:899
static normalize($code, $typeId=Type::EMAIL)
Определения normalizer.php:28
static normalizeEmail($code)
Определения normalizer.php:60
const EMAIL
Определения type.php:21
static validate($code, $typeId=Type::EMAIL)
Определения validator.php:27
$startTime
Определения sync.php:69
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$filter
Определения iblock_catalog_list.php:54
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
check_email($email, $strict=false, $domainCheck=false)
Определения tools.php:4571
Определения arrayresult.php:2
Определения ufield.php:9
Определения base.php:8
Определения agent.php:8
$event
Определения prolog_after.php:141
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199