- Модуль: mail
- Путь к файлу: ~/bitrix/modules/mail/lib/helper/mailbox/imap.php
- Класс: BitrixMailHelperMailboxImap
- Вызов: Imap::getSyncRange
protected function getSyncRange($dirPath, &$uidtoken, $intervalSynchronizationAttempts = 0)
{
$meta = $this->client->select($dirPath, $error);
if (false === $meta)
{
$this->warnings->add($this->client->getErrors()->toArray());
return null;
}
if (!($meta['exists'] > 0))
{
return null;
}
$uidtoken = $meta['uidvalidity'];
/*
The interval may be smaller if the uid of the last message
in the database is close to the split point in the set of intervals
*/
$maximumLengthSynchronizationInterval = $this->getMaximumSynchronizationLengthsOfIntervals($intervalSynchronizationAttempts);
$rangeGetter = function ($min, $max) use ($dirPath, $uidtoken, &$rangeGetter, $maximumLengthSynchronizationInterval)
{
$size = $max - $min + 1;
$set = [];
$d = $size < 1000 ? $maximumLengthSynchronizationInterval : pow(10, round(ceil(log10($size) - 0.7) / 2) * 2 - 2);
//Take intermediate interval values
for ($i = $min; $i <= $max; $i = $i + $d)
{
$set[] = $i;
}
/*
The end of the expected interval should not exceed the identifier of the last message
*/
if (count($set) > 1 && end($set) >= $max)
{
array_pop($set);
}
//The last item in the set must match the last item on the service
$set[] = $max;
//Return messages starting from the 1st existing one
$set = $this->client->fetch(false, $dirPath, join(',', $set), '(UID)', $error);
if (empty($set))
{
return false;
}
ksort($set);
static $uidMinInDatabase, $uidMaxInDatabase, $takeFromDown;
if (!isset($uidMinInDatabase, $uidMaxInDatabase, $takeFromDown))
{
$messagesUidBoundariesIntervalInDatabase = $this->getUidRange($dirPath, $uidtoken);
if ($messagesUidBoundariesIntervalInDatabase)
{
$uidMinInDatabase = $messagesUidBoundariesIntervalInDatabase['MIN'];
$uidMaxInDatabase = $messagesUidBoundariesIntervalInDatabase['MAX'];
$takeFromDown = $messagesUidBoundariesIntervalInDatabase['TAKE_FROM_DOWN'];
}
else
{
$takeFromDown = true;
$uidMinInDatabase = $uidMaxInDatabase = (end($set)['UID'] + 1);
}
}
if (count($set) == 1)
{
$uid = reset($set)['UID'];
if ($uid > $uidMaxInDatabase || $uid < $uidMinInDatabase)
{
return array($uid, $uid);
}
}
elseif (end($set)['UID'] > $uidMaxInDatabase)
{
/*
Select the closest element with the largest uid
from the set of messages on the service (every hundredth)
to a message from the database (synchronized) with the maximum uid.
*/
do
{
$max = current($set)['id'];
$min = prev($set)['id'];
}
while (current($set)['UID'] > $uidMaxInDatabase && prev($set) && next($set));
if ($max - $min > $maximumLengthSynchronizationInterval)
{
return $rangeGetter($min, $max);
}
else
{
/*
Since we upload messages "up",
we know the upper ones and there is no point in "capturing" existing messages in the interval.
The selection is made within the interval, so the presence of extreme messages with the specified identifiers is not necessary.
+ 1 / - do not include an already uploaded message
*/
return array(
max($set[$min]['UID'], $uidMaxInDatabase + 1),
$set[$max]['UID'],
);
}
}
elseif (reset($set)['UID'] < $uidMinInDatabase && $takeFromDown)
{
do
{
$min = current($set)['id'];
$max = next($set)['id'];
}
while (current($set)['UID'] < $uidMinInDatabase && next($set) && prev($set));
if ($max - $min > $maximumLengthSynchronizationInterval)
{
return $rangeGetter($min, $max);
}
else
{
/*
Since we upload messages "down",
we know the upper ones and there is no point in "capturing" existing messages in the interval.
The selection is made within the interval, so the presence of extreme messages with the specified identifiers is not necessary.
- 1 / - do not include an already uploaded message
*/
return array(
min($set[$max]['UID'], $uidMinInDatabase - 1),
$set[$min]['UID'],
);
}
}
return null;
};
return $rangeGetter(1, $meta['exists']);
}