static function decode($text, $limit = 0)
{
$result = Array();
if ($text == '')
{
return $result;
}
$metrics = Array();
$date = new BitrixMainTypeDateTime();
if ($limit > 0 && mb_strlen($text) > $limit)
{
$text = mb_substr($text, 0, $limit);
}
$originalText = $text;
$text = mb_strtolower($text);
$workTimeStart = explode('.', BitrixMainConfigOption::get('calendar', 'work_time_start', '9'));
$timeOfStartDate = str_pad(intval($workTimeStart[0] ?? 0), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeStart[1] ?? 0), 2, "0", STR_PAD_LEFT);
$workTimeEnd = explode('.', BitrixMainConfigOption::get('calendar', 'work_time_end', '18'));
$timeOfEndDate = str_pad(intval($workTimeEnd[0] ?? 0), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeEnd[1] ?? 0), 2, "0", STR_PAD_LEFT);
$defaultPregExceptionSearch = Array('.', '/', '-', ':');
$defaultPregExceptionReplace = Array('.', '/', '-', ':');
// metric 1: near date
$pattern = Array();
for ($i = 1; $i <= 11; $i++)
{
$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_1_".$i));
$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
}
if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
{
foreach ($match[0] as $matchPattern)
{
$matchType = '';
switch($matchPattern[0])
{
case $pattern[1]:
$matchType = 'DAYAFTERTOMORROW';
break;
case $pattern[2]:
$matchType = 'TOMORROW';
break;
case $pattern[3]:
$matchType = 'TODAY';
break;
case $pattern[4]:
$matchType = 'YESTERDAY';
break;
case $pattern[5]:
$matchType = 'DAYBEFOREYESTERDAY';
break;
case $pattern[9]:
$matchType = 'WEEK';
break;
case $pattern[10]:
$matchType = 'WEEKEND';
break;
case $pattern[11]:
$matchType = 'MONTH';
break;
}
if ($matchType <> '')
{
$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
$matchWord = self::getMatchWord($originalText, $position);
$metrics[1][] = Array(
'TYPE' => $matchType,
'COUNT' => mb_strlen($matchWord),
'POSITION' => $position,
'MATCH' => $matchWord
);
}
}
}
// metric 2: day of weeks
$pattern = Array();
for ($i = 1; $i <= 10; $i++)
{
$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_2_".$i));
$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
}
if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
{
foreach ($match[0] as $matchPattern)
{
$matchType = '';
switch($matchPattern[0])
{
case $pattern[1]:
$matchType = 'MONDAY';
if (is_array($metrics[1]))
{
foreach ($metrics[1] as $key => $metric)
{
if ($metric['TYPE'] == 'WEEK')
{
$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
$matchWord = self::getMatchWord($originalText, $position);
if ($matchPattern[1] < $metric['POSITION'] && $matchPattern[1] + mb_strlen($matchWord) >= $metric['POSITION'] + $metric['COUNT'])
{
unset($metrics[1][$key]);
if (empty($metrics[1]))
{
unset($metrics[1]);
}
}
}
}
}
break;
case $pattern[2]:
$matchType = 'TUESDAY';
break;
case $pattern[3]:
case $pattern[4]:
case $pattern[5]:
$matchType = 'WEDNESDAY';
break;
case $pattern[6]:
$matchType = 'THURSDAY';
break;
case $pattern[7]:
$matchType = 'FRIDAY';
break;
case $pattern[8]:
$matchType = 'SATURDAY';
break;
case $pattern[9]:
case $pattern[10]:
$matchType = 'SUNDAY';
break;
}
if ($matchType <> '')
{
$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
$matchWord = self::getMatchWord($originalText, $position);
$metrics[2][] = Array(
'TYPE' => $matchType,
'COUNT' => mb_strlen($matchWord),
'POSITION' => $position,
'MATCH' => $matchWord
);
}
}
}
// metric 3: modificators before/after and time
$pattern = Array();
for ($i = 1; $i <= 9; $i++)
{
$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_3_".$i));
$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
}
if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
{
foreach ($match[0] as $matchPattern)
{
$matchType = '';
switch($matchPattern[0])
{
case $pattern[1]:
$matchType = 'BEFORE';
break;
case $pattern[2]:
$matchType = 'AFTER';
break;
case $pattern[3]:
$matchType = 'NEXT';
break;
case $pattern[4]:
$matchType = 'PREVIOUS';
break;
case $pattern[5]:
case $pattern[6]:
$matchType = 'ENDOF';
break;
case $pattern[7]:
$matchType = 'MIDDLEOF';
break;
case $pattern[8]:
$matchType = 'STARTOF';
break;
case $pattern[9]:
case $pattern[10]:
$matchType = 'THIS';
break;
}
if (in_array($matchType, Array('BEFORE', 'AFTER')) && isset($metrics[1]))
{
foreach ($metrics[1] as $key => $metric)
{
if (in_array($metric['TYPE'], Array('DAYAFTERTOMORROW', 'DAYBEFOREYESTERDAY')))
{
if ($metric['POSITION'] == $matchPattern[1])
{
$matchType = '';
}
}
else if (in_array($metric['TYPE'], Array('TOMORROW', 'YESTERDAY')))
{
if ($metric['POSITION'] == $matchPattern[1] + mb_strlen($matchPattern[0])+1)
{
if ($metric['TYPE'] == 'TOMORROW')
{
$metrics[1][$key]['TYPE'] = $matchType == 'AFTER'? 'DAYAFTERTOMORROW': 'TODAY';
}
else
{
$metrics[1][$key]['TYPE'] = $matchType == 'AFTER'? 'TODAY': 'DAYBEFOREYESTERDAY';
}
$matchType = '';
}
}
}
}
if ($matchType <> '')
{
$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
$matchWord = self::getMatchWord($originalText, $position);
$metrics[3][] = Array(
'TYPE' => $matchType,
'COUNT' => mb_strlen($matchWord),
'POSITION' => $position,
'MATCH' => $matchWord
);
}
}
}
if (preg_match_all("/([0-2][0-9]:[0-5][0-9])/", $text, $match, PREG_OFFSET_CAPTURE))
{
foreach ($match[0] as $matchPattern)
{
$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
$matchWord = self::getMatchWord($originalText, $position);
$metrics[3][] = Array(
'TYPE' => 'HHMM',
'VALUE' => $matchPattern[0],
'COUNT' => mb_strlen($matchPattern[0]),
'POSITION' => $position,
'MATCH' => $matchWord
);
}
}
// metric 4: date
$pattern = Array();
$patternOriginal = Array();
$patternLength = Array();
for ($i = 1; $i <= 3; $i++)
{
$patternOriginal[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_4_".$i));
$patternOriginal[$i] = $patternOriginal[$i] <> ''? $patternOriginal[$i]: 'bxt2dmetricskip';
$patternLength[$i] = mb_strlen($patternOriginal[$i]);
if ($patternOriginal[$i] != 'bxt2dmetricskip')
{
$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $patternOriginal[$i]);
$pattern[$i] = str_replace(
Array('yyyy', 'yy', 'mm', 'dd'),
Array('[1-2][0-9][0-9][0-9]', '[0-9][0-9]', '[0-1][0-9]', '[0-3][0-9]'),
$pattern[$i]
);
$pattern[$i] = '^(?>[s|t]?)('.$pattern[$i].')|[s|^|t]('.$pattern[$i].')(?=[s|$|r|t])';
}
}
if (preg_match_all("/".implode('|', $pattern)."/", $text, $match, PREG_OFFSET_CAPTURE))
{
$count = count($match)-1;
for ($i = 1; $i <= $count; $i++)
{
foreach ($match[$i] as $matchPattern)
{
if (!$matchPattern[0])
{
continue;
}
$matchType = '';
$matchLength = '';
switch(mb_strlen($matchPattern[0]))
{
case $patternLength[1]:
$matchType = 'DDMMYYYY';
$matchYear = mb_substr($matchPattern[0], mb_strpos($patternOriginal[1], 'yyyy'), 4);
$matchMonth = mb_substr($matchPattern[0], mb_strpos($patternOriginal[1], 'mm'), 2);
$matchDay = mb_substr($matchPattern[0], mb_strpos($patternOriginal[1], 'dd'), 2);
$matchPattern[0] = $matchYear.'-'.$matchMonth.'-'.$matchDay;
$matchLength = $patternLength[1];
break;
case $patternLength[2]:
$matchType = 'DDMMYY';
$matchYear = mb_substr($matchPattern[0], mb_strpos($patternOriginal[2], 'yy'), 2);
$matchMonth = mb_substr($matchPattern[0], mb_strpos($patternOriginal[2], 'mm'), 2);
$matchDay = mb_substr($matchPattern[0], mb_strpos($patternOriginal[2], 'dd'), 2);
$matchPattern[0] = '20'.$matchYear.'-'.$matchMonth.'-'.$matchDay;
$matchLength = $patternLength[2];
break;
case $patternLength[3]:
$matchType = 'DDMM';
$matchMonth = mb_substr($matchPattern[0], mb_strpos($patternOriginal[3], 'mm'), 2);
$matchDay = mb_substr($matchPattern[0], mb_strpos($patternOriginal[3], 'dd'), 2);
$matchPattern[0] = $date->format('Y').'-'.$matchMonth.'-'.$matchDay;
$matchLength = $patternLength[3];
break;
}
$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
$matchWord = mb_substr($originalText, $position, $matchLength);
$metrics[4][] = Array(
'TYPE' => $matchType,
'VALUE' => $matchPattern[0],
'COUNT' => $matchLength,
'POSITION' => $position,
'MATCH' => $matchWord
);
}
}
}
// metric 5: modificators of time
$pattern = Array();
for ($i = 1; $i <= 5; $i++)
{
$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_5_".$i));
$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
}
if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
{
foreach ($match[0] as $matchPattern)
{
$matchType = '';
$matchValue = '';
switch($matchPattern[0])
{
case $pattern[1]:
$matchType = 'MORNING';
$matchValue = $timeOfStartDate;
break;
case $pattern[2]:
$matchType = 'LUNCH';
$matchValue = '14:00';
break;
case $pattern[3]:
break;
case $pattern[4]:
$matchType = 'WORKDAY';
$matchValue = $timeOfEndDate;
if (isset($metrics[1]))
{
foreach ($metrics[1] as $key => $metric)
{
if ($metric['TYPE'] == 'TODAY')
{
if ($metric['POSITION'] == $matchPattern[1] + mb_strlen($matchPattern[3]))
{
$matchType = '';
}
}
}
}
break;
case $pattern[5]:
$matchType = 'EVENING';
$matchValue = '20:00';
break;
}
if ($matchType <> '')
{
$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
$matchWord = self::getMatchWord($originalText, $position);
$metrics[5][] = Array(
'TYPE' => $matchType,
'VALUE' => $matchValue,
'COUNT' => mb_strlen($matchWord),
'POSITION' => $position,
'MATCH' => $matchWord
);
}
}
}
$countOfMetrics = 0;
foreach ($metrics as $values)
{
if (!empty($values))
{
$countOfMetrics++;
}
}
$useDefault = false;
if ($countOfMetrics == 1 && (isset($metrics[3]) || isset($metrics[5])))
{}
else if ($countOfMetrics == 1)
{
$useDefault = true;
}
else if ($countOfMetrics == 2 && isset($metrics[3]))
{
$useDefault = !isset($metrics[5]);
}
else if ($countOfMetrics == 2 && isset($metrics[5]) && (isset($metrics[1]) || isset($metrics[2]) || isset($metrics[4])))
{
if (isset($metrics[1]))
{
foreach ($metrics[1] as $metric)
{
$progressDate = self::createDateUsingMetrics(1, $metric, $metrics[5]);
$matchParams = self::getTextForReplace($originalText, $metric, $metrics[5]);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_RELATIVE, $metric, $metrics[5]);
}
}
else if (isset($metrics[2]))
{
foreach ($metrics[2] as $metric)
{
$progressDate = self::createDateUsingMetrics(2, $metric, $metrics[5]);
$matchParams = self::getTextForReplace($originalText, $metric, $metrics[5]);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_DAYOFWEEK, $metric, $metrics[5]);
}
}
else if (isset($metrics[4]))
{
foreach ($metrics[4] as $metric)
{
$progressDate = self::createDateUsingMetrics(4, $metric, $metrics[5]);
$matchParams = self::getTextForReplace($originalText, $metric, $metrics[5]);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_CALENDAR, $metric, $metrics[5]);
}
}
}
else if ($countOfMetrics == 2 && isset($metrics[1]) && (isset($metrics[2]) || isset($metrics[4])))
{
if (isset($metrics[2]))
{
foreach ($metrics[2] as $metric)
{
$array = array();
$progressDate = self::createDateUsingMetrics(2, $metric, $array);
$matchParams = self::getTextForReplace($originalText, $metric, array());
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_DAYOFWEEK, $metric);
}
}
elseif (isset($metrics[4]))
{
foreach ($metrics[4] as $metric)
{
$array = array();
$progressDate = self::createDateUsingMetrics(4, $metric, $array);
$matchParams = self::getTextForReplace($originalText, $metric, array());
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_CALENDAR, $metric);
}
}
}
else
{
$useDefault = true;
}
if ($useDefault)
{
$modificators = $metrics[3] ?? array();
if (isset($metrics[4]) && count($metrics[4]))
{
foreach ($metrics[4] as $metric)
{
$progressDate = self::createDateUsingMetrics(4, $metric, $modificators);
$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_CALENDAR, $metric, $modificators);
}
}
else if (isset($metrics[2]) && count($metrics[2]))
{
foreach ($metrics[2] as $metric)
{
$progressDate = self::createDateUsingMetrics(2, $metric, $modificators);
$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_DAYOFWEEK, $metric, $modificators);
}
}
else if (isset($metrics[1]) && count($metrics[1]))
{
foreach ($metrics[1] as $metric)
{
$progressDate = self::createDateUsingMetrics(1, $metric, $modificators);
$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_RELATIVE, $metric, $modificators);
}
}
else if (isset($metrics[5]) && count($metrics[5]))
{
foreach ($metrics[5] as $metric)
{
$progressDate = self::createDateUsingMetrics(5, $metric, $modificators);
$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_PARTOFDAY, $metric, $modificators);
}
}
else if (isset($metrics[3]) && count($metrics[3]))
{
foreach ($metrics[3] as $metric)
{
$array = array();
$progressDate = self::createDateUsingMetrics(3, $metric, $array);
$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_MODIFIER, $metric);
}
}
}
return $result;
}