PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/mail/lib/mailmessageuid.php

https://gitlab.com/alexprowars/bitrix
PHP | 391 lines | 281 code | 43 blank | 67 comment | 11 complexity | a33d3d4579a6d881bc6134b9a9e901c8 MD5 | raw file
  1. <?php
  2. namespace Bitrix\Mail;
  3. use Bitrix\Mail\Helper\MessageEventManager;
  4. use Bitrix\Mail\Internals\MessageUploadQueueTable;
  5. use Bitrix\Main\Entity;
  6. use Bitrix\Main\EventManager;
  7. use Bitrix\Main\Localization;
  8. Localization\Loc::loadMessages(__FILE__);
  9. /**
  10. * Class MailMessageUidTable
  11. *
  12. * DO NOT WRITE ANYTHING BELOW THIS
  13. *
  14. * <<< ORMENTITYANNOTATION
  15. * @method static EO_MailMessageUid_Query query()
  16. * @method static EO_MailMessageUid_Result getByPrimary($primary, array $parameters = array())
  17. * @method static EO_MailMessageUid_Result getById($id)
  18. * @method static EO_MailMessageUid_Result getList(array $parameters = array())
  19. * @method static EO_MailMessageUid_Entity getEntity()
  20. * @method static \Bitrix\Mail\EO_MailMessageUid createObject($setDefaultValues = true)
  21. * @method static \Bitrix\Mail\EO_MailMessageUid_Collection createCollection()
  22. * @method static \Bitrix\Mail\EO_MailMessageUid wakeUpObject($row)
  23. * @method static \Bitrix\Mail\EO_MailMessageUid_Collection wakeUpCollection($rows)
  24. */
  25. class MailMessageUidTable extends Entity\DataManager
  26. {
  27. public static function getFilePath()
  28. {
  29. return __FILE__;
  30. }
  31. public static function getTableName()
  32. {
  33. return 'b_mail_message_uid';
  34. }
  35. /**
  36. * @param array $filter
  37. * @param array $fields
  38. * @param array $eventData - optional, for compatibility reasons, should have the following structure:
  39. * [ ['HEADER_MD5' => .., 'MESSAGE_ID' => .., 'MAILBOX_USER_ID' => ..], [..]]
  40. * @return \Bitrix\Main\DB\Result
  41. * @throws \Bitrix\Main\ArgumentException
  42. * @throws \Bitrix\Main\Db\SqlQueryException
  43. * @throws \Bitrix\Main\ObjectException
  44. * @throws \Bitrix\Main\ObjectPropertyException
  45. * @throws \Bitrix\Main\SystemException
  46. */
  47. public static function updateList(array $filter, array $fields, array $eventData = [])
  48. {
  49. $entity = static::getEntity();
  50. $connection = $entity->getConnection();
  51. $result = $connection->query(sprintf(
  52. "UPDATE %s SET %s WHERE %s",
  53. $connection->getSqlHelper()->quote($entity->getDbTableName()),
  54. $connection->getSqlHelper()->prepareUpdate($entity->getDbTableName(), $fields)[0],
  55. Entity\Query::buildFilterSql($entity, $filter)
  56. ));
  57. $eventManager = EventManager::getInstance();
  58. $eventKey = $eventManager->addEventHandler(
  59. 'mail',
  60. 'onMailMessageModified',
  61. array(MessageEventManager::class, 'onMailMessageModified')
  62. );
  63. $event = new \Bitrix\Main\Event('mail', 'onMailMessageModified', array(
  64. 'MAIL_FIELDS_DATA' => $eventData,
  65. 'UPDATED_FIELDS_VALUES' => $fields,
  66. 'UPDATED_BY_FILTER' => $filter,
  67. ));
  68. $event->send();
  69. EventManager::getInstance()->removeEventHandler('mail', 'onMailMessageModified', $eventKey);
  70. return $result;
  71. }
  72. /**
  73. * @param array $filter
  74. * @param array $messages
  75. * @param int|false $limit
  76. * @return bool
  77. * @throws \Bitrix\Main\ArgumentException
  78. * @throws \Bitrix\Main\Db\SqlQueryException
  79. * @throws \Bitrix\Main\ObjectPropertyException
  80. * @throws \Bitrix\Main\SystemException
  81. */
  82. public static function deleteList(array $filter, array $messages = [], $limit = false): bool
  83. {
  84. $eventName = MessageEventManager::EVENT_DELETE_MESSAGES;
  85. $messages = static::selectMessagesToBeDeleted(
  86. MessageEventManager::getRequiredFieldNamesForEvent($eventName),
  87. $filter,
  88. $messages,
  89. $limit
  90. );
  91. if (empty($messages))
  92. {
  93. return false;
  94. }
  95. $entity = static::getEntity();
  96. $connection = $entity->getConnection();
  97. $portionLimit = 200;
  98. for ($i = 0; $i < count($messages); $i=$i+$portionLimit)
  99. {
  100. $portion = array_slice($messages, $i, $portionLimit);
  101. $query = sprintf(
  102. ' FROM %s WHERE ID IN (\'' . join("','", array_column($portion, 'ID')) . '\')',
  103. $connection->getSqlHelper()->quote($entity->getDbTableName()),
  104. );
  105. $connection->query(sprintf(
  106. 'INSERT IGNORE INTO %s (ID, MAILBOX_ID, MESSAGE_ID) (SELECT ID, MAILBOX_ID, MESSAGE_ID %s)',
  107. $connection->getSqlHelper()->quote(Internals\MessageDeleteQueueTable::getTableName()),
  108. $query
  109. ));
  110. $connection->query(sprintf('DELETE %s', $query));
  111. }
  112. if ($messagesIds = array_column($messages, 'MESSAGE_ID'))
  113. {
  114. $remains = array_column(
  115. static::getList(array(
  116. 'select' => array('MESSAGE_ID'),
  117. 'filter' => array(
  118. '@MESSAGE_ID' => $messagesIds,
  119. ),
  120. ))->fetchAll(),
  121. 'MESSAGE_ID'
  122. );
  123. //checking that the values were actually deleted:
  124. $messages = array_filter(
  125. $messages,
  126. function ($item) use ($remains)
  127. {
  128. return !in_array($item['MESSAGE_ID'], $remains);
  129. }
  130. );
  131. }
  132. $eventManager = EventManager::getInstance();
  133. $eventKey = $eventManager->addEventHandler(
  134. 'mail',
  135. 'onMailMessageDeleted',
  136. array(MessageEventManager::class, 'onMailMessageDeleted')
  137. );
  138. $event = new \Bitrix\Main\Event('mail', 'onMailMessageDeleted', array(
  139. 'MAIL_FIELDS_DATA' => $messages,
  140. 'DELETED_BY_FILTER' => $filter,
  141. ));
  142. $event->send();
  143. EventManager::getInstance()->removeEventHandler('mail', 'onMailMessageDeleted', $eventKey);
  144. return true;
  145. }
  146. public static function getPresetRemoveFilters()
  147. {
  148. return [
  149. '==DELETE_TIME' => 0,
  150. ];
  151. }
  152. /**
  153. * @param array $filter
  154. * @return \Bitrix\Main\DB\Result
  155. * @throws \Bitrix\Main\ArgumentException
  156. * @throws \Bitrix\Main\Db\SqlQueryException
  157. * @throws \Bitrix\Main\SystemException
  158. */
  159. public static function deleteListSoft(array $filter)
  160. {
  161. $entity = static::getEntity();
  162. $connection = $entity->getConnection();
  163. $filter = array_merge($filter , static::getPresetRemoveFilters());
  164. //mark selected messages for deletion if there are no messages in the download queue
  165. $query = sprintf(
  166. 'UPDATE %s SET %s WHERE %s AND NOT EXISTS (SELECT 1 FROM %s WHERE %s)',
  167. $connection->getSqlHelper()->quote($entity->getDbTableName()),
  168. $connection->getSqlHelper()->prepareUpdate($entity->getDbTableName(), [
  169. 'DELETE_TIME' => time(),
  170. ])[0],
  171. Entity\Query::buildFilterSql(
  172. $entity,
  173. $filter
  174. ),
  175. $connection->getSqlHelper()->quote(Internals\MessageUploadQueueTable::getTableName()),
  176. Entity\Query::buildFilterSql(
  177. $entity,
  178. [
  179. '=ID' => new \Bitrix\Main\DB\SqlExpression('?#', 'ID'),
  180. '=MAILBOX_ID' => new \Bitrix\Main\DB\SqlExpression('?#', 'MAILBOX_ID'),
  181. ]
  182. )
  183. );
  184. $result = $connection->query($query);
  185. $count = $connection->getAffectedRowsCount();
  186. $result->setCount($count > 0 ? $count : 0);
  187. return $result;
  188. }
  189. /**@
  190. * @param $fields
  191. * @param $filter
  192. * @param array $eventData
  193. * @param int|false $limit
  194. * @return array
  195. * @throws \Bitrix\Main\ArgumentException
  196. * @throws \Bitrix\Main\ObjectPropertyException
  197. * @throws \Bitrix\Main\SystemException
  198. */
  199. private static function selectMessagesToBeDeleted($fields, $filter, array $eventData, $limit = false): array
  200. {
  201. $result = array();
  202. $primary = array('ID', 'MAILBOX_ID');
  203. $eventData = array_values($eventData);
  204. if (empty($eventData))
  205. {
  206. $select = $fields;
  207. }
  208. else
  209. {
  210. $select = array_diff($fields, array_intersect($fields, ...array_map('array_keys', $eventData)));
  211. if (empty($select))
  212. {
  213. return $eventData;
  214. }
  215. if (array_diff($primary, array_intersect($primary, ...array_map('array_keys', $eventData))))
  216. {
  217. $select = $fields;
  218. }
  219. else
  220. {
  221. foreach ($eventData as $item)
  222. {
  223. $key = sprintf('%u:%s', $item['MAILBOX_ID'], $item['ID']);
  224. $result[$key] = $item;
  225. }
  226. }
  227. }
  228. $select = array_unique(array_merge($primary, $select));
  229. $mailsFilter = $filter;
  230. $mailsFilter['==IS_IN_QUEUE'] = false;
  231. $queueSubquery = MessageUploadQueueTable::query();
  232. $queueSubquery->addFilter('=ID', new \Bitrix\Main\DB\SqlExpression('%s'));
  233. $queueSubquery->addFilter('=MAILBOX_ID', new \Bitrix\Main\DB\SqlExpression('%s'));
  234. $emailsForDeleteQuery = MailMessageUidTable::query()
  235. ->registerRuntimeField(new Entity\ExpressionField(
  236. 'IS_IN_QUEUE',
  237. sprintf('EXISTS(%s)', $queueSubquery->getQuery()),
  238. ['ID', 'MAILBOX_ID']
  239. ))
  240. ->setFilter($mailsFilter);
  241. if($limit !== false)
  242. {
  243. $emailsForDeleteQuery->setLimit($limit);
  244. }
  245. foreach ($select as $index => $selectingField)
  246. {
  247. if (strncmp('MAILBOX_', $selectingField, 8) === 0 && !MailMessageUidTable::getEntity()->hasField($selectingField))
  248. {
  249. $emailsForDeleteQuery->addSelect('MAILBOX.'.mb_substr($selectingField, 8), $selectingField);
  250. continue;
  251. }
  252. $emailsForDeleteQuery->addSelect($selectingField);
  253. }
  254. $res = $emailsForDeleteQuery->exec();
  255. while ($item = $res->fetch())
  256. {
  257. $key = sprintf('%u:%s', $item['MAILBOX_ID'], $item['ID']);
  258. $result[$key] = array_merge((array) $result[$key], $item);
  259. }
  260. return array_values($result);
  261. }
  262. /**
  263. * Merge data. Insert-update.
  264. *
  265. * @param array $insert Insert fields.
  266. * @param array $update Update fields.
  267. * @return void
  268. * @throws \Bitrix\Main\ArgumentException
  269. * @throws \Bitrix\Main\Db\SqlQueryException
  270. * @throws \Bitrix\Main\SystemException
  271. */
  272. public static function mergeData(array $insert, array $update)
  273. {
  274. $entity = static::getEntity();
  275. $connection = $entity->getConnection();
  276. $helper = $connection->getSqlHelper();
  277. $sql = $helper->prepareMerge($entity->getDBTableName(), $entity->getPrimaryArray(), $insert, $update);
  278. $sql = current($sql);
  279. if($sql <> '')
  280. {
  281. $connection->queryExecute($sql);
  282. $entity->cleanCache();
  283. }
  284. }
  285. public static function getMap()
  286. {
  287. return array(
  288. 'ID' => array(
  289. 'data_type' => 'string',
  290. 'primary' => true,
  291. ),
  292. 'MAILBOX_ID' => array(
  293. 'data_type' => 'integer',
  294. 'primary' => true,
  295. ),
  296. 'DIR_MD5' => array(
  297. 'data_type' => 'string',
  298. ),
  299. 'DIR_UIDV' => array(
  300. 'data_type' => 'integer',
  301. ),
  302. 'MSG_UID' => array(
  303. 'data_type' => 'integer',
  304. ),
  305. 'INTERNALDATE' => array(
  306. 'data_type' => 'datetime',
  307. ),
  308. 'HEADER_MD5' => array(
  309. 'data_type' => 'string',
  310. ),
  311. 'IS_SEEN' => array(
  312. 'data_type' => 'enum',
  313. 'values' => array('Y', 'N', 'S', 'U'),
  314. ),
  315. 'IS_OLD' => array(
  316. 'data_type' => 'enum',
  317. 'values' => array('Y', 'N', 'D'),
  318. ),
  319. 'SESSION_ID' => array(
  320. 'data_type' => 'string',
  321. 'required' => true,
  322. ),
  323. 'TIMESTAMP_X' => array(
  324. 'data_type' => 'datetime',
  325. ),
  326. 'DATE_INSERT' => array(
  327. 'data_type' => 'datetime',
  328. 'required' => true,
  329. ),
  330. 'MESSAGE_ID' => array(
  331. 'data_type' => 'integer',
  332. 'required' => true,
  333. ),
  334. 'MAILBOX' => array(
  335. 'data_type' => 'Bitrix\Mail\Mailbox',
  336. 'reference' => array('=this.MAILBOX_ID' => 'ref.ID'),
  337. ),
  338. 'MESSAGE' => array(
  339. 'data_type' => 'Bitrix\Mail\MailMessage',
  340. 'reference' => array('=this.MESSAGE_ID' => 'ref.ID'),
  341. ),
  342. 'DELETE_TIME' => array(
  343. 'data_type' => 'integer',
  344. 'default' => 0,
  345. ),
  346. );
  347. }
  348. }