Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
call.php
1<?php
2
3namespace Bitrix\Im\Call;
4
20
21class Call
22{
23 const STATE_NEW = 'new';
24 const STATE_INVITING = 'inviting';
25 const STATE_ANSWERED = 'answered';
26 const STATE_FINISHED = 'finished';
27
28 const TYPE_INSTANT = 1;
29 const TYPE_PERMANENT = 2;
30
31 const RECORD_TYPE_VIDEO = 'video';
32 const RECORD_TYPE_AUDIO = 'audio';
33
34 const PROVIDER_PLAIN = 'Plain';
35 const PROVIDER_BITRIX = 'Bitrix';
36 const PROVIDER_VOXIMPLANT = 'Voximplant';
37
38 protected $id;
39 protected $type;
40 protected $initiatorId;
41 protected $isPublic = false;
42 protected $publicId;
43 protected $provider;
44 protected $entityType;
45 protected $entityId;
46 protected $parentId;
47 protected $state;
48 protected $startDate;
49 protected $endDate;
50 protected $logUrl;
51 protected $chatId;
52 protected $uuid;
53 protected $secretKey;
54 protected $endpoint;
55
57 protected $associatedEntity = null;
59 protected $users;
60
62 protected $signaling;
63
67 protected function __construct()
68 {
69 }
70
74 public function getId()
75 {
76 return (int)$this->id;
77 }
78
82 public function getProvider()
83 {
84 return $this->provider;
85 }
86
90 public function getInitiatorId()
91 {
92 return $this->initiatorId;
93 }
94
99 public function getUser($userId)
100 {
101 $this->loadUsers();
102 return isset($this->users[$userId]) ? $this->users[$userId] : null;
103 }
104
109 public function getUsers()
110 {
111 $this->loadUsers();
112 return array_keys($this->users);
113 }
114
121 public function hasUser($userId)
122 {
123 $this->loadUsers();
124 return isset($this->users[$userId]);
125 }
126
133 public function addUser($newUserId)
134 {
135 $this->loadUsers();
136 if($this->users[$newUserId])
137 {
138 return $this->users[$newUserId];
139 }
140
141 if(count($this->users) >= $this->getMaxUsers())
142 {
143 return false;
144 }
145
146 $this->users[$newUserId] = CallUser::create([
147 'CALL_ID' => $this->id,
148 'USER_ID' => $newUserId,
149 'STATE' => CallUser::STATE_IDLE,
150 'LAST_SEEN' => null
151 ]);
152 $this->users[$newUserId]->save();
153
154 if($this->associatedEntity)
155 {
156 $this->associatedEntity->onUserAdd($newUserId);
157 }
158
159 return $this->users[$newUserId];
160 }
161
162 public function removeUser($userId)
163 {
164 $this->loadUsers();
165 if($this->users[$userId])
166 {
167 CallUser::delete($this->id, $userId);
168 unset($this->users[$userId]);
169 }
170 }
171
178 public function hasActiveUsers(bool $strict = true)
179 {
180 $this->loadUsers();
181 $states = [];
182
183 foreach ($this->users as $userId => $user)
184 {
185 $userState = $user->getState();
186 $states[$userState] = isset($states[$userState]) ? $states[$userState] + 1 : 1;
187 }
188 if($this->type == static::TYPE_PERMANENT || !$strict)
189 {
190 return $states[CallUser::STATE_READY] >= 1;
191 }
192 else
193 {
194 return $states[CallUser::STATE_READY] >= 2 || ($states[CallUser::STATE_READY] >= 1 && $states[CallUser::STATE_CALLING] >= 1);
195 }
196 }
197
198 public function getSignaling()
199 {
200 if(is_null($this->signaling))
201 {
202 $this->signaling = new Signaling($this);
203 }
204
205 return $this->signaling;
206 }
207
211 public function getAssociatedEntity()
212 {
214 }
215
217 {
218 $entity = EntityFactory::createEntity($this, $entityType, $entityId);
219
220 if(!$entity)
221 {
222 throw new ArgumentException("Unknown entity " . $entityType . "; " . $entityId);
223 }
224
225 $this->associatedEntity = $entity;
226 $this->entityType = $entityType;
227 $this->entityId = $entityId;
228 $this->save();
229
230 $this->getSignaling()->sendAssociatedEntityReplaced($this->getCurrentUserId());
231 }
232
239 public function checkAccess($userId)
240 {
241 return in_array($userId, $this->getUsers());
242 }
243
247 public function getState()
248 {
249 return $this->state;
250 }
251
255 public function getParentId()
256 {
257 return $this->parentId;
258 }
259
265 public function getChatId()
266 {
267 return $this->chatId;
268 }
269
270 public function getUuid()
271 {
272 return $this->uuid;
273 }
274
275 public function getSecretKey()
276 {
277 return $this->secretKey;
278 }
279
280 public function getEndpoint()
281 {
282 return $this->endpoint;
283 }
284
290 public function getStartDate(): DateTime
291 {
292 return $this->startDate;
293 }
294
300 public function getEndDate(): ?DateTime
301 {
302 return $this->endDate;
303 }
304
305 public function inviteUsers(int $senderId, array $toUserIds, $isLegacyMobile, $video = false, $sendPush = true)
306 {
307 $this->getSignaling()->sendInvite(
308 $senderId,
309 $toUserIds,
310 $isLegacyMobile,
311 $video,
312 $sendPush
313 );
314 }
315
319 public function updateState($state)
320 {
321 if($this->state == $state)
322 {
323 return false;
324 }
325 $prevState = $this->state;
326 $this->state = $state;
327 $updateResult = CallTable::updateState($this->getId(), $state);
328 if(!$updateResult)
329 {
330 return false;
331 }
332
333 if($this->associatedEntity)
334 {
335 $this->associatedEntity->onStateChange($state, $prevState);
336 }
337 return true;
338 }
339
340 public function setLogUrl(string $logUrl)
341 {
342 $this->logUrl = $logUrl;
343 }
344
345 public function setEndpoint($endpoint)
346 {
347 $this->endpoint = $endpoint;
348 }
349
350 public function finish()
351 {
352 if($this->endDate instanceof DateTime)
353 {
354 return;
355 }
356
357 $this->endDate = new DateTime();
358
359 if ($this->updateState(static::STATE_FINISHED))
360 {
361 $this->loadUsers();
362 foreach ($this->users as $callUser)
363 {
364 if ($callUser->getState() === CallUser::STATE_CALLING)
365 {
366 $callUser->updateState(CallUser::STATE_IDLE);
367 }
368 }
369 $this->getSignaling()->sendFinish();
370 $this->saveStat();
371 }
372 }
373
374 public function getConnectionData(int $userId): ?array
375 {
376 return null;
377 }
378
379 public function toArray($currentUserId = 0, $withSecrets = false)
380 {
381 $result = [
382 'ID' => $this->id,
383 'TYPE' => $this->type,
384 'INITIATOR_ID' => $this->initiatorId,
385 'IS_PUBLIC' => $this->isPublic ? 'Y' : 'N',
386 'PUBLIC_ID' => $this->publicId,
387 'PROVIDER' => $this->provider,
388 'ENTITY_TYPE' => $this->entityType,
389 'ENTITY_ID' => $this->entityId,
390 'PARENT_ID' => $this->parentId,
391 'STATE' => $this->state,
392 'START_DATE' => $this->startDate,
393 'END_DATE' => $this->endDate,
394 'LOG_URL' => $this->logUrl,
395 'CHAT_ID' => $this->chatId,
396 'ASSOCIATED_ENTITY' => ($this->associatedEntity) ? $this->associatedEntity->toArray($currentUserId) : [],
397 'UUID' => $this->uuid,
398 'ENDPOINT' => $this->endpoint,
399 ];
400 if ($withSecrets)
401 {
402 $result['SECRET_KEY'] = $this->secretKey;
403 }
404
405 return $result;
406 }
407
408 public function save()
409 {
410 $fields = $this->toArray(0, true);
411 unset($fields['ID']);
412
413 if(!$this->id)
414 {
415 $insertResult = CallTable::add($fields);
416 $this->id = $insertResult->getId();
417 }
418 else
419 {
420 $updateResult = CallTable::update($this->id, $fields);
421 }
422 }
423
424 public function makeClone($newProvider = null)
425 {
426 $callFields = $this->toArray();
427 $callFields['ID'] = null;
428 $callFields['PUBLIC_ID'] = randString(10);
429 $callFields['STATE'] = static::STATE_NEW;
430 $callFields['PROVIDER'] = $newProvider ?? $callFields['PROVIDER'];
431 $callFields['PARENT_ID'] = $this->id;
432
433 $instance = CallFactory::createWithArray($callFields['PROVIDER'], $callFields);
434 $instance->save();
435
436 $instance->users = [];
437 foreach ($this->getUsers() as $userId)
438 {
439 $instance->users[$userId] = CallUser::create([
440 'CALL_ID' => $instance->id,
441 'USER_ID' => $userId,
442 'STATE' => $instance->users[$userId] ? $instance->users[$userId]->getState() : CallUser::STATE_IDLE,
443 'LAST_SEEN' => null
444 ]);
445 $instance->users[$userId]->save();
446 }
447
448 return $instance;
449 }
450
451 protected function loadUsers()
452 {
453 if(is_array($this->users))
454 return;
455
456 $this->users = array();
457
458 $cursor = CallUserTable::getList(array(
459 'filter' => array(
460 '=CALL_ID' => $this->id
461 )
462 ));
463
464 while($row = $cursor->fetch())
465 {
466 $this->users[$row['USER_ID']] = CallUser::create($row);
467 }
468 }
469
470 protected function saveStat()
471 {
472 $callLength = 0;
473 if ($this->startDate instanceof DateTime && $this->endDate instanceof DateTime)
474 {
475 $callLength = $this->endDate->getTimestamp() - $this->startDate->getTimestamp();
476 }
477 $userCountChat = count($this->users);
478
479 $usersActive = 0;
480 $mobileUsers = 0;
481 $externalUsers = 0;
482 $screenShared = false;
483 $recorded = false;
484 $authTypes = UserTable::getList([
485 'select' => ['ID', 'EXTERNAL_AUTH_ID'],
486 'filter' => ['=ID' => $this->getUsers()]
487 ])->fetchAll();
488 $authTypes = array_column($authTypes, 'EXTERNAL_AUTH_ID', 'ID');
489 foreach ($this->users as $userId => $user)
490 {
491 if ($user->getLastSeen() != null)
492 {
493 $usersActive++;
494 }
495 if ($user->isUaMobile())
496 {
497 $mobileUsers++;
498 }
499 if ($authTypes[$userId] === Auth::AUTH_TYPE)
500 {
501 $externalUsers++;
502 if ($user->getFirstJoined())
503 {
504 $userLateness = $user->getFirstJoined()->getTimestamp() - $this->startDate->getTimestamp();
505 AddEventToStatFile("im", "im_call_finish", $this->id, $userLateness, "user_lateness", $userId);
506 }
507 }
508 if ($user->wasRecorded())
509 {
510 $recorded = true;
511 }
512 if ($user->wasRecorded())
513 {
514 $screenShared = true;
515 }
516 }
517
518 $chatType = null;
519 $finishStatus = 'normal';
520 if ($this->entityType === EntityType::CHAT)
521 {
522 if(is_numeric($this->entityId))
523 {
524 $chatType = 'private';
525 // private chat, entity id === other user id
526 $otherUserState =
527 $this->getUser($this->entityId)
528 ? $this->getUser($this->entityId)->getState()
529 : ''
530 ;
531
532 if ($otherUserState == CallUser::STATE_DECLINED)
533 {
534 $finishStatus = 'declined';
535 }
536 else if ($otherUserState == CallUser::STATE_BUSY)
537 {
538 $finishStatus = 'busy';
539 }
540 else if ($otherUserState == CallUser::STATE_UNAVAILABLE || $otherUserState == CallUser::STATE_CALLING)
541 {
542 $finishStatus = 'unavailable';
543 }
544 }
545 else
546 {
547 $chatId = Dialog::getChatId($this->entityId);
548 $isVideoConf = (bool)AliasTable::getRow([
549 'filter' => ['=ENTITY_ID' => $chatId, '=ENTITY_TYPE' => \Bitrix\Im\Alias::ENTITY_TYPE_VIDEOCONF]
550 ]);
551 $chatType = 'group';
552 }
553 }
554
555 if ($callLength > 30 && $finishStatus === 'normal')
556 {
557 \Bitrix\Im\Limit::incrementCounter(\Bitrix\Im\Limit::COUNTER_CALL_SUCCESS);
558 }
559
560 AddEventToStatFile("im", "im_call_finish", $this->id, $userCountChat, "user_count_chat", 0);
561 AddEventToStatFile("im", "im_call_finish", $this->id, $usersActive, "user_count_call", 0);
562 AddEventToStatFile("im", "im_call_finish", $this->id, $mobileUsers, "user_count_mobile", 0);
563 AddEventToStatFile("im", "im_call_finish", $this->id, $externalUsers, "user_count_external", 0);
564 AddEventToStatFile("im", "im_call_finish", $this->id, $callLength, "call_length", 0);
565 AddEventToStatFile("im", "im_call_finish", $this->id, ($screenShared ? "Y" : "N"), "screen_shared", 0);
566 AddEventToStatFile("im", "im_call_finish", $this->id, ($recorded ? "Y" : "N"), "recorded", 0);
567 if($chatType)
568 {
569 AddEventToStatFile("im","im_call_finish", $this->id, $chatType, "chat_type", 0);
570 }
571 if (isset($isVideoConf))
572 {
573 AddEventToStatFile("im","im_call_finish", $this->id, ($isVideoConf ? "Y" : "N"), "is_videoconf", 0);
574 }
575 AddEventToStatFile("im","im_call_finish", $this->id, $finishStatus, "status", 0);
576 }
577
578 public static function isFeedbackAllowed(): bool
579 {
580 if (Loader::includeModule('bitrix24'))
581 {
582 return \CBitrix24::getPortalZone() == 'ru';
583 }
584
585 return Option::get('im', 'allow_call_feedback', 'N') === 'Y';
586 }
587
588 public function getMaxUsers()
589 {
590 if ($this->provider == static::PROVIDER_VOXIMPLANT)
591 {
592 return static::getMaxCallServerParticipants();
593 }
594
595 return (int)Option::get('im', 'turn_server_max_users');
596 }
597
598 public function getLogToken(int $userId = 0, int $ttl = 3600) : string
599 {
600 $userId = $userId ?: $this->getCurrentUserId();
601 if(!$userId)
602 {
603 return '';
604 }
605
606 if (Loader::includeModule("bitrix24") && defined('BX24_HOST_NAME'))
607 {
608 $portalId = BX24_HOST_NAME;
609 }
610 else if (defined('IM_CALL_LOG_HOST'))
611 {
612 $portalId = IM_CALL_LOG_HOST;
613 }
614 else
615 {
616 return '';
617 }
618
619 $secret = Option::get('im', 'call_log_secret');
620 if ($secret == '')
621 {
622 return '';
623 }
624
625 return JWT::encode(
626 [
627 'prt' => $portalId,
628 'call' => $this->getId(),
629 'usr' => $userId,
630 'exp' => (new DateTime())->getTimestamp() + $ttl
631 ],
632 $secret
633 );
634 }
635
636 public static function getLogService() : string
637 {
638 return (string)Option::get('im', 'call_log_service');
639 }
640
641 public static function getMaxParticipants()
642 {
643 if (static::isCallServerEnabled())
644 {
645 return static::getMaxCallServerParticipants();
646 }
647 else
648 {
649 return (int)Option::get('im', 'turn_server_max_users');
650 }
651 }
652
653 public static function getMaxCallServerParticipants()
654 {
655 if(Loader::includeModule('bitrix24'))
656 {
657 return (int)\Bitrix\Bitrix24\Feature::getVariable('im_max_call_participants');
658 }
659 return (int)Option::get('im', 'call_server_max_users');
660 }
661
666 {
667 $instance = new static();
668 $instance->type = $type;
669 $instance->initiatorId = $initiatorId;
670 $instance->provider = $provider;
671 $instance->entityType = $entityType;
672 $instance->entityId = $entityId;
673 $instance->startDate = new DateTime();
674 $instance->publicId = randString(10);
675 $instance->state = static::STATE_NEW;
676
677 $instance->associatedEntity = Integration\EntityFactory::createEntity($instance, $entityType, $entityId);
678 $instance->chatId = $instance->associatedEntity->getChatId();
679
680 $instance->save();
681
682 // todo: remove when the calls are supported in the mobile
683 $instance->associatedEntity->onCallCreate();
684
685 $instance->users = [];
686 foreach ($instance->associatedEntity->getUsers() as $userId)
687 {
688 $instance->users[$userId] = CallUser::create([
689 'CALL_ID' => $instance->id,
690 'USER_ID' => $userId,
692 'LAST_SEEN' => null
693 ]);
694 $instance->users[$userId]->save();
695 }
696
697 $instance->initCall();
698
699 $event = new Event(
700 'im',
701 'onCallCreate',
702 array(
703 'id' => $instance->id,
704 'type' => $instance->type,
705 'initiatorId' => $instance->initiatorId,
706 'provider' => $instance->provider,
707 'entityType' => $instance->entityType,
708 'entityId' => $instance->entityId,
709 'startDate' => $instance->startDate,
710 'publicId' => $instance->publicId,
711 'chatId' => $instance->chatId,
712 )
713 );
714 $event->send();
715
716 return $instance;
717 }
718
719 protected function initCall()
720 {
721 // to be overridden
722 }
723
736 public static function searchActive($type, $provider, $entityType, $entityId, $currentUserId = 0)
737 {
738 if (!$currentUserId)
739 {
740 $currentUserId = \Bitrix\Im\User::getInstance()->getId();
741 }
742 $query = CallTable::query()
743 ->addSelect("*")
744 ->where("TYPE", $type)
745 ->where("PROVIDER", $provider)
746 ->where("ENTITY_TYPE", $entityType)
747 ->whereNull("END_DATE")
748 ->setOrder(["ID" => "DESC"])
749 ->setLimit(1);
750
751 if ($entityType === EntityType::CHAT && strpos($entityId, "chat") !== 0)
752 {
753 $query->where("INITIATOR_ID", $entityId);
754 $query->where("ENTITY_ID", $currentUserId);
755 }
756 else
757 {
758 $query->where("ENTITY_ID", $entityId);
759 }
760
761 $callFields = $query->exec()->fetch();
762
763 if(!$callFields)
764 {
765 return null;
766 }
767
768 $instance = static::createWithArray($callFields);
769 if($instance->hasActiveUsers(false))
770 {
771 return $instance;
772 }
773 return null;
774 }
775
776 public static function searchActiveByUuid(string $uuid): ?Call
777 {
778 $callFields = CallTable::query()
779 ->addSelect("*")
780 ->where("UUID", $uuid)
781 ->setLimit(1)
782 ->exec()
783 ->fetch()
784 ;
785
786 if(!$callFields)
787 {
788 return null;
789 }
790
791 return static::createWithArray($callFields);
792 }
793
800 public static function createWithArray(array $fields)
801 {
802 $instance = new static();
803
804 $instance->id = $fields['ID'];
805 $instance->type = (int)$fields['TYPE'];
806 $instance->initiatorId = $fields['INITIATOR_ID'];
807 $instance->isPublic = $fields['IS_PUBLIC'];
808 $instance->publicId = $fields['PUBLIC_ID'];
809 $instance->provider = $fields['PROVIDER'];
810 $instance->entityType = $fields['ENTITY_TYPE'];
811 $instance->entityId = $fields['ENTITY_ID'];
812 $instance->startDate = isset ($fields['START_DATE']) && $fields['START_DATE'] instanceof DateTime ? $fields['START_DATE'] : null;
813 $instance->endDate = isset ($fields['END_DATE']) && $fields['END_DATE'] instanceof DateTime ? $fields['END_DATE'] : null;
814 $instance->parentId = (int)$fields['PARENT_ID'] ?: null;
815 $instance->state = $fields['STATE'];
816 $instance->logUrl = $fields['LOG_URL'];
817 $instance->chatId = $fields['CHAT_ID'];
818 $instance->uuid = $fields['UUID'];
819 $instance->secretKey = $fields['SECRET_KEY'];
820 $instance->endpoint = $fields['ENDPOINT'];
821
822 if($instance->entityType && $instance->entityId)
823 {
824 $instance->associatedEntity = Integration\EntityFactory::createEntity($instance, $instance->entityType, $instance->entityId);
825 }
826
827 $instance->initCall();
828
829 return $instance;
830 }
831
841 public static function createWithPublicId($publicId)
842 {
843 $row = CallTable::getRow([
844 'filter' => [
845 '=PUBLIC_ID' => $publicId
846 ]
847 ]);
848
849 if(is_array($row))
850 {
851 return static::createWithArray($row);
852 }
853 else
854 {
855 return false;
856 }
857 }
858
859 public static function loadWithId($id)
860 {
861 $row = CallTable::getRowById($id);
862
863 if(is_array($row))
864 {
865 return static::createWithArray($row);
866 }
867 else
868 {
869 return false;
870 }
871 }
872
873 public static function isCallServerEnabled(): bool
874 {
875 if (Loader::includeModule("bitrix24"))
876 {
877 return true;
878 }
879 if (!ModuleManager::isModuleInstalled("voximplant"))
880 {
881 return false;
882 }
883
884 return (bool)Option::get("im", "call_server_enabled");
885 }
886
890 public static function isBitrixCallServerEnabled(): bool
891 {
893 }
894
895 public static function isBitrixCallEnabled(): bool
896 {
897 $isEnabled = Option::get('im', 'bitrix_call_enabled', 'N');
898
899 return $isEnabled === 'Y';
900 }
901
902 public static function isVoximplantCallServerEnabled(): bool
903 {
905 }
906
907 protected function getCurrentUserId() : int
908 {
909 return $GLOBALS['USER'] ? (int)$GLOBALS['USER']->getId() : 0;
910 }
911
912 public static function onVoximplantConferenceFinished(Event $event)
913 {
914 $callId = $event->getParameter('CONFERENCE_CALL_ID');
915 $logUrl = $event->getParameter('LOG_URL');
916 if (!$logUrl)
917 {
918 return;
919 }
920
921 $call = Call::loadWithId($callId);
922 if (!$call)
923 {
924 return;
925 }
926 $call->finish();
927 $call->setLogUrl($logUrl);
928 $call->save();
929 }
930}
const ENTITY_TYPE_VIDEOCONF
Definition alias.php:13
const TYPE_INSTANT
Definition call.php:28
getUser($userId)
Definition call.php:99
inviteUsers(int $senderId, array $toUserIds, $isLegacyMobile, $video=false, $sendPush=true)
Definition call.php:305
static createWithArray(array $fields)
Definition call.php:800
updateState($state)
Definition call.php:319
static isBitrixCallEnabled()
Definition call.php:895
addUser($newUserId)
Definition call.php:133
setLogUrl(string $logUrl)
Definition call.php:340
getLogToken(int $userId=0, int $ttl=3600)
Definition call.php:598
static getMaxCallServerParticipants()
Definition call.php:653
const PROVIDER_PLAIN
Definition call.php:34
const RECORD_TYPE_VIDEO
Definition call.php:31
hasActiveUsers(bool $strict=true)
Definition call.php:178
static searchActiveByUuid(string $uuid)
Definition call.php:776
static createWithPublicId($publicId)
Definition call.php:841
static getLogService()
Definition call.php:636
const STATE_ANSWERED
Definition call.php:25
const RECORD_TYPE_AUDIO
Definition call.php:32
static isFeedbackAllowed()
Definition call.php:578
makeClone($newProvider=null)
Definition call.php:424
toArray($currentUserId=0, $withSecrets=false)
Definition call.php:379
setAssociatedEntity($entityType, $entityId)
Definition call.php:216
static getMaxParticipants()
Definition call.php:641
static onVoximplantConferenceFinished(Event $event)
Definition call.php:912
const PROVIDER_BITRIX
Definition call.php:35
removeUser($userId)
Definition call.php:162
setEndpoint($endpoint)
Definition call.php:345
static createWithEntity($type, $provider, $entityType, $entityId, $initiatorId)
Definition call.php:665
checkAccess($userId)
Definition call.php:239
const TYPE_PERMANENT
Definition call.php:29
hasUser($userId)
Definition call.php:121
static isBitrixCallServerEnabled()
Definition call.php:890
const STATE_FINISHED
Definition call.php:26
static searchActive($type, $provider, $entityType, $entityId, $currentUserId=0)
Definition call.php:736
const STATE_INVITING
Definition call.php:24
getConnectionData(int $userId)
Definition call.php:374
static loadWithId($id)
Definition call.php:859
const PROVIDER_VOXIMPLANT
Definition call.php:36
static isVoximplantCallServerEnabled()
Definition call.php:902
static isCallServerEnabled()
Definition call.php:873
static delete($callId, $userId)
Definition calluser.php:175
static create(array $fields)
Definition calluser.php:28
static getChatId($dialogId, $userId=null)
Definition dialog.php:91
const COUNTER_CALL_SUCCESS
Definition limit.php:6
getParameter($key)
Definition event.php:80
static isModuleInstalled($moduleName)
static encode($payload, $key, $alg='HS256', $keyId=null, $head=null)
Definition jwt.php:161
$GLOBALS['____1444769544']
Definition license.php:1