PageRenderTime 53ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/calendar/lib/ical/outcomingeventmanager.php

https://gitlab.com/alexprowars/bitrix
PHP | 460 lines | 376 code | 59 blank | 25 comment | 14 complexity | 6d3d9b6c01019548eba4e82d1c7bdef7 MD5 | raw file
  1. <?php
  2. namespace Bitrix\Calendar\ICal;
  3. use Bitrix\Calendar\Util;
  4. use Bitrix\Main\Loader;
  5. use Bitrix\Main\Localization\Loc;
  6. use Bitrix\Main\Text\Encoding;
  7. use Bitrix\Calendar\ICal\Basic\{Dictionary, ICalUtil};
  8. class OutcomingEventManager
  9. {
  10. const ATTACHMENT_NAME = 'invite.ics';
  11. const CHARSET = 'utf-8';
  12. const CONTENT_TYPE = 'text/calendar';
  13. const MAX_SENT = 3;
  14. /**
  15. * @var string
  16. */
  17. private $method;
  18. /**
  19. * @var string
  20. */
  21. private $uid;
  22. /**
  23. * @var string
  24. */
  25. private $status;
  26. /**
  27. * @var array
  28. */
  29. private $eventFields;
  30. /**
  31. * @var array
  32. */
  33. private $attendees;
  34. /**
  35. * @var array
  36. */
  37. private $receiver;
  38. /**
  39. * @var array
  40. */
  41. private $sender;
  42. private $answer;
  43. /**
  44. * @var mixed
  45. */
  46. private $changeFields;
  47. private $counterInvitations;
  48. public static function getInstance(array $params): OutcomingEventManager
  49. {
  50. return new self($params);
  51. }
  52. public function __construct(array $params)
  53. {
  54. $this->method = $params['icalMethod'];
  55. $this->eventFields = $params['arFields'];
  56. $this->attendees = $params['userIndex'];
  57. $this->receiver = $params['receiver'];
  58. $this->sender = $params['sender'];
  59. $this->changeFields = $params['changeFields'];
  60. $this->counterInvitations = 0;
  61. }
  62. public function __serialize(): array
  63. {
  64. return [
  65. 'method' => $this->method,
  66. 'eventFields' => $this->eventFields,
  67. 'attendees' => $this->attendees,
  68. 'receiver' => $this->receiver,
  69. 'sender' => $this->sender,
  70. 'changeFields' => $this->changeFields,
  71. ];
  72. }
  73. public function __unserialize(array $data): void
  74. {
  75. $this->method = $data['method'];
  76. $this->eventFields = $data['eventFields'];
  77. $this->attendees = $data['attendees'];
  78. $this->receiver = $data['receiver'];
  79. $this->sender = $data['sender'];
  80. $this->changeFields = $data['changeFields'];
  81. }
  82. public function inviteUser(): OutcomingEventManager
  83. {
  84. $this->checkOrganizerEmail();
  85. $filesContent = $this->getRequestContent();
  86. $mailEventFields = $this->getRequestMailEventFields();
  87. $files = $this->getFiles();
  88. $this->status = \CEvent::sendImmediate('SEND_ICAL_INVENT', SITE_ID, $mailEventFields, "Y", "", $files, '', $filesContent);
  89. return $this;
  90. }
  91. public function replyInvitation(): OutcomingEventManager
  92. {
  93. $this->answer = $this->attendees[$this->eventFields['OWNER_ID']]['STATUS'];
  94. $filesContent = $this->getReplyContent();
  95. $mailEventFields = $this->getReplyMailEventFields();
  96. $files = $this->getFiles();
  97. $this->status = \CEvent::sendImmediate('SEND_ICAL_INVENT', SITE_ID, $mailEventFields, "Y", "", $files, '', $filesContent);
  98. return $this;
  99. }
  100. public function cancelInvitation(): OutcomingEventManager
  101. {
  102. $filesContent = $this->getCancelContent();
  103. $mailEventFields = $this->getCancelMailEventFields();
  104. $files = [];
  105. $this->status = \CEvent::sendImmediate('SEND_ICAL_INVENT', SITE_ID, $mailEventFields, "Y", "", $files, '', $filesContent);
  106. return $this;
  107. }
  108. public function getUId(): string
  109. {
  110. return $this->uid;
  111. }
  112. public function incrementCounterInvitations()
  113. {
  114. $this->counterInvitations++;
  115. }
  116. public function getEventId()
  117. {
  118. return $this->eventFields['ID'];
  119. }
  120. public function getEvent()
  121. {
  122. return $this->eventFields;
  123. }
  124. public function getMethod()
  125. {
  126. return $this->method;
  127. }
  128. public function getCountInvitations()
  129. {
  130. return $this->counterInvitations;
  131. }
  132. public function getStatus(): string
  133. {
  134. return $this->status;
  135. }
  136. public function getReceiver()
  137. {
  138. return $this->receiver;
  139. }
  140. private function getSenderAddress(): string
  141. {
  142. return $this->sender['EMAIL'];
  143. }
  144. private function getReceiverAddress(): string
  145. {
  146. if (isset($this->receiver['MAILTO']))
  147. {
  148. return $this->receiver['MAILTO'];
  149. }
  150. return $this->receiver['EMAIL'];
  151. }
  152. private function getBodyMessage(): string
  153. {
  154. return 'ical body message';
  155. }
  156. private function getSubjectMessage(): string
  157. {
  158. $result = '';
  159. $siteName = \COption::GetOptionString("main", "site_name", '');
  160. if ($siteName !== '')
  161. {
  162. $result = "[".$siteName."]";
  163. }
  164. switch ($this->method)
  165. {
  166. case 'request':
  167. $result .= ' ' . Loc::getMessage("EC_CALENDAR_ICAL_MAIL_METHOD_REQUEST");
  168. break;
  169. case 'edit':
  170. $result .= ' ' . Loc::getMessage("EC_CALENDAR_ICAL_MAIL_METHOD_EDIT");
  171. break;
  172. case 'cancel':
  173. $result .= ' ' . Loc::getMessage("EC_CALENDAR_ICAL_MAIL_METHOD_CANCEL");
  174. break;
  175. case 'reply':
  176. $result .= ' ' . $this->answer === 'accepted'
  177. ? Loc::getMessage('EC_CALENDAR_ICAL_MAIL_METHOD_REPLY_ACCEPTED')
  178. : Loc::getMessage('EC_CALENDAR_ICAL_MAIL_METHOD_REPLY_DECLINED');
  179. break;
  180. }
  181. $result .= ": ".$this->eventFields['NAME'];
  182. return $result;
  183. }
  184. private function getFiles(): array
  185. {
  186. return [];
  187. }
  188. private function getRequestContent(): array
  189. {
  190. global $APPLICATION;
  191. $attachmentManager = new OutcomingAttachmentManager ($this->eventFields, $this->attendees, $this->method);
  192. $attachmentManager->prepareRequestAttachment();
  193. $this->uid = $attachmentManager->getUid();
  194. $fileContent = Encoding::convertEncoding($attachmentManager->getAttachment(), SITE_CHARSET, "utf-8");
  195. return [[
  196. 'CONTENT' => $fileContent,
  197. 'CONTENT_TYPE' => self::CONTENT_TYPE,
  198. 'METHOD' => Dictionary::METHODS[$this->method],
  199. 'CHARSET' => self::CHARSET,
  200. 'NAME' => self::ATTACHMENT_NAME,
  201. 'ID' => ICalUtil::getUniqId(),
  202. ]];
  203. }
  204. private function getRequestMailEventFields(): array
  205. {
  206. }
  207. private function getReplyMailEventFields()
  208. {
  209. return [
  210. 'EMAIL_FROM' => $this->getSenderAddress(),
  211. 'EMAIL_TO' => $this->getReceiverAddress(),
  212. // 'EMAIL_TO' => $this->getMailtoAddress(),
  213. 'MESSAGE_SUBJECT' => $this->getSubjectMessage(),
  214. 'MESSAGE_PHP' => $this->getReplyBodyMessage(),
  215. 'NAME' => $this->eventFields['NAME'],
  216. 'ANSWER' => $this->answer,
  217. 'DATE_FROM' => $this->eventFields['DATE_FROM_MAIL'],
  218. 'DATE_TO' => $this->eventFields['DATE_TO'],
  219. 'DESCRIPTION' => str_replace("\r\n", "#$&#$&#$&", $this->eventFields['DESCRIPTION']),
  220. 'ATTENDEES' => $this->getAttendeesList(),
  221. 'ATTENDEES_LIST' => $this->getAttendeesList(),
  222. 'ORGANIZER' => $this->getOrganizerName(),
  223. 'LOCATION' => $this->eventFields['LOCATION'],
  224. 'FILES_LINK' =>$this->getFilesLink(),
  225. 'METHOD' => $this->method,
  226. ];
  227. }
  228. private function getCancelMailEventFields()
  229. {
  230. return [
  231. "=Reply-To" => $this->getOrganizerName().' <'.$this->getReceiverAddress().'>',
  232. "=From" => $this->getOrganizerName().' <'.$this->getSenderAddress().'>',
  233. "=Message-Id" => $this->getMessageId(),
  234. "=In-Reply-To" => $this->getMessageReplyTo(),
  235. 'EMAIL_FROM' => $this->getSenderAddress(),
  236. 'EMAIL_TO' => $this->getReceiverAddress(),
  237. 'MESSAGE_SUBJECT' => $this->getSubjectMessage(),
  238. 'MESSAGE_PHP' => $this->getBodyMessage(),
  239. 'DATE_FROM' => $this->eventFields['DATE_FROM'],
  240. 'DATE_TO' => $this->eventFields['DATE_TO'],
  241. 'NAME' => $this->eventFields['NAME'],
  242. 'DESCRIPTION' => str_replace("\r\n", "#$&#$&#$&", $this->eventFields['DESCRIPTION']),
  243. 'ATTENDEES' => $this->getAttendeesList(),
  244. 'ORGANIZER' => $this->getOrganizerName(),
  245. 'LOCATION' => $this->eventFields['LOCATION'],
  246. 'FILES_LINK' =>$this->getFilesLink(),
  247. 'METHOD' => $this->method,
  248. ];
  249. }
  250. private function getAttendeesList(): string
  251. {
  252. if ($this->eventFields['MEETING']['HIDE_GUESTS'])
  253. {
  254. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_HIDE_GUESTS_INFORMATION');
  255. }
  256. $attendees = [];
  257. foreach ($this->attendees as $attendee)
  258. {
  259. if (!empty($attendee['NAME']) && $attendee['LAST_NAME'])
  260. {
  261. $attendees[] = $attendee['NAME'] . ' ' . $attendee['LAST_NAME'];
  262. }
  263. }
  264. return implode(", ", $attendees);
  265. }
  266. private function getOrganizerName(): string
  267. {
  268. return $this->attendees[$this->eventFields['MEETING_HOST']]['NAME']
  269. . ' ' . $this->attendees[$this->eventFields['MEETING_HOST']]['LAST_NAME']
  270. . (empty($this->attendees[$this->eventFields['MEETING_HOST']]['EMAIL'])
  271. ? '' :' (' . $this->attendees[$this->eventFields['MEETING_HOST']]['EMAIL'] .')');
  272. }
  273. private function getFilesLink()
  274. {
  275. $attaches = [];
  276. foreach ($this->eventFields['ATTACHES'] as $attach)
  277. {
  278. $attaches[] = '<a href="'.$attach['link'].'">'.$attach['name'].'</a><br />' ;
  279. }
  280. return implode(" ", $attaches);
  281. }
  282. private function getMessageId(): string
  283. {
  284. return "<CALENDAR_EVENT_".$this->eventFields['PARENT_ID']."@".$GLOBALS["SERVER_NAME"].">";
  285. }
  286. private function getMessageReplyTo(): string
  287. {
  288. return $this->getMessageId();
  289. }
  290. private function getReplyContent(): array
  291. {
  292. global $APPLICATION;
  293. $attachmentManager = new OutcomingAttachmentManager ($this->eventFields, $this->attendees, $this->method);
  294. $attachmentManager->prepareReplyAttachment();
  295. $fileContent = Encoding::convertEncoding($attachmentManager->getAttachment(), SITE_CHARSET, "utf-8");
  296. return [[
  297. 'CONTENT' => $fileContent,
  298. 'CONTENT_TYPE' => self::CONTENT_TYPE,
  299. 'METHOD' => Dictionary::METHODS[$this->method],
  300. 'CHARSET' => self::CHARSET,
  301. 'NAME' => self::ATTACHMENT_NAME,
  302. 'ID' => ICalUtil::getUniqId(),
  303. ]];
  304. }
  305. private function getReplyBodyMessage()
  306. {
  307. return 'reply body message';
  308. }
  309. private function getCancelContent(): array
  310. {
  311. global $APPLICATION;
  312. $attachmentManager = new OutcomingAttachmentManager ($this->eventFields, $this->attendees, $this->method);
  313. $attachmentManager->prepareCancelAttachment();
  314. $fileContent = Encoding::convertEncoding($attachmentManager->getAttachment(), SITE_CHARSET, "utf-8");
  315. return [[
  316. 'CONTENT' => $fileContent,
  317. 'CONTENT_TYPE' => self::CONTENT_TYPE,
  318. 'METHOD' => Dictionary::METHODS[$this->method],
  319. 'CHARSET' => self::CHARSET,
  320. 'NAME' => self::ATTACHMENT_NAME,
  321. 'ID' => ICalUtil::getUniqId(),
  322. ]];
  323. }
  324. private function getDateForTemplate()
  325. {
  326. $res = Util::getIcalTemplateDate([
  327. 'DATE_FROM' => $this->eventFields['DATE_FROM'],
  328. 'DATE_TO' => $this->eventFields['DATE_TO'],
  329. 'TZ_FROM' => $this->eventFields['TZ_FROM'],
  330. 'TZ_TO' => $this->eventFields['TZ_TO'],
  331. 'FULL_DAY' => $this->eventFields['SKIP_TIME'],
  332. ]);
  333. $offset = (Util::getDateObject(null, false, $this->eventFields['TZ_FROM']))->format('P');
  334. $res .= ' (' . $this->eventFields['TZ_FROM'] . ', ' . 'UTC' . $offset . ')';
  335. if (isset($this->eventFields['RRULE']['FREQ']) && $this->eventFields['RRULE']['FREQ'] !== 'NONE')
  336. {
  337. $rruleString = Util::getIcalTemplateRRule($this->eventFields['RRULE'],
  338. [
  339. 'DATE_FROM' => $this->eventFields['DATE_FROM'],
  340. 'DATE_TO' => $this->eventFields['DATE_TO'],
  341. 'TZ_FROM' => $this->eventFields['TZ_FROM'],
  342. 'TZ_TO' => $this->eventFields['TZ_TO'],
  343. 'FULL_DAY' => $this->eventFields['SKIP_TIME'],
  344. ]
  345. );
  346. $res .= ', (' . $rruleString . ')';
  347. }
  348. return $res;
  349. }
  350. private function getEditTitle()
  351. {
  352. if ($this->method !== 'edit')
  353. {
  354. return null;
  355. }
  356. if (count($this->changeFields) === 1)
  357. {
  358. switch ($this->changeFields[0]['fieldKey'])
  359. {
  360. case 'DATE_FROM':
  361. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_CHANGE_FIELD_TITLE_DATE');
  362. case 'LOCATION':
  363. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_CHANGE_FIELD_TITLE_LOCATION');
  364. case 'ATTENDEES':
  365. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_CHANGE_FIELD_TITLE_ATTENDEES');
  366. case 'RRULE':
  367. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_CHANGE_FIELD_TITLE_RRULE');
  368. case 'NAME':
  369. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_CHANGE_FIELD_TITLE_NAME');
  370. default:
  371. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_METHOD_EDIT');
  372. }
  373. }
  374. return Loc::getMessage('EC_CALENDAR_ICAL_MAIL_METHOD_EDIT');
  375. }
  376. private function getChangeFieldsString()
  377. {
  378. $res = [];
  379. if (!empty($this->changeFields))
  380. {
  381. foreach ($this->changeFields as $changeField)
  382. {
  383. $res[] = $changeField['fieldKey'];
  384. }
  385. }
  386. return implode(';', $res);
  387. }
  388. private function checkOrganizerEmail()
  389. {
  390. if (Loader::includeModule('mail'))
  391. {
  392. if (empty($this->sender['EMAIL']))
  393. {
  394. $boxes = \Bitrix\Mail\MailboxTable::getUserMailboxes($this->eventFields['MEETING_HOST']);
  395. $email = array_shift($boxes)['EMAIL'];
  396. $this->sender['EMAIL'] = $email;
  397. $this->attendees[$this->eventFields['MEETING_HOST']]['EMAIL'] = $email;
  398. }
  399. }
  400. }
  401. }