Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
sharingajax.php
1<?php
3
15use Bitrix\Crm;
24
25Loc::loadMessages(__FILE__);
26
28{
29 private ?Sharing\Link\Factory $factory = null;
30
31 public function configureActions(): array
32 {
33 return [
34 'getUsersAccessibility' => [
35 '-prefilters' => [
36 ActionFilter\Authentication::class,
37 ActionFilter\Csrf::class
38 ],
39 '+postfilters' => [
40 new ActionFilter\Cors()
41 ],
42 ],
43 'saveEvent' => [
44 '-prefilters' => [
45 ActionFilter\Authentication::class,
46 ActionFilter\Csrf::class
47 ],
48 '+postfilters' => [
49 new ActionFilter\Cors()
50 ],
51 ],
52 'saveCrmEvent' => [
53 '-prefilters' => [
54 ActionFilter\Authentication::class,
55 ActionFilter\Csrf::class
56 ],
57 '+postfilters' => [
58 new ActionFilter\Cors()
59 ],
60 ],
61 'deleteEvent' => [
62 '-prefilters' => [
63 ActionFilter\Authentication::class,
64 ActionFilter\Csrf::class
65 ],
66 '+postfilters' => [
67 new ActionFilter\Cors()
68 ],
69 ],
70 'saveFirstEntry' => [
71 '-prefilters' => [
72 ActionFilter\Authentication::class,
73 ActionFilter\Csrf::class
74 ],
75 '+postfilters' => [
76 new ActionFilter\Cors()
77 ],
78 ],
79 'getConferenceLink' => [
80 '-prefilters' => [
81 ActionFilter\Authentication::class,
82 ActionFilter\Csrf::class
83 ],
84 '+postfilters' => [
85 new ActionFilter\Cors()
86 ],
87 ],
88 'getIcsFileContent' => [
89 '-prefilters' => [
90 ActionFilter\Authentication::class,
91 ActionFilter\Csrf::class
92 ],
93 '+postfilters' => [
94 new ActionFilter\Cors()
95 ],
96 ],
97 'handleTimelineNotify' => [
98 '-prefilters' => [
99 ActionFilter\Authentication::class,
100 ActionFilter\Csrf::class
101 ],
102 '+postfilters' => [
103 new ActionFilter\Cors()
104 ],
105 ],
106 ];
107 }
108
110 {
111 Sharing\Helper::disableOptionPayAttentionToNewSharingFeature();
112 }
113
114 public function enableUserSharingAction(): ?array
115 {
116 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
117 {
118 return null;
119 }
120
121 $sharing = new Sharing\Sharing(\CCalendar::GetUserId());
122 $result = $sharing->enable();
123 if (!$result->isSuccess())
124 {
125 $this->addErrors($this->getErrors());
126 return null;
127 }
128
129 return $sharing->getLinkInfo();
130 }
131
132 public function disableUserSharingAction(): ?bool
133 {
134 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
135 {
136 return null;
137 }
138
139 $sharing = new Sharing\Sharing(\CCalendar::GetUserId());
140 $result = $sharing->disable();
141 if (!$result->isSuccess())
142 {
143 $this->addErrors($this->getErrors());
144 return null;
145 }
146
147 return true;
148 }
149
150 public function disableUserLinkAction(?string $hash): bool
151 {
152 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
153 {
154 return false;
155 }
156
157 $sharing = new Sharing\Sharing(\CCalendar::GetUserId());
158 $result = $sharing->deactivateUserLink($hash);
159 if (!$result->isSuccess())
160 {
161 $this->addErrors($this->getErrors());
162
163 return false;
164 }
165
166 return true;
167 }
168
169 public function increaseFrequentUseAction(?string $hash)
170 {
171 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
172 {
173 return false;
174 }
175
176 $sharing = new Sharing\Sharing(\CCalendar::GetUserId());
177 $result = $sharing->increaseFrequentUse($hash);
178 if (!$result->isSuccess())
179 {
180 $this->addErrors($this->getErrors());
181
182 return false;
183 }
184
185 return true;
186 }
187
188 public function generateUserJointSharingLinkAction(array $memberIds): ?array
189 {
190 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
191 {
192 return null;
193 }
194
195 $userId = \CCalendar::GetCurUserId();
196 $result = (new Sharing\Sharing($userId))->generateUserJointLink($memberIds);
197 if (!$result->isSuccess())
198 {
199 $this->addErrors($this->getErrors());
200
201 return null;
202 }
203
204 return $result->getData();
205 }
206
207 public function getAllUserLinkAction(): ?array
208 {
209 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
210 {
211 return null;
212 }
213
214 $userId = \CCalendar::GetCurUserId();
215
216 return [
217 'userLinks' => (new Sharing\Sharing($userId))->getAllUserLinkInfo(),
218 'pathToUser' => Option::get('intranet', 'path_user', '/company/personal/user/#USER_ID#/', '-'),
219 ];
220 }
221
222 public function getUsersAccessibilityAction(): array
223 {
224 $request = $this->getRequest();
225
226 $userIds = $request->getPost('userIds');
227 $fromTs = $request->getPost('timestampFrom') / 1000;
228 $toTs = $request->getPost('timestampTo') / 1000;
229
230 if (!is_array($userIds) || !$fromTs || !$toTs)
231 {
232 return [];
233 }
234
236 'userIds' => array_map('intval', $userIds),
237 'timestampFrom' => $fromTs,
238 'timestampTo' => $toTs
239 ]))->getUsersAccessibilitySegmentsInUtc();
240 }
241
249 public function saveEventAction(): array
250 {
251 $connection = Application::getConnection();
252 $sqlHelper = $connection->getSqlHelper();
253
254 $result = [];
255 $request = $this->getRequest();
256
257 $userName = $sqlHelper->forSql(trim($request['userName'] ?? ''));
258 $userContact = $sqlHelper->forSql(trim($request['userContact'] ?? ''));
259 $parentLinkHash = $sqlHelper->forSql(trim($request['parentLinkHash'] ?? ''));
260 $ownerId = (int)($request['ownerId'] ?? null);
261 $ownerCreated = ($request['ownerCreated'] ?? null) === 'true';
262
263 $contactDataError = !Sharing\SharingEventManager::validateContactData($userContact);
264 $contactNameError = !Sharing\SharingEventManager::validateContactName($userName);
265 if ($contactDataError || $contactNameError)
266 {
267 $this->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_INCORRECT_CONTACT_DATA')));
268
269 return [
270 'contactDataError' => $contactDataError,
271 'contactNameError' => $contactNameError,
272 ];
273 }
274
276 $link = Link\Factory::getInstance()->getLinkByHash($parentLinkHash);
277
278 if (
279 !$link
280 || !$link->isActive()
281 || $link->getObjectType() !== Sharing\Link\Helper::USER_SHARING_TYPE
282 || $link->getObjectId() !== $ownerId
283 )
284 {
285 $this->addError(new Error('Link not found'));
286
287 return $result;
288 }
289
290 $userParams = [
291 'NAME' => $userName,
292 'CONTACT_DATA' => $userContact,
293 ];
294 if ($ownerCreated)
295 {
296 $userId = SharingUser::getInstance()->getAnonymousUserForOwner($userParams);
297 }
298 else
299 {
300 $userId = SharingUser::getInstance()->login(true, $userParams);
301 }
302
303
304 if (!$userId)
305 {
306 $this->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_USER_NOT_FOUND')));
307
308 return $result;
309 }
310
311 $eventData = Sharing\SharingEventManager::getEventDataFromRequest($request);
312 $eventData['eventName'] = Sharing\SharingEventManager::getSharingEventNameByUserName($userName);
313
314 $event = Sharing\SharingEventManager::prepareEventForSave($eventData, $userId, $link);
315
316 $sharingEventManager = new Sharing\SharingEventManager($event, $userId, $ownerId, $link);
317 $eventCreateResult = $sharingEventManager->createEvent(false, $userParams['NAME']);
318
319 if ($errors = $eventCreateResult->getErrors())
320 {
321 $this->addError($errors[0]);
322
323 return $result;
324 }
325
327 $event = $eventCreateResult->getData()['event'];
329 $eventLink = $eventCreateResult->getData()['eventLink'];
330
331 Sharing\Analytics::getInstance()->sendMeetingCreated($link);
332
333 // Auto-accepting meeting for owner and members
334 $this->autoAcceptSharingEvent($event->getId(), $ownerId);
335 foreach ($link->getMembers() as $member)
336 {
337 $this->autoAcceptSharingEvent($event->getId(), $member->getId());
338 }
339
341 $event = (new Mappers\Factory())->getEvent()->getById($event->getId());
342
343 $notificationService = null;
344 if (SharingEventManager::isEmailCorrect($userContact))
345 {
346 $notificationService = (new Sharing\Notification\Mail())
347 ->setEventLink($eventLink)
348 ->setEvent($event)
349 ;
350 }
351
352 $notificationService?->notifyAboutMeetingCreated($userContact);
353
354 return [
355 'eventId' => $event->getId(),
356 'eventName' => $event->getName(),
357 'eventLinkId' => $eventLink->getId(),
358 'eventLinkHash' => $eventLink->getHash(),
359 'eventLinkShortUrl' => Sharing\Helper::getShortUrl($eventLink->getUrl()),
360 ];
361 }
362
363 public function saveCrmEventAction(): array
364 {
365 $result = [];
366 $request = $this->getRequest();
367
368 if (!Loader::includeModule('crm'))
369 {
370 $this->addError(new Error('Module crm not found'));
371
372 return $result;
373 }
374
375 $connection = Application::getConnection();
376 $sqlHelper = $connection->getSqlHelper();
377
378
379 $crmDealLinkHash = $sqlHelper->forSql(trim($request['crmDealLinkHash'] ?? ''));
380 $ownerId = (int)($request['ownerId'] ?? null);
381 $ownerCreated = ($request['ownerCreated'] ?? null) === 'true';
382
384 $crmDealLink = Link\Factory::getInstance()->getLinkByHash($crmDealLinkHash);
385
386 if (
387 !$crmDealLink
388 || !$crmDealLink->isActive()
389 || $crmDealLink->getObjectType() !== Sharing\Link\Helper::CRM_DEAL_SHARING_TYPE
390 || $crmDealLink->getOwnerId() !== $ownerId
391 )
392 {
393 $this->addError(new Error('Link not found'));
394
395 return $result;
396 }
397
398 if (!$crmDealLink->getContactId()|| !$crmDealLink->getContactType())
399 {
400 $userName = $sqlHelper->forSql(trim($request['userName'] ?? ''));
401 $userContact = $sqlHelper->forSql(trim($request['userContact'] ?? ''));
402
403 $contactDataError = !Sharing\SharingEventManager::validateContactData($userContact);
404 $contactNameError = !Sharing\SharingEventManager::validateContactName($userName);
405 if ($contactDataError || $contactNameError)
406 {
407 $this->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_INCORRECT_CONTACT_DATA')));
408
409 return [
410 'contactDataError' => $contactDataError,
411 'contactNameError' => $contactNameError,
412 ];
413 }
414 }
415 else
416 {
417 $contactType = $crmDealLink->getContactType();
418 $contactId = $crmDealLink->getContactId();
419 $contactData = \Bitrix\Crm\Service\Container::getInstance()
420 ->getEntityBroker($contactType)
421 ->getById($contactId)
422 ;
423 if (!$contactData)
424 {
425 $this->addError(new Error('Contact not found'));
426
427 return $result;
428 }
429
430 $userName = '';
431 if ($contactType === \CCrmOwnerType::Contact)
432 {
433 $userName = $contactData->getFullName();
434 }
435 elseif ($contactType === \CCrmOwnerType::Company)
436 {
437 $userName = $contactData->getTitle();
438 }
439 $userContact = '';
440 }
441
442 $userParams = [
443 'NAME' => $userName,
444 'CONTACT_DATA' => $userContact,
445 ];
446 if ($ownerCreated)
447 {
448 $userId = SharingUser::getInstance()->getAnonymousUserForOwner($userParams);
449 }
450 else
451 {
452 $userId = SharingUser::getInstance()->login(true, $userParams);
453 }
454
455 $eventData = Sharing\SharingEventManager::getCrmEventDataFromRequest($request);
456 $eventData['eventName'] = Sharing\SharingEventManager::getSharingEventNameByUserName($userName);
457
458 $event = Sharing\SharingEventManager::prepareEventForSave($eventData, $userId, $crmDealLink);
459
460 $sharingEventManager = new Sharing\SharingEventManager($event, $userId, $ownerId, $crmDealLink);
461 $eventCreateResult = $sharingEventManager->createEvent(false, $userParams['NAME']);
462
463 if ($errors = $eventCreateResult->getErrors())
464 {
465 $this->addError($errors[0]);
466
467 return $result;
468 }
469
471 $event = $eventCreateResult->getData()['event'];
473 $eventLink = $eventCreateResult->getData()['eventLink'];
474
475 Sharing\Analytics::getInstance()->sendMeetingCreated($crmDealLink);
476
477 $dateFrom = $request['dateFrom'] ?? null;
478 $timezone = $request['timezone'] ?? null;
479
481 $eventStart = Util::getDateObject($dateFrom, false, $timezone);
482 $activityName = Loc::getMessage('EC_SHARINGAJAX_ACTIVITY_SUBJECT');
483
484 $crmDealLink->setLastStatus(null);
485 (new Sharing\Link\CrmDealLinkMapper())->update($crmDealLink);
486
487 // Create calendar sharing activity in deal
488 (new Sharing\Crm\ActivityManager($event->getId(), $crmDealLink, $userName))
489 ->createCalendarSharingActivity($activityName, $event->getDescription(), $eventStart)
490 ;
491
492 // Auto-accepting meeting for owner and members
493 $this->autoAcceptSharingEvent($event->getId(), $ownerId);
494 foreach ($crmDealLink->getMembers() as $member)
495 {
496 $this->autoAcceptSharingEvent($event->getId(), $member->getId());
497 }
498
499 //notify client about meeting is auto-accepted
500 if ($crmDealLink->getContactId() > 0)
501 {
502 Crm\Integration\Calendar\Notification\Manager::getSenderInstance($crmDealLink)
503 ->setCrmDealLink($crmDealLink)
504 ->setEvent($event)
505 ->setEventLink($eventLink)
506 ->sendCrmSharingAutoAccepted()
507 ;
508 }
509 else
510 {
511 (new Sharing\Notification\Mail())
512 ->setEventLink($eventLink)
513 ->setEvent($event)
514 ->notifyAboutMeetingCreated($userContact)
515 ;
516 }
517
518 return [
519 'eventId' => $event->getId(),
520 'eventName' => $event->getName(),
521 'eventLinkId' => $eventLink->getId(),
522 'eventLinkHash' => $eventLink->getHash(),
523 'eventLinkShortUrl' => Sharing\Helper::getShortUrl($eventLink->getUrl()),
524 ];
525 }
526
532 public function deleteEventAction(): array
533 {
534 $result = [];
535 $request = $this->getRequest();
536 $eventId = (int)$request['eventId'];
537 $eventLinkHash = Application::getConnection()->getSqlHelper()->forSql($request['eventLinkHash']);
538
540 $eventLink = Link\Factory::getInstance()->getLinkByHash($eventLinkHash);
541 if (
542 !$eventLink
543 || !$eventLink->isActive()
544 || $eventLink->getObjectType() !== Sharing\Link\Helper::EVENT_SHARING_TYPE
545 )
546 {
547 $this->addError(new Error('Link not found'));
548
549 return $result;
550 }
551
553 $event = (new Mappers\Event())->getById($eventId);
554 if (!$event)
555 {
556 $this->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_EVENT_NOT_FOUND')));
557
558 return $result;
559 }
560
561 if ($event->getId() !== $eventLink->getEventId())
562 {
563 $this->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_EVENT_DELETE_ERROR')));
564
565 return $result;
566 }
567
568 $sharingEventManager = new Sharing\SharingEventManager($event, $eventLink->getHostId(), $eventLink->getOwnerId());
569 $eventDeleteResult = $sharingEventManager->deleteEvent();
570
571 if ($eventDeleteResult->getErrors())
572 {
573 $this->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_EVENT_DELETE_ERROR')));
574 }
575 else
576 {
577 $sharingEventManager->deactivateEventLink($eventLink);
578 }
579
580 return $result;
581 }
582
586 public function saveFirstEntryAction()
587 {
588 $cookieName = 'CALENDAR_SHARING_FIRST_PAGE_VISITED';
589 $cookie = new Cookie($cookieName, 'Y', null, false);
590 Context::getCurrent()->getResponse()->addCookie($cookie);
591 }
592
593 public function saveLinkRuleAction(string $linkHash, array $ruleArray): array
594 {
595 $result = [];
596
597 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
598 {
599 $this->addError(new Error('Access denied'));
600
601 return $result;
602 }
603
604 $saveResult = \Bitrix\Calendar\Sharing\Link\Rule\Helper::getInstance()->saveLinkRule($linkHash, $ruleArray);
605
606 if (!$saveResult)
607 {
608 $this->addError(new Error('Error while trying to save rule'));
609 }
610
611 return $result;
612 }
613
614 private function currentUserIsNotResponsible(Sharing\Link\Link $link): bool
615 {
616 if (!Loader::includeModule('crm'))
617 {
618 return false;
619 }
620
621 if (!($link instanceof Sharing\Link\CrmDealLink))
622 {
623 return false;
624 }
625
626 $currentUserId = (new Crm\Service\Context())->getUserId();
627
628 return $this->getAssignedId($link) !== $currentUserId;
629 }
630
631 private function getAssignedId(Sharing\Link\CrmDealLink $link): ?int
632 {
633 $entityBroker = Crm\Service\Container::getInstance()->getEntityBroker(\CCrmOwnerType::Deal);
634 if (!$entityBroker)
635 {
636 return null;
637 }
638
639 $entity = $entityBroker->getById($link->getEntityId());
640 if (!$entity)
641 {
642 return null;
643 }
644
645 return $entity->getAssignedById();
646 }
647
657 public function getConferenceLinkAction(string $eventLinkHash): array
658 {
659 $result = [];
660 $eventLinkHash = Application::getConnection()->getSqlHelper()->forSql($eventLinkHash);
661
663 $eventLink = Link\Factory::getInstance()->getLinkByHash($eventLinkHash);
664 if (!$eventLink || !$eventLink->isActive() || $eventLink->getObjectType() !== Sharing\Link\Helper::EVENT_SHARING_TYPE)
665 {
666 $this->addError(new Error('Link not found'));
667
668 return $result;
669 }
670
671 $conferenceLink = (new Sharing\SharingConference($eventLink))->getConferenceLink();
672
673 if (!$conferenceLink)
674 {
675 $this->addError(new Error('Error while creating conference link'));
676
677 return $result;
678 }
679
680 $result['conferenceLink'] = $conferenceLink;
681
682 return $result;
683 }
684
688 public function getIcsFileContentAction(string $eventLinkHash): string
689 {
690 $result = '';
691 $eventLinkHash = Application::getConnection()->getSqlHelper()->forSql($eventLinkHash);
692
694 $eventLink = Link\Factory::getInstance()->getLinkByHash($eventLinkHash);
695 if (
696 !$eventLink
697 || !$eventLink->isActive()
698 || $eventLink->getObjectType() !== Sharing\Link\Helper::EVENT_SHARING_TYPE
699 )
700 {
701 $this->addError(new Error('Link not found'));
702
703 return $result;
704 }
705
707 $event = (new Mappers\Event())->getById($eventLink->getEventId());
708
709 if (!$event)
710 {
711 $this->addError(new Error(Loc::getMessage('EC_SHARINGAJAX_EVENT_ACCESS_DENIED')));
712
713 return $result;
714 }
715
716 $event->setName(SharingEventManager::getSharingEventNameByUserId($eventLink->getOwnerId()));
717 return IcsManager::getInstance()->getIcsFileContent($event, [
718 'eventUrl' => Sharing\Helper::getShortUrl($eventLink->getUrl()),
719 'conferenceUrl' => Sharing\Helper::getShortUrl($eventLink->getUrl() . Sharing\Helper::ACTION_CONFERENCE),
720 ]);
721 }
722
723 public function getDeletedSharedEventAction(int $entryId): array
724 {
725 if (Loader::includeModule('intranet') && !\Bitrix\Intranet\Util::isIntranetUser())
726 {
727 return [];
728 }
729
730 $event = \CCalendar::getDeletedSharedEvent($entryId);
731 $linkArray = [];
732 if (is_array($event))
733 {
735 $eventId = $entryId === $event['ID'] ? $entryId : $event['PARENT_ID'];
736 $link = (new Sharing\Link\Factory())->getDeletedEventLinkByEventId($eventId);
737 if (!is_null($link))
738 {
739 $linkArray = [
740 'canceledTimestamp' => $link->getCanceledTimestamp(),
741 'externalUserName' => $link->getExternalUserName(),
742 'externalUserId' => $link->getHostId(),
743 ];
744 }
745 }
746
747 return [
748 'entry' => $event,
749 'link' => $linkArray,
750 'userTimezone' => $this->getUserTimezoneName(),
751 ];
752 }
753
754 public function handleTimelineNotifyAction(): array
755 {
756 $result = [];
757
758 if (!Loader::includeModule('crm'))
759 {
760 $this->addError(new Error('Module crm not installed'));
761
762 return $result;
763 }
764
765 $connection = Application::getConnection();
766 $sqlHelper = $connection->getSqlHelper();
767 $request = $this->getRequest();
768 $linkHash = $sqlHelper->forSql(trim($request['linkHash'] ?? ''));
769 $entityType = $sqlHelper->forSql(trim($request['entityType'] ?? ''));
770 $notifyType = $sqlHelper->forSql(trim($request['notifyType']) ?? '');
771 $entityId = (int)($request['entityId'] ?? null);
772 $dateFrom = $request['dateFrom'] ?? null;
773 $timezone = $request['timezone'] ?? null;
774
775
777 $link = Link\Factory::getInstance()->getLinkByHash($linkHash);
778 if (
779 !$link
780 || !$link->isActive()
781 || $link->getObjectId() !== $entityId
782 || $link->getObjectType() !== $entityType
783 )
784 {
785 $this->addError(new Error('Link not found'));
786
787 return $result;
788 }
789
790 if (in_array($notifyType, Sharing\Crm\NotifyManager::NOTIFY_TYPES, true))
791 {
792 (new Sharing\Crm\NotifyManager($link, $notifyType))
793 ->sendSharedCrmActionsEvent(Util::getDateTimestamp($dateFrom, $timezone));
794
795 $link->setLastStatus($notifyType);
796 (new Sharing\Link\CrmDealLinkMapper())->update($link);
797 }
798
799 return $result;
800 }
801
802 public function updateSharingSettingsCollapsedAction(string $collapsed): void
803 {
804 $value = $collapsed === 'Y' ? 'Y' : 'N';
805 \CUserOptions::SetOption('calendar', 'sharingSettingsCollapsed', $value);
806 }
807
808 private function getUserTimezoneName(): string
809 {
810 $userId = \CCalendar::GetCurUserId();
811
812 return \CCalendar::getUserTimezoneName($userId);
813 }
814
815 private function autoAcceptSharingEvent(int $eventId, int $userId)
816 {
817 \CCalendarEvent::SetMeetingStatus([
818 'eventId' => $eventId,
819 'userId' => $userId,
820 'status' => 'Y',
821 'sharingAutoAccept' => true,
822 ]);
823 }
824}
generateUserJointSharingLinkAction(array $memberIds)
updateSharingSettingsCollapsedAction(string $collapsed)
saveLinkRuleAction(string $linkHash, array $ruleArray)
static getDateObject(string $date=null, ?bool $fullDay=true, ?string $tz='UTC')
Definition util.php:102
static getDateTimestamp(?string $dateFrom, ?string $timezone)
Definition util.php:690
static getConnection($name="")
static getCurrent()
Definition context.php:241
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29