• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/lib/orm/data/datamanager.php
  • Класс: BitrixMainORMDataDataManager
  • Вызов: DataManager::updateMulti
static function updateMulti($primaries, $data, $ignoreEvents = false)
{
	$entity = static::getEntity();
	$primaries = array_values($primaries);

	/** @var EntityObject[] $objects */
	$objects = [];

	foreach ($primaries as &$primary)
	{
		static::normalizePrimary($primary, $data);
		static::validatePrimary($primary);

		/** @var EntityObject $object */
		$object = $entity->wakeUpObject($primary);

		foreach ($data as $k => $v)
		{
			$object->set($k, $v);
		}

		$objects[] = $object;
	}

	$result = new UpdateResult;

	try
	{
		// before event
		if (!$ignoreEvents)
		{
			foreach ($objects as $object)
			{
				static::callOnBeforeUpdateEvent($object, $data, $result);
			}
		}

		// collect array data
		$allFields = [];
		$allUfData = [];

		foreach ($objects as $k => $object)
		{
			// actualize old-style fields array from object
			$allFields[$k] = $object->collectValues(Values::CURRENT, FieldTypeMask::SCALAR);

			// uf values
			$allUfData[$k] = $object->collectValues(Values::CURRENT, FieldTypeMask::USERTYPE);
		}

		// check data and uf
		foreach ($objects as $k => $object)
		{
			$fields = $allFields[$k];
			$ufdata = $allUfData[$k];

			// check data
			static::checkFields($result, $object->primary, $fields);

			// check uf data
			if (!empty($ufdata))
			{
				static::checkUfFields($object, $ufdata, $result);
			}

			// check if there is still some data
			if (empty($fields) && empty($ufdata))
			{
				$result->addError(new EntityError("There is no data to add."));
			}
		}

		// return if any error in any row
		if (!$result->isSuccess(true))
		{
			return $result;
		}

		//event on adding
		if (!$ignoreEvents)
		{
			foreach ($objects as $k => $object)
			{
				$fields = $allFields[$k];
				$ufdata = $allUfData[$k];

				static::callOnUpdateEvent($object, $fields, $ufdata);
			}
		}

		// prepare sql
		$allSqlData = [];

		foreach ($allFields as $k => $fields)
		{
			// use save modifiers
			$fieldsToDb = $fields;

			foreach ($fieldsToDb as $fieldName => $value)
			{
				$field = $entity->getField($fieldName);
				$fieldsToDb[$fieldName] = $field->modifyValueBeforeSave($value, $fields);
			}

			$dataReplacedColumn = static::replaceFieldName($fieldsToDb);

			$allSqlData[$k] = $dataReplacedColumn;
		}

		// check if rows data are equal
		$areEqual = true;

		$dataSample = $allSqlData[0];
		asort($dataSample);

		if (!empty($allSqlData[0]))
		{

			foreach ($allSqlData as $data)
			{
				asort($data);

				if ($data !== $dataSample)
				{
					$areEqual = false;
					break;
				}
			}

			// save data
			$connection = $entity->getConnection();
			$helper = $connection->getSqlHelper();
			$tableName = $entity->getDBTableName();

			// save data
			if ($areEqual)
			{
				// one query
				$update = $helper->prepareUpdate($tableName, $dataSample);
				$where = [];
				$isSinglePrimary = (count($entity->getPrimaryArray()) == 1);

				foreach ($allSqlData as $k => $data)
				{
					$replacedPrimary = static::replaceFieldName($objects[$k]->primary);

					if ($isSinglePrimary)
					{
						// for single primary IN is better
						$primaryName = key($replacedPrimary);
						$primaryValue = current($replacedPrimary);
						$tableField = $entity->getConnection()->getTableField($tableName, $primaryName);

						$where[] = $helper->convertToDb($primaryValue, $tableField);
					}
					else
					{
						$id = [];

						foreach ($replacedPrimary as $primaryName => $primaryValue)
						{
							$id[] = $helper->prepareAssignment($tableName, $primaryName, $primaryValue);
						}
						$where[] = implode(' AND ', $id);
					}
				}

				if ($isSinglePrimary)
				{
					$where = $helper->quote($entity->getPrimary()).' IN ('.join(', ', $where).')';
				}
				else
				{
					$where = '('.join(') OR (', $where).')';
				}

				$sql = "UPDATE ".$helper->quote($tableName)." SET ".$update[0]." WHERE ".$where;
				$connection->queryExecute($sql, $update[1]);

				$result->setAffectedRowsCount($connection);
			}
			else
			{
				// query for each row
				foreach ($allSqlData as $k => $dataReplacedColumn)
				{
					$update = $helper->prepareUpdate($tableName, $dataReplacedColumn);

					$replacedPrimary = static::replaceFieldName($objects[$k]->primary);

					$id = [];

					foreach ($replacedPrimary as $primaryName => $primaryValue)
					{
						$id[] = $helper->prepareAssignment($tableName, $primaryName, $primaryValue);
					}
					$where = implode(' AND ', $id);

					$sql = "UPDATE ".$helper->quote($tableName)." SET ".$update[0]." WHERE ".$where;
					$connection->queryExecute($sql, $update[1]);

					$result->setAffectedRowsCount($connection);
				}
			}
		}

		// doesn't make sense for multiple rows
		$result->setData($dataSample);

		if (count($allSqlData) == 1)
		{
			$result->setPrimary($objects[0]->primary);
			$result->setObject($objects[0]);
		}

		// save uf data
		foreach ($allUfData as $ufdata)
		{
			if (!empty($ufdata))
			{
				global $USER_FIELD_MANAGER;
				$USER_FIELD_MANAGER->update($entity->getUfId(), end($primary), $ufdata);
			}
		}

		static::cleanCache();

		// event after update
		if (!$ignoreEvents)
		{
			foreach ($objects as $k => $object)
			{
				$fields = $allFields[$k] + $allUfData[$k];

				static::callOnAfterUpdateEvent($object, $fields);
			}
		}
	}
	catch (Exception $e)
	{
		// check result to avoid warning
		$result->isSuccess();

		throw $e;
	}

	return $result;
}