• Модуль: calendar
  • Путь к файлу: ~/bitrix/modules/calendar/classes/general/calendar_webservice.php
  • Класс: CCalendarWebService
  • Вызов: CCalendarWebService::UpdateListItems
function UpdateListItems($listName, $updates)
{
	global $USER;

	$arStatusValues = array_flip($this->arStatusValues);
	$arPriorityValues = array_flip($this->arPriorityValues);

	if (!$listName_original = CIntranetUtils::checkGUID($listName))
	{
		return new CSoapFault('Data error', 'Wrong GUID - ' . $listName);
	}

	$obResponse = new CXMLCreator('Results');

	$listName = ToUpper(CIntranetUtils::makeGUID($listName_original));
	$arSections = CCalendarSect::GetList(array('arFilter' => array('XML_ID' => $listName_original)));
	if (!$arSections || !is_array($arSections[0]))
	{
		return new CSoapFault(
			'List not found',
			'List with ' . $listName . ' GUID not found'
		);
	}

	$arSection = $arSections[0];

	$bGroup = $arSection['CAL_TYPE'] === 'group';
	$calType = $arSection['CAL_TYPE'];
	$ownerId = $arSection['OWNER_ID'];

	if ($bGroup)
	{
		BitrixMainLoader::includeModule('socialnetwork');
		$arGroupTmp = CSocNetGroup::GetByID($arSection['SOCNET_GROUP_ID']);
		if ($arGroupTmp["CLOSED"] === "Y")
		{
			if (COption::GetOptionString("socialnetwork", "work_with_closed_groups", "N") !== "Y")
			{
				return new CSoapFault(
					'Cannot modify archive group calendar',
					'Cannot modify archive group calendar'
				);
			}
		}
	}

	$obBatch = $updates->children[0];
//		$atrONERROR = $obBatch->getAttribute('OnError');
//		$atrDATEINUTC = $obBatch->getAttribute('DateInUtc');
//		$atrPROPERTIES = $obBatch->getAttribute('Properties');

	$arChanges = $obBatch->children;

	//$arResultIDs = array();
	//$dateStart = ConvertTimeStamp(strtotime('-1 hour'), 'FULL');
	$responseRows = array();
	$replicationId = array();
	$userId = (is_object($USER) && $USER->GetID()) ? $USER->GetID() : 1;

	foreach ($arChanges as $obMethod)
	{
		$arData = array('_command' => $obMethod->getAttribute('Cmd'));

		foreach ($obMethod->children as $obField)
		{
			$name = $obField->getAttribute('Name');
			if ($name === 'MetaInfo')
			{
				$name .= '_' . $obField->getAttribute('Property');
			}

			$arData[$name] = $obField->content;
		}

		if ($arData['_command'] === 'Delete')
		{
			$obRes = new CXMLCreator('Result');
			$obRes->setAttribute('ID', $obMethod->getAttribute('ID').','.$arData['_command']);
			$obRes->setAttribute('List', $listName);
			$obRes->addChild($obNode = new CXMLCreator('ErrorCode'));

			$res = CCalendar::DeleteEvent($arData['ID']);
			if ($res === true)
			{
				$obNode->setData('0x00000000');
			}
			else
			{
				$obNode->setData('0x81020014');
			}

			/*
				0x00000000 - ok
				0x81020015 - data conflict
				0x81020014 - generic error such as invalid value for Field
				0x81020016 - item does not exist
			*/
			$obResponse->addChild($obRes);
		}
		elseif ($arData['_command'] === 'New' || $arData['_command'] === 'Update')
		{
			$arData['Location'] = trim($arData['Location']);
			$arData['EventType'] = (int)$arData['EventType'];

			if ((int)$arData['EventType'] === 2)
			{
				$arData['EventType'] = 0;
			}

			if ($arData['EventType'] > 2 /* || ($arData['EventType'] == 1 && !$arData['RecurrenceData'])*/)
			{
				return new CSoapFault(
					'Unsupported event type',
					'Event type unsupported'
				);
			}

			$id = $arData['_command'] === 'New' ? 0 : (int)$arData['ID'];

			$arData['fRecurrence'] = (int)$arData['fRecurrence'];
			$arData['RRULE'] = '';

			if (isset($arData['EventDate']))
			{
				$fromTsUTC = $this->__makeTS($arData['EventDate']);
				if ($arData['RecurrenceData'] && $arData['fAllDayEvent'])
				{
					$toTsUTC = $fromTsUTC;
				}
				elseif (!$arData['RecurrenceData'] && $arData['fAllDayEvent'])
				{
					$toTsUTC = $this->__makeTS($arData['EndDate']) - 86340;
				}
				else
				{
					$toTsUTC = $this->__makeTS($arData['EndDate']);
				}

				$skipTime = $arData['fAllDayEvent'] ? 'Y' : 'N';
				$fromTs = $fromTsUTC;
				$toTs = $toTsUTC;
				if (!$arData['fAllDayEvent'])
				{
					$fromTs += CCalendar::GetCurrentOffsetUTC($userId);
					$toTs += CCalendar::GetCurrentOffsetUTC($userId);
				}
			}
			else
			{
				$fromTs = $toTs = $fromTsUTC = $toTsUTC = false;
				$skipTime = false;
			}

			if ($arData['RecurrenceData'] && isset($arData['EventDate']))
			{
				$xmlstr = $arData['RecurrenceData'];
				$obRecurData = new CDataXML();
				$obRecurData->LoadString($xmlstr);

				$obRecurRule = $obRecurData->tree->children[0]->children[0];
				$obRecurRepeat = $obRecurRule->children[1];
				$obNode = $obRecurRepeat->children[0];

				$arData['RRULE'] = [];
				switch($obNode->name)
				{
					case 'daily':
						// hack. we have no "work days" daily recurence
						if ($obNode->getAttribute('weekday') === 'TRUE')
						{
							$arData['RRULE']['FREQ'] = 'WEEKLY';
							$arData['RRULE']['BYDAY'] = 'MO,TU,WE,TH,FR';
							$arData['RRULE']['INTERVAL'] = 1;
						}
						else
						{
							$arData['RRULE']['FREQ'] = 'DAILY';
							$arData['RRULE']['INTERVAL'] = $obNode->getAttribute('dayFrequency');
						}

						$time_end = strtotime(
							date(date('Y-m-d', $fromTsUTC).' H:i:s', $toTsUTC)
						);

						$arData['DT_LENGTH'] = $time_end - $fromTsUTC;
					break;

					case 'weekly':
						$arData['RRULE']['FREQ'] = 'WEEKLY';
						$arData['RRULE']['BYDAY'] = [];

						$arWeekDays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'];
						foreach ($arWeekDays as $day => $value)
						{
							if ($obNode->getAttribute($value))
							{
								$arData['RRULE']['BYDAY'][] = mb_strtoupper($value);
							}
						}

						$arData['RRULE']['BYDAY'] = implode(',', $arData['RRULE']['BYDAY']);
						$arData['RRULE']['INTERVAL'] = $obNode->getAttribute('weekFrequency');

						$time_end = strtotime(date(date('Y-m-d', $fromTsUTC).' H:i:s', $toTsUTC));

						$arData['DT_LENGTH'] = $time_end - $fromTsUTC;
					break;

					case 'monthly':
						$arData['RRULE']['FREQ'] = 'MONTHLY';
						$arData['RRULE']['INTERVAL'] = $obNode->getAttribute('monthFrequency');
						$time_end = strtotime(date(date('Y-m', $fromTsUTC).'-d H:i:s', $toTsUTC));

						$arData['DT_LENGTH'] = $time_end - $fromTsUTC;
					break;

					case 'yearly':
						$arData['RRULE']['FREQ'] = 'YEARLY';
						$arData['RRULE']['INTERVAL'] = $obNode->getAttribute('yearFrequency');

						$time_end = strtotime(date(date('Y', $fromTsUTC).'-m-d H:i:s', $toTsUTC));

						$arData['DT_LENGTH'] = $time_end - $fromTsUTC;
					break;
				}

				if ((int)$arData['DT_LENGTH'] === 0 && isset($arData['RRULE']['FREQ']))
				{
					$arData['DT_LENGTH'] = 86400;
				}

				$obWhile = $obRecurRule->children[2];
				if ($obWhile->name === 'repeatForever')
				{
					$arData['RRULE']['UNTIL'] = MakeTimeStamp('');;
				}
				elseif ($obWhile->name === 'windowEnd')
				{
					$toTsUTC = $this->__makeTS($obWhile->textContent());
					$arData['RRULE']['UNTIL'] = ConvertTimeStamp($toTsUTC, 'FULL');
				}
				elseif ($obWhile->name === 'repeatInstances')
				{
					$arData['RRULE']['COUNT'] = intval($obWhile->textContent());
				}
			}
			elseif(($arData['fRecurrence'] === -1) && ($id > 0))
			{
				$arData['RRULE'] = -1;
			}

			$arFields = [
				"ID" => $id,
				'CAL_TYPE' => $calType,
				'OWNER_ID' => $ownerId,
				'CREATED_BY' => $userId,
				'NAME' => $arData['Title'],
				'DESCRIPTION' => self::ClearOutlookHtml($arData['Description']),
				'SECTIONS' => [$arSection['ID']],
				'ACCESSIBILITY' => $arStatusValues[$arData['MetaInfo_BusyStatus']],
				'IMPORTANCE' => $arPriorityValues[$arData['MetaInfo_Priority']],
				'RRULE' => $arData['RRULE'],
				'LOCATION' => BitrixCalendarRoomsUtil::unParseTextLocation($arData['Location'])
			];

			if ($fromTs && $toTs)
			{
				$arFields['DATE_FROM'] = CCalendar::Date($fromTs, $skipTime === 'N');
				$arFields['DATE_TO'] = CCalendar::Date($toTs, $skipTime === 'N');
				$arFields['DT_SKIP_TIME'] = $skipTime;
			}

			if (isset($arData['DT_LENGTH']) && $arData['DT_LENGTH'] > 0)
			{
				$arFields['DT_LENGTH'] = $arData['DT_LENGTH'];
			}

			$eventId = CCalendar::SaveEvent(
				[
					'arFields' => $arFields,
					'fromWebservice' => true
				]
			);

			if ($eventId && ((int)$eventId) > 0)
			{
				$eventId = (int)$eventId;
				$replicationId[$eventId] = $arData['MetaInfo_ReplicationID'];

				$responseRows[$eventId] = new CXMLCreator('Result');
				$responseRows[$eventId]->setAttribute('ID', $obMethod->getAttribute('ID').','.$arData['_command']);
				$responseRows[$eventId]->setAttribute('List', $listName);

				$responseRows[$eventId]->addChild($obNode = new CXMLCreator('ErrorCode'));
				$obNode->setData('0x00000000');
				//$responseRows[$eventId]->setAttribute('Version', 3);
			}
		}
	}

	$userId = (is_object($USER) && $USER->GetID()) ? $USER->GetID() : 1;
	$fetchMeetings = (int)CCalendar::GetMeetingSection($userId) === (int)$arSection['ID'];
	$arEvents = CCalendarEvent::GetList(
		[
			'arFilter' => [
				'CAL_TYPE' => $calType,
				'OWNER_ID' => $ownerId,
				'SECTION' => $arSection['ID']
			],
			'getUserfields' => false,
			'parseRecursion' => false,
			'fetchAttendees' => false,
			'fetchMeetings' => $fetchMeetings,
			'userId' => $userId
		]
	);

	foreach ($arEvents as $event)
	{
		if ($responseRows[$event['ID']])
		{
			$last_change = 0;
			$obRow = $this->__getRow($event, $listName, $last_change);
			$obRow->setAttribute('xmlns:z', "#RowsetSchema");

			if ($replicationId[$event['ID']])
			{
				$obRow->setAttribute('MetaInfo_ReplicationID', $replicationId[$event['ID']]);
			}

			$responseRows[$event['ID']]->addChild($obRow);
		}

		$obResponse->addChild($responseRows[$event['ID']]);
	}

	return ['UpdateListItemsResult' => $obResponse];
}