/modules/main/lib/text/dateconverter.php
PHP | 1114 lines | 1001 code | 76 blank | 37 comment | 251 complexity | 4870576334a1608fd5e2ab095bc17416 MD5 | raw file
- <?php
- namespace Bitrix\Main\Text;
- use Bitrix\Main\Localization\Loc as Loc;
- class DateConverter
- {
- /**
- * Creates Date object from Text (return array of result object)
- *
- * Examples: "end of next week", "tomorrow morning", "friday 25.10"
- *
- * @param string $text
- * @param integer $limit
- * @return \Bitrix\Main\Text\DateConverterResult[]
- */
- public static function decode($text, $limit = 0)
- {
- $result = Array();
- if ($text == '')
- {
- return $result;
- }
- $metrics = Array();
- $date = new \Bitrix\Main\Type\DateTime();
- if ($limit > 0 && mb_strlen($text) > $limit)
- {
- $text = mb_substr($text, 0, $limit);
- }
- $originalText = $text;
- $text = mb_strtolower($text);
- $workTimeStart = explode('.', \Bitrix\Main\Config\Option::get('calendar', 'work_time_start', '9'));
- $timeOfStartDate = str_pad(intval($workTimeStart[0]), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeStart[1]), 2, "0", STR_PAD_LEFT);
- $workTimeEnd = explode('.', \Bitrix\Main\Config\Option::get('calendar', 'work_time_end', '18'));
- $timeOfEndDate = str_pad(intval($workTimeEnd[0]), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeEnd[1]), 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[6]:
- case $pattern[7]:
- case $pattern[8]:
- $matchType = '';
- 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 (count($metrics[1]) == 0)
- {
- 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 (count($values) > 0)
- {
- $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 = isset($metrics[3])? $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;
- }
- /**
- * Creates Date object from metrics (private method for self::decode)
- *
- * @param int $type Type of metric
- * @param array $metric Params of metric
- * @param array $metricModificator List of metric modificators
- * @param \Bitrix\Main\Type\DateTime $date If not specified, the modified date is got from the current date.
- * @return \Bitrix\Main\Type\DateTime
- *
- */
- private static function createDateUsingMetrics($type, $metric, &$metricModificator = array(), \Bitrix\Main\Type\DateTime $date = null)
- {
- $defaultDate = $date? $date: new \Bitrix\Main\Type\DateTime();
- $metricModificator = is_array($metricModificator)? $metricModificator: array();
- $workTimeStart = explode('.', \Bitrix\Main\Config\Option::get('calendar', 'work_time_start', '9'));
- $timeOfStartDate = str_pad(intval($workTimeStart[0]), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeStart[1]), 2, "0", STR_PAD_LEFT);
- $workTimeEnd = explode('.', \Bitrix\Main\Config\Option::get('calendar', 'work_time_end', '18'));
- $timeOfEndDate = str_pad(intval($workTimeEnd[0]), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeEnd[1]), 2, "0", STR_PAD_LEFT);
- $result = null;
- switch($type)
- {
- case 1:
- $metricDate = $defaultDate;
- switch($metric['TYPE'])
- {
- case 'DAYAFTERTOMORROW':
- $metricDate->add('TOMORROW')->add('TOMORROW');
- break;
- case 'TOMORROW':
- $metricDate->add('TOMORROW');
- break;
- case 'YESTERDAY':
- $metricDate->add('YESTERDAY');
- break;
- case 'DAYBEFOREYESTERDAY':
- $metricDate->add('YESTERDAY')->add('YESTERDAY');
- break;
- }
- $modificator = '';
- $metricTime = $timeOfEndDate;
- $metricModificator = self::checkModifierPosition($metric, $metricModificator);
- foreach ($metricModificator as $currentModificator)
- {
- if ($metric['TYPE'] == 'WEEK')
- {
- if (in_array($currentModificator['TYPE'], Array('BEFORE', 'PREVIOUS')))
- {
- $metricDate->add('-1 WEEK');
- }
- else if (in_array($currentModificator['TYPE'], Array('AFTER', 'NEXT')))
- {
- $metricDate->add('1 WEEK');
- }
- else if ($currentModificator['TYPE'] == 'MIDDLEOF')
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('WEDNESDAY', $metricDate);
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'STARTOF')
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('MONDAY', $metricDate);
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'ENDOF')
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('FRIDAY', $metricDate);
- $modificator = true;
- }
- }
- else if ($metric['TYPE'] == 'WEEKEND')
- {
- if (in_array($currentModificator['TYPE'], Array('BEFORE')))
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('SATURDAY', $metricDate);
- $metricDate->add('-1 DAY');
- $modificator = true;
- }
- else if (in_array($currentModificator['TYPE'], Array('PREVIOUS')))
- {
- $metricDate->add('-1 WEEK');
- $metricDate = self::getDateOfDayOfCurrentWeek('SATURDAY', $metricDate);
- $modificator = true;
- }
- else if (in_array($currentModificator['TYPE'], Array('NEXT')))
- {
- $metricDate->add('1 WEEK');
- $metricDate = self::getDateOfDayOfCurrentWeek('SATURDAY', $metricDate);
- $modificator = true;
- }
- else if (in_array($currentModificator['TYPE'], Array('AFTER')))
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('SUNDAY', $metricDate);
- $metricDate->add('1 DAY');
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'MIDDLEOF')
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('SATURDAY', $metricDate);
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'STARTOF')
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('SATURDAY', $metricDate);
- $metricTime = $timeOfStartDate;
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'ENDOF')
- {
- $metricDate = self::getDateOfDayOfCurrentWeek('SUNDAY', $metricDate);
- $modificator = true;
- }
- }
- else if ($metric['TYPE'] == 'MONTH')
- {
- if (in_array($currentModificator['TYPE'], Array('BEFORE', 'PREVIOUS')))
- {
- $metricDate->add('-1 MONTH');
- $numberOfMonth = $metricDate->format('t');
- $metricDate = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m').'-'.$numberOfMonth.' '.$timeOfEndDate.':00', 'Y-m-d H:i:s');
- $modificator = true;
- }
- else if (in_array($currentModificator['TYPE'], Array('AFTER', 'NEXT')))
- {
- $metricDate->add('1 MONTH');
- $numberOfMonth = $metricDate->format('t');
- $metricDate = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m').'-'.$numberOfMonth.' '.$timeOfEndDate.':00', 'Y-m-d H:i:s');
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'MIDDLEOF')
- {
- $numberOfHalfMonth = ceil($metricDate->format('t')/2);
- $metricDate = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m').'-'.$numberOfHalfMonth.' '.$timeOfEndDate.':00', 'Y-m-d H:i:s');
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'STARTOF')
- {
- $metricDate = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m').'-01 '.$timeOfStartDate.':00', 'Y-m-d H:i:s');
- $modificator = true;
- }
- else if ($currentModificator['TYPE'] == 'ENDOF')
- {
- $numberOfMonth = $metricDate->format('t');
- $metricDate = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m').'-'.$numberOfMonth.' '.$timeOfEndDate.':00', 'Y-m-d H:i:s');
- $modificator = true;
- }
- }
- else
- {
- if (in_array($currentModificator['TYPE'], Array('BEFORE', 'PREVIOUS')))
- {
- $metricDate->add('-1 DAY');
- }
- else if (in_array($currentModificator['TYPE'], Array('AFTER', 'NEXT')))
- {
- $metricDate->add('1 DAY');
- }
- else if ($currentModificator['TYPE'] == 'MIDDLEOF')
- {
- $metricTime = '14:00';
- }
- else if ($currentModificator['TYPE'] == 'STARTOF')
- {
- $metricTime = $timeOfStartDate;
- }
- $modificator = true;
- }
- if (in_array($currentModificator['TYPE'], Array('MORNING', 'LUNCH', 'EVENING', 'HHMM')))
- {
- $metricTime = $currentModificator['VALUE'];
- $modificator = true;
- }
- }
- if (!$modificator)
- {
- if ($metric['TYPE'] == 'WEEK')
- {
- if ($metricDate->format('N') == 3)
- {
- $metricDate->add('FRIDAY');
- }
- else if ($metricDate->format('N') < 3)
- {
- $metricDate->add('THURSDAY');
- }
- else if ($metricDate->format('N') != 7)
- {
- $metricDate->add('SUNDAY');
- }
- }
- else if ($metric['TYPE'] == 'WEEKEND')
- {
- if (strtolower($metricDate->format('l')) == 'saturday')
- $metricDate->add('SUNDAY');
- else if (strtolower($metricDate->format('l')) != 'sunday')
- $metricDate->add('SATURDAY');
- }
- else if ($metric['TYPE'] == 'MONTH')
- {
- $numberOfMonth = $metricDate->format('j');
- if ($numberOfMonth > 15)
- {
- $plus = $metricDate->format('t')-$numberOfMonth;
- if ($plus >= 1)
- {
- $metricDate->add($plus.' DAY');
- }
- }
- else if ($numberOfMonth >= 10 && $numberOfMonth <= 15)
- {
- $plus = 20-$numberOfMonth;
- $metricDate->add($plus.' DAY');
- }
- else
- {
- $plus = 15-$numberOfMonth;
- $metricDate->add($plus.' DAY');
- }
- }
- }
- $result = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m-d').' '.$metricTime.':00', 'Y-m-d H:i:s');
- break;
- case 2:
- $metricDate = $defaultDate;
- $modificator = '';
- $metricTime = $timeOfEndDate;
- $metricModificator = self::checkModifierPosition($metric, $metricModificator);
- foreach ($metricModificator as $currentModificator)
- {
- $metricDate = self::getDateOfDayOfCurrentWeek($metric['TYPE'], $metricDate);
- if ($currentModificator['TYPE'] == 'BEFORE')
- {
- $metricDate->add('-1 DAY');
- }
- else if ($currentModificator['TYPE'] == 'AFTER')
- {
- $metricDate->add('1 DAY');
- }
- else if ($currentModificator['TYPE'] == 'THIS')
- {
- $metricDate->add('LAST '.$metric['TYPE']);
- }
- else if (in_array($currentModificator['TYPE'], Array('NEXT', 'PREVIOUS')))
- {
- if ($currentModificator['TYPE'] == 'NEXT')
- {
- $metricDate->add('NEXT '.$metric['TYPE']);
- }
- else
- {
- $metricDate->add('PREVIOUS '.$metric['TYPE']);
- }
- }
- else if ($currentModificator['TYPE'] == 'MIDDLEOF')
- {
- $metricTime = '14:00';
- }
- else if ($currentModificator['TYPE'] == 'STARTOF')
- {
- $metricTime = $timeOfStartDate;
- }
- else if (in_array($currentModificator['TYPE'], Array('MORNING', 'LUNCH', 'EVENING', 'HHMM')))
- {
- $metricTime = $currentModificator['VALUE'];
- }
- $modificator = true;
- }
- if (!$modificator)
- {
- $modificator = strtolower($metric['TYPE']) == strtolower($metricDate->format('l'))? 'NEXT ': '';
- $metricDate->add($modificator.$metric['TYPE']);
- }
- $result = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m-d').' '.$metricTime.':00', 'Y-m-d H:i:s');
- break;
- case 3:
- $metricDate = $defaultDate;
- $metricTime = $timeOfEndDate;
- switch($metric['TYPE'])
- {
- case 'BEFORE':
- $metricDate->add('TOMORROW')->add('TOMORROW');
- break;
- case 'AFTER':
- $metricDate->add('TOMORROW');
- break;
- case 'NEXT':
- $metricDate->add('YESTERDAY');
- break;
- case 'PREVIOUS':
- $metricDate->add('YESTERDAY')->add('YESTERDAY');
- break;
- case 'MIDDLEOF':
- $metricTime = '14:00';
- break;
- case 'STARTOF':
- $metricTime = $timeOfStartDate;
- break;
- case 'HHMM':
- $metricTime = $metric['VALUE'];
- break;
- }
- $result = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m-d').' '.$metricTime.':00', 'Y-m-d H:i:s');
- break;
- case 4:
- $modificator = '';
- $metricTime = $timeOfEndDate;
- $metricModificator = self::checkModifierPosition($metric, $metricModificator);
- foreach ($metricModificator as $currentModificator)
- {
- if (in_array($currentModificator['TYPE'], Array('MORNING', 'LUNCH', 'EVENING', 'HHMM')))
- {
- $metricTime = $currentModificator['VALUE'];
- }
- }
- $result = new \Bitrix\Main\Type\DateTime($metric['VALUE'].' '.$metricTime.':00', 'Y-m-d H:i:s');
- break;
- case 5:
- $metricDate = $defaultDate;
- $modificator = '';
- $metricTime = $metric['VALUE'];
- $metricModificator = self::checkModifierPosition($metric, $metricModificator);
- foreach ($metricModificator as $currentModificator)
- {
- if ($currentModificator['TYPE'] == 'BEFORE')
- {
- $metricDate->add('-1 DAY');
- }
- else if ($currentModificator['TYPE'] == 'AFTER')
- {
- $metricDate->add('1 DAY');
- }
- else if (in_array($currentModificator['TYPE'], Array('NEXT', 'PREVIOUS')))
- {
- if ($currentModificator['TYPE'] == 'NEXT')
- {
- $metricDate->add('NEXT '.$metric['TYPE']);
- }
- else
- {
- $metricDate->add('PREVIOUS '.$metric['TYPE']);
- }
- }
- else if ($currentModificator['TYPE'] == 'MIDDLEOF')
- {
- $metricTime = '14:00';
- }
- else if ($currentModificator['TYPE'] == 'STARTOF')
- {
- $metricTime = $timeOfStartDate;
- }
- else if (in_array($currentModificator['TYPE'], Array('MORNING', 'LUNCH', 'EVENING', 'HHMM')))
- {
- $metricTime = $currentModificator['VALUE'];
- }
- $modificator = true;
- }
- if (!$modificator)
- {
- $modificator = strtolower($metric['TYPE']) == strtolower($metricDate->format('l'))? 'NEXT ': '';
- $metricDate->add($modificator.$metric['TYPE']);
- }
- $result = new \Bitrix\Main\Type\DateTime($metricDate->format('Y-m-d').' '.$metricTime.':00', 'Y-m-d H:i:s');
- break;
- }
- return $result;
- }
- /**
- * Creates Date object of the day of the method week (private function for self::createDateUsingMetrics)
- *
- * @param string $nameOfday name of the day (monday, tuesday, etc)
- * @param \Bitrix\Main\Type\DateTime $date If not specified, the modified date is got from the current date.
- * @return \Bitrix\Main\Type\DateTime
- *
- */
- private static function getDateOfDayOfCurrentWeek($nameOfday, \Bitrix\Main\Type\DateTime $date = null)
- {
- $date = $date? $date: new \Bitrix\Main\Type\DateTime();
- $nameOfday = mb_strtoupper($nameOfday);
- if (!in_array($nameOfday, Array('MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY')))
- return false;
- $relation = '';
- $day = $date->format('N');
- if (
- $nameOfday == 'MONDAY' && $day == 1 ||
- $nameOfday == 'TUESDAY' && $day <= 2 ||
- $nameOfday == 'WEDNESDAY' && $day <= 3 ||
- $nameOfday == 'THURSDAY' && $day <= 4 ||
- $nameOfday == 'FRIDAY' && $day <= 5 ||
- $nameOfday == 'SATURDAY' && $day <= 6 ||
- $nameOfday == 'SUNDAY' && $day <= 7
- )
- {
- $relation = 'THIS';
- }
- $date->add($relation.' '.$nameOfday);
- return $date;
- }
- /**
- * @param $text
- * @param $position
- * @return string
- */
- private static function getMatchWord($text, $position)
- {
- $letters = array_merge(Array(" ", "\n", "\t", "\r"), str_split('"-.,?!#$%^&*();:<>\|{}-=^@[]`'));
- $spaceFound = self::findFirstOccurrence($text, $letters, $position);
- if ($spaceFound !== false)
- {
- $result = mb_substr($text, $position, $spaceFound - $position);
- }
- else
- {
- $result = mb_substr($text, $position);
- }
- return $result;
- }
- private static function getTextForReplace($text, $metrics, $metricModifier)
- {
- $found = false;
- $minStartPosition = null;
- $maxEndPosition = null;
- if (!empty($metrics))
- {
- $minStartPosition = $metrics['POSITION'];
- $maxEndPosition = $metrics['POSITION'] + $metrics['COUNT'];
- $found = true;
- }
- if (is_array($metricModifier))
- {
- foreach ($metricModifier as $metrics)
- {
- if (!$found)
- {
- $minStartPosition = $metrics['POSITION'];
- $maxEndPosition = $metrics['POSITION'] + $metrics['COUNT'];
- $found = true;
- }
- else
- {
- if ($minStartPosition > $metrics['POSITION'])
- {
- $minStartPosition = $metrics['POSITION'];
- }
- if ($maxEndPosition < $metrics['POSITION'] + $metrics['COUNT'])
- {
- $maxEndPosition = $metrics['POSITION'] + $metrics['COUNT'];
- }
- }
- }
- }
- if (is_null($minStartPosition) || is_null($maxEndPosition))
- {
- $result = false;
- }
- else
- {
- $result = mb_substr($text, $minStartPosition, $maxEndPosition - $minStartPosition);
- $result = Array('TEXT' => $result, 'POSITION' => $minStartPosition, 'LENGTH' => mb_strlen($result));
- }
- return $result;
- }
- private static function checkModifierPosition($metrics, $metricModifier)
- {
- $newMetrics = $metrics;
- $stackMetrics = Array();
- $while = true;
- $maxWhile = 100;
- while ($while && $maxWhile > 0)
- {
- $while = false;
- foreach ($metricModifier as $key => $currentModificator)
- {
- $diffResult = abs($newMetrics['POSITION'] - ($currentModificator['POSITION'] + $currentModificator['COUNT']));
- if ($diffResult < 5)
- {
- $while = true;
- $newMetrics = $currentModificator;
- $stackMetrics[] = $currentModificator;
- unset($metricModifier[$key]);
- }
- else
- {
- $diffResult = abs($newMetrics['POSITION']+$newMetrics['COUNT'] - ($currentModificator['POSITION']));
- if ($diffResult < 5)
- {
- $while = true;
- $newMetrics = $currentModificator;
- $stackMetrics[] = $currentModificator;
- unset($metricModifier[$key]);
- }
- }
- }
- $maxWhile--;
- }
- return $stackMetrics;
- }
- private static function findFirstOccurrence($haystack, $needle, $offset=0)
- {
- $haystack = mb_substr($haystack, 0, 25 + $offset);
- if(!is_array($needle))
- {
- $needle = array($needle);
- }
- $positions = array();
- foreach($needle as $query)
- {
- $result = mb_strpos($haystack, $query, $offset);
- if ($result !== false)
- {
- $positions[] = $result;
- }
- }
- return empty($positions)? false: min($positions);
- }
- }