AnonSec Shell
Server IP : 85.193.89.191  /  Your IP : 18.224.32.112
Web Server : Apache
System : Linux 956367-cx40159.tmweb.ru 3.10.0-1160.105.1.el7.x86_64 #1 SMP Thu Dec 7 15:39:45 UTC 2023 x86_64
User : bitrix ( 600)
PHP Version : 8.1.27
Disable Function : NONE
MySQL : OFF  |  cURL : OFF  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/bitrix/www/bitrix/modules/main/lib/text/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home/bitrix/www/bitrix/modules/main/lib/text/dateconverter.php
<?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] ?? 0), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeStart[1] ?? 0), 2, "0", STR_PAD_LEFT);

		$workTimeEnd = explode('.', \Bitrix\Main\Config\Option::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;
	}

	/**
	 * 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] ?? 0), 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] ?? 0), 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');
							}
						}
						elseif ($numberOfMonth >= 10)
						{
							$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);
	}
}

Anon7 - 2022
AnonSec Team