• Модуль: mail
  • Путь к файлу: ~/bitrix/modules/mail/lib/helper/mailbox/imap.php
  • Класс: BitrixMailHelperMailboxImap
  • Вызов: Imap::resyncDirInternal
protected function resyncDirInternal($dir, $numberForResync = false)
{
	$meta = $this->client->select($dir->getPath(), $error);
	if (false === $meta)
	{
		$this->warnings->add($this->client->getErrors()->toArray());

		return false;
	}

	$uidtoken = $meta['uidvalidity'];

	if ($meta['exists'] > 0)
	{
		if ($uidtoken > 0)
		{
			$result = $this->unregisterMessages(
				array(
					'=DIR_MD5'  => md5($dir->getPath(true)),
					' $uidtoken,
				),
				[
					'info' => 'the directory has been deleted',
				]
			);

			$countDeleted = $result ? $result->getCount() : 0;

			$this->lastSyncResult['deletedMessages'] += $countDeleted;
		}
	}
	else
	{
		if ($this->client->ensureEmpty($dir->getPath(), $error))
		{
			$result = $this->unregisterMessages(
				array(
					'=DIR_MD5' => md5($dir->getPath(true)),
				),
				[
					'info' => 'all messages in the directory have been deleted ',
				]
			);

			$countDeleted = $result ? $result->getCount() : 0;

			$this->lastSyncResult['deletedMessages'] += $countDeleted;
		}

		return;
	}

	$fetcher = function ($range) use ($dir)
	{
		$messages = $this->client->fetch(false, $dir->getPath(), $range, '(UID FLAGS)', $error);

		if (empty($messages))
		{
			if (false === $messages)
			{
				$this->warnings->add($this->client->getErrors()->toArray());
			}
			else
			{
				// @TODO: log
			}

			return false;
		}

		krsort($messages);

		return $messages;
	};

	$messagesNumberInTheMailService = $meta['exists'];
	$messages = $fetcher(($messagesNumberInTheMailService > 10000 || $numberForResync !== false) ? sprintf('1,%u', $messagesNumberInTheMailService) : '1:*');

	if (empty($messages))
	{
		return (false === $messages ? false : null);
	}

	//interval of messages in the directory
	$range = array(
		reset($messages)['UID'],
		end($messages)['UID'],
	);
	sort($range);

	if($range[0]===$range[1] and $messagesNumberInTheMailService > 1)
	{
		return false;
	}

	//deleting non-existent messages in the service ( not included in the message interval on the service )
	$result = $this->unregisterMessages(
		array(
			'=DIR_MD5' => md5($dir->getPath(true)),
			'>MSG_UID' => 0,
			array(
				'LOGIC'    => 'OR',
				' $range[0],
				'>MSG_UID' => $range[1],
			),
		),
		[
			'info' => 'optimized deletion of non-existent messages',
		]
	);

	$countDeleted = $result ? $result->getCount() : 0;

	$this->lastSyncResult['deletedMessages'] += $countDeleted;

	//resynchronizing a certain number of messages
	if($numberForResync !== false)
	{
		$range1 = $meta['exists'];
		$range0 = max($range1 - ($numberForResync - 1), 1);
		$messages = $fetcher(sprintf('%u:%u', $range0, $range1));

		if (empty($messages))
		{
			return;
		}

		$this->resyncMessages($dir->getPath(true), $uidtoken, $messages);

		return;
	}

	if (!($meta['exists'] > 10000))
	{
		$this->resyncMessages($dir->getPath(true), $uidtoken, $messages);

		return;
	}

	$range1 = $meta['exists'];
	while ($range1 > 0)
	{
		$rangeSize = $range1 > 10000 ? 8000 : $range1;
		$range0 = max($range1 - $rangeSize, 1);

		$messages = $fetcher(sprintf('%u:%u', $range0, $range1));

		if (empty($messages))
		{
			return;
		}

		$this->resyncMessages($dir->getPath(true), $uidtoken, $messages);

		if ($this->isTimeQuotaExceeded())
		{
			return;
		}

		$range1 -= $rangeSize;
	}
}