Your IP : 18.119.255.122


Current Path : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/catalog/lib/compatible/
Upload File :
Current File : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/catalog/lib/compatible/eventcompatibility.php

<?php
/** @global \CMain $APPLICATION */

namespace Bitrix\Catalog\Compatible;

use Bitrix\Main,
	Bitrix\Main\Localization\Loc,
	Bitrix\Catalog;

Loc::loadMessages(__FILE__);

final class EventCompatibility
{
	/* Events old kernel, which will be called in a new kernel */

	/* class \CProduct */
	const ENTITY_PRODUCT = 'Product';
	const EVENT_ON_BEFORE_PRODUCT_ADD = 'OnBeforeProductAdd';
	const EVENT_ON_PRODUCT_ADD = 'OnProductAdd';
	const EVENT_ON_BEFORE_PRODUCT_UPDATE = 'OnBeforeProductUpdate';
	const EVENT_ON_PRODUCT_UPDATE = 'OnProductUpdate';

	/* class \CPrice */
	const ENTITY_PRICE = 'Price';
	const EVENT_ON_BEFORE_PRICE_ADD = 'OnBeforePriceAdd';
	const EVENT_ON_PRICE_ADD = 'OnPriceAdd';
	const EVENT_ON_BEFORE_PRICE_UPDATE = 'OnBeforePriceUpdate';
	const EVENT_ON_PRICE_UPDATE = 'OnPriceUpdate';
	const EVENT_ON_BEFORE_PRICE_DELETE = 'OnBeforePriceDelete';
	const EVENT_ON_PRICE_DELETE = 'OnPriceDelete';

	private static $allowEvents = 0;

	private static $handlerList = array();

	private static $whiteList = array(
		self::ENTITY_PRODUCT => array(
			'ID' => true,
			'QUANTITY' => true,
			'QUANTITY_TRACE' => true,
			'WEIGHT' => true,
			'PRICE_TYPE' => true,
			'RECUR_SCHEME_LENGTH' => true,
			'RECUR_SCHEME_TYPE' => true,
			'TRIAL_PRICE_ID' => true,
			'WITHOUT_ORDER' => true,
			'SELECT_BEST_PRICE' => true,
			'VAT_ID' => true,
			'VAT_INCLUDED' => true,
			'CAN_BUY_ZERO' => true,
			'NEGATIVE_AMOUNT_TRACE' => true,
			'TMP_ID' => true,
			'PURCHASING_PRICE' => true,
			'PURCHASING_CURRENCY' => true,
			'BARCODE_MULTI' => true,
			'QUANTITY_RESERVED' => true,
			'SUBSCRIBE' => true,
			'WIDTH' => true,
			'LENGTH' => true,
			'HEIGHT' => true,
			'MEASURE' => true,
			'TYPE' => true,
			'AVAILABLE' => true,
			'BUNDLE' => true,
			'PRICE_MODE' => true
		),
		self::ENTITY_PRICE => array(
			'PRODUCT_ID' => true,
			'CATALOG_GROUP_ID' => true,
			'PRICE' => true,
			'CURRENCY' => true,
			'QUANTITY_FROM' => true,
			'QUANTITY_TO' => true,
			'PRICE_SCALE' => true,
			'EXTRA_ID' => true,
			'TMP_ID' => true,
			'MEASURE_RATIO_ID' => true
		)
	);

	public static function execAgent()
	{
		self::registerEvents();
		return '';
	}

	public static function registerEvents()
	{
		$eventManager = Main\EventManager::getInstance();

		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_BEFORE_ADD,
			'catalog', __CLASS__, 'handlerProductOnBeforeAdd'
		);
		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_AFTER_ADD,
			'catalog', __CLASS__, 'handlerProductOnAfterAdd'
		);

		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_BEFORE_UPDATE,
			'catalog', __CLASS__, 'handlerProductOnBeforeUpdate'
		);
		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_AFTER_UPDATE,
			'catalog', __CLASS__, 'handlerProductOnAfterUpdate'
		);

		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_BEFORE_ADD,
			'catalog', __CLASS__, 'handlerPriceOnBeforeAdd'
		);
		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_AFTER_ADD,
			'catalog', __CLASS__, 'handlerPriceOnAfterAdd'
		);

		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_BEFORE_UPDATE,
			'catalog', __CLASS__, 'handlerPriceOnBeforeUpdate'
		);
		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_AFTER_UPDATE,
			'catalog', __CLASS__, 'handlerPriceOnAfterUpdate'
		);

		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_BEFORE_DELETE,
			'catalog', __CLASS__, 'handlerPriceOnBeforeDelete'
		);
		$eventManager->registerEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_AFTER_DELETE,
			'catalog', __CLASS__, 'handlerPriceOnAfterDelete'
		);

		unset($eventManager);
	}

	public static function unRegisterEvents()
	{
		$eventManager = Main\EventManager::getInstance();

		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_BEFORE_ADD,
			'catalog', __CLASS__, 'handlerProductOnBeforeAdd'
		);
		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_AFTER_ADD,
			'catalog', __CLASS__, 'handlerProductOnAfterAdd'
		);

		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_BEFORE_UPDATE,
			'catalog', __CLASS__, 'handlerProductOnBeforeUpdate'
		);
		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Product::'.Main\Entity\DataManager::EVENT_ON_AFTER_UPDATE,
			'catalog', __CLASS__, 'handlerProductOnAfterUpdate'
		);

		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_BEFORE_ADD,
			'catalog', __CLASS__, 'handlerPriceOnBeforeAdd'
		);
		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_AFTER_ADD,
			'catalog', __CLASS__, 'handlerPriceOnAfterAdd'
		);

		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_BEFORE_UPDATE,
			'catalog', __CLASS__, 'handlerPriceOnBeforeUpdate'
		);
		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_AFTER_UPDATE,
			'catalog', __CLASS__, 'handlerPriceOnAfterUpdate'
		);

		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_BEFORE_DELETE,
			'catalog', __CLASS__, 'handlerPriceOnBeforeDelete'
		);
		$eventManager->unRegisterEventHandler(
			'catalog', 'Bitrix\Catalog\Model\Price::'.Main\Entity\DataManager::EVENT_ON_AFTER_DELETE,
			'catalog', __CLASS__, 'handlerPriceOnAfterDelete'
		);

		unset($eventManager);
	}

	public static function handlerProductOnBeforeAdd(Catalog\Model\Event $event)
	{
		return self::handlerOnBeforeAdd($event, self::ENTITY_PRODUCT, self::EVENT_ON_BEFORE_PRODUCT_ADD);
	}

	public static function handlerProductOnAfterAdd(Catalog\Model\Event $event)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		$success = $event->getParameter('success');
		if (!$success)
			return $result;

		self::disableEvents();

		$handlerList = array_merge(
			self::getHandlerList('catalog', self::EVENT_ON_PRODUCT_ADD),
			self::getHandlerList('sale', self::EVENT_ON_PRODUCT_ADD)       // compatibility with old strange code
		);
		if (!empty($handlerList))
		{
			$data = array(
				$event->getParameter('id'),
				$event->getParameter('fields') + $event->getParameter('external_fields')
			);

			foreach ($handlerList as $handler)
			{
				ExecuteModuleEventEx($handler, $data);
			}
			unset($handler, $data);
		}
		unset($handlerList);

		self::enableEvents();

		return $result;
	}

	public static function handlerProductOnBeforeUpdate(Catalog\Model\Event $event)
	{
		return self::handlerOnBeforeUpdate($event, self::ENTITY_PRODUCT, self::EVENT_ON_BEFORE_PRODUCT_UPDATE);
	}

	public static function handlerProductOnAfterUpdate(Catalog\Model\Event $event)
	{
		return self::handlerOnAfterModify($event, self::EVENT_ON_PRODUCT_UPDATE);
	}

	public static function handlerPriceOnBeforeAdd(Catalog\Model\Event $event)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', self::EVENT_ON_BEFORE_PRICE_ADD);

		if (!empty($handlerList))
		{
			$error = false;
			$fields = $event->getParameter('fields');
			$externalFields = $event->getParameter('external_fields');
			$oldFields = $fields;
			$oldExternalFields = $externalFields;
			$actions = $event->getParameter('actions');
			$fields['RECALL'] = (isset($actions['OLD_RECOUNT']) && $actions['OLD_RECOUNT'] === true);

			foreach ($handlerList as $handler)
			{
				if (ExecuteModuleEventEx($handler, array(&$fields)) === false)
				{
					$error = true;
					break;
				}
			}
			unset($handler);

			if (isset($fields['RECALL']))
			{
				$result->modifyActions(array('OLD_RECOUNT' => $fields['RECALL']));
				unset($fields['RECALL']);
			}
			else
			{
				if (isset($actions['OLD_RECOUNT']))
					$result->unsetActions(array('OLD_RECOUNT'));
			}

			self::fillResultData($result, self::ENTITY_PRICE, $oldFields, $oldExternalFields, $fields);
			unset($actions, $oldExternalFields, $oldFields, $externalFields, $fields);

			if ($error)
				self::setHandlerError($result, self::EVENT_ON_BEFORE_PRICE_ADD);
			unset($error);
		}

		self::enableEvents();

		return $result;
	}

	public static function handlerPriceOnAfterAdd(Catalog\Model\Event $event)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		$success = $event->getParameter('success');
		if (!$success)
			return $result;

		self::disableEvents();

		$handlerList = array_merge(
			self::getHandlerList('catalog', self::EVENT_ON_PRICE_ADD),
			self::getHandlerList('sale', self::EVENT_ON_PRICE_ADD)       // compatibility with old strange code
		);
		if (!empty($handlerList))
		{
			$fields = $event->getParameter('fields');
			$actions = $event->getParameter('actions');
			$fields['RECALL'] = (isset($actions['OLD_RECOUNT']) && $actions['OLD_RECOUNT'] === true);
			$data = array(
				$event->getParameter('id'),
				$fields + $event->getParameter('external_fields')
			);
			unset($actions, $fields);

			foreach ($handlerList as $handler)
			{
				ExecuteModuleEventEx($handler, $data);
			}
			unset($handler, $data);
		}
		unset($handlerList);

		self::enableEvents();

		return $result;
	}

	public static function handlerPriceOnBeforeUpdate(Catalog\Model\Event $event)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', self::EVENT_ON_BEFORE_PRICE_UPDATE);
		if (!empty($handlerList))
		{
			$error = false;
			$id = $event->getParameter('id');
			$fields = $event->getParameter('fields');
			$externalFields = $event->getParameter('external_fields');
			$oldFields = $fields;
			$oldExternalFields = $externalFields;
			$actions = $event->getParameter('actions');
			$fields['RECALL'] = (isset($actions['OLD_RECOUNT']) && $actions['OLD_RECOUNT'] === true);

			foreach ($handlerList as $handler)
			{
				if (ExecuteModuleEventEx($handler, array($id, &$fields)) === false)
				{
					$error = true;
					break;
				}
			}
			unset($handler);

			if (isset($fields['RECALL']))
			{
				$result->modifyActions(array('OLD_RECOUNT' => $fields['RECALL']));
				unset($fields['RECALL']);
			}
			else
			{
				if (isset($actions['OLD_RECOUNT']))
					$result->unsetActions(array('OLD_RECOUNT'));
			}

			self::fillResultData($result, self::ENTITY_PRICE, $oldFields, $oldExternalFields, $fields);
			unset($actions, $oldExternalFields, $oldFields, $externalFields, $fields);

			if ($error)
				self::setHandlerError($result, self::EVENT_ON_BEFORE_PRICE_UPDATE);
			unset($error);
		}
		unset($handlerList);

		self::enableEvents();

		return $result;
	}

	public static function handlerPriceOnAfterUpdate(Catalog\Model\Event $event)
	{
		return self::handlerPriceOnAfterModify($event, self::EVENT_ON_PRICE_UPDATE);
	}

	public static function handlerPriceOnBeforeDelete(Catalog\Model\Event $event)
	{
		return self::handlerOnBeforeDelete($event, self::EVENT_ON_BEFORE_PRICE_DELETE);
	}

	public static function handlerPriceOnAfterDelete(Catalog\Model\Event $event)
	{
		return self::handlerOnAfterDelete($event, self::EVENT_ON_PRICE_DELETE);
	}

	/**
	 * Enable old kernel events.
	 *
	 * @return void
	 */
	private static function enableEvents()
	{
		self::$allowEvents++;
	}

	/**
	 * Disable old kernel events.
	 *
	 * @return void
	 */
	private static function disableEvents()
	{
		self::$allowEvents--;
	}

	/**
	 * Return is allow old kernel events.
	 *
	 * @return bool
	 */
	private static function allowedEvents()
	{
		return (self::$allowEvents >= 0);
	}

	private static function getHandlerList($module, $event)
	{
		$eventIndex = $module.':'.$event;
		if (!isset(self::$handlerList[$eventIndex]))
		{
			self::$handlerList[$eventIndex] = array();
			$eventManager = Main\EventManager::getInstance();
			$result = $eventManager->findEventHandlers($module, $event);
			if (!empty($result))
			{
				foreach (array_keys($result) as $index)
				{
					$result[$index]['FROM_MODULE_ID'] = 'catalog';
					$result[$index]['MESSAGE_ID'] = $event;
				}
				unset($index);
				self::$handlerList[$eventIndex] = $result;
			}
			unset($result, $eventManager);
		}
		return self::$handlerList[$eventIndex];
	}

	private static function handlerOnBeforeAdd(Catalog\Model\Event $event, $entity, $eventName)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', $eventName);
		if (!empty($handlerList))
		{
			$error = false;
			$fields = $event->getParameter('fields');
			$externalFields = $event->getParameter('external_fields');
			$oldFields = $fields;
			$oldExternalFields = $externalFields;
			if (!empty($externalFields))
				$fields = $fields + $externalFields;

			foreach ($handlerList as $handler)
			{
				if (ExecuteModuleEventEx($handler, array(&$fields)) === false)
				{
					$error = true;
					break;
				}
			}
			unset($handler);

			self::fillResultData($result, $entity, $oldFields, $oldExternalFields, $fields);
			unset($oldExternalFields, $oldFields, $externalFields, $fields);

			if ($error)
				self::setHandlerError($result, $eventName);
			unset($error);
		}

		self::enableEvents();

		return $result;
	}

	private static function handlerOnAfterModify(Catalog\Model\Event $event, $eventName)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		$success = $event->getParameter('success');
		if (!$success)
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', $eventName);
		if (!empty($handlerList))
		{
			$data = array(
				$event->getParameter('id'),
				$event->getParameter('fields') + $event->getParameter('external_fields')
			);

			foreach ($handlerList as $handler)
			{
				ExecuteModuleEventEx($handler, $data);
			}
			unset($handler, $data);
		}
		unset($handlerList);

		self::enableEvents();

		return $result;
	}

	private static function handlerOnBeforeUpdate(Catalog\Model\Event $event, $entity, $eventName)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', $eventName);
		if (!empty($handlerList))
		{
			$error = false;
			$id = $event->getParameter('id');
			$fields = $event->getParameter('fields');
			$externalFields = $event->getParameter('external_fields');
			$oldFields = $fields;
			$oldExternalFields = $externalFields;
			if (!empty($externalFields))
				$fields = $fields + $externalFields;

			foreach ($handlerList as $handler)
			{
				if (ExecuteModuleEventEx($handler, array($id, &$fields)) === false)
				{
					$error = true;
					break;
				}
			}
			unset($handler);

			self::fillResultData($result, $entity, $oldFields, $oldExternalFields, $fields);
			unset($oldExternalFields, $oldFields, $externalFields, $fields);

			if ($error)
				self::setHandlerError($result, $eventName);
			unset($error);
		}
		unset($handlerList);

		self::enableEvents();

		return $result;
	}

	private static function handlerOnBeforeDelete(Catalog\Model\Event $event, $eventName)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', $eventName);
		if (!empty($handlerList))
		{
			$error = false;
			$id = $event->getParameter('id');

			foreach ($handlerList as $handler)
			{
				if (ExecuteModuleEventEx($handler, array($id)) === false)
				{
					$error = true;
					break;
				}
			}
			unset($handler);

			if ($error)
				self::setHandlerError($result, $eventName);
			unset($id, $error);
		}

		self::enableEvents();

		return $result;
	}

	private static function handlerOnAfterDelete(Catalog\Model\Event $event, $eventName)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		$success = $event->getParameter('success');
		if (!$success)
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', $eventName);
		if (!empty($handlerList))
		{
			$data = array(
				$event->getParameter('id')
			);

			foreach ($handlerList as $handler)
			{
				ExecuteModuleEventEx($handler, $data);
			}
			unset($handler, $data);
		}
		unset($handlerList);

		self::enableEvents();

		return $result;
	}

	private static function handlerPriceOnAfterModify(Catalog\Model\Event $event, $eventName)
	{
		$result = new Catalog\Model\EventResult();
		if (!self::allowedEvents())
			return $result;

		$success = $event->getParameter('success');
		if (!$success)
			return $result;

		self::disableEvents();

		$handlerList = self::getHandlerList('catalog', $eventName);
		if (!empty($handlerList))
		{
			$fields = $event->getParameter('fields');
			$actions = $event->getParameter('actions');
			$fields['RECALL'] = (isset($actions['OLD_RECOUNT']) && $actions['OLD_RECOUNT'] === true);
			$data = array(
				$event->getParameter('id'),
				$fields + $event->getParameter('external_fields')
			);
			unset($actions, $fields);

			foreach ($handlerList as $handler)
			{
				ExecuteModuleEventEx($handler, $data);
			}
			unset($handler, $data);
		}
		unset($handlerList);

		self::enableEvents();

		return $result;
	}

	private static function setHandlerError(Catalog\Model\EventResult $result, $eventName)
	{
		global $APPLICATION;

		$oldException = $APPLICATION->GetException();
		if (is_object($oldException))
		{
			$result->addError(new Main\Entity\EntityError(
				$oldException->GetString()
			));
		}
		else
		{
			$result->addError(new Main\Entity\EntityError(
				Loc::getMessage(
					'BX_CATALOG_EVENT_COMPATIBILITY_ERR_UNKNOWN',
					array('#EVENT#' => $eventName)
				)
			));
		}
		unset($oldException);
	}

	private static function fillResultData(
		Catalog\Model\EventResult $result,
		$entity,
		array $fields,
		array $externalFields,
		array $handlerFields
	)
	{
		$unsetFields = array();
		$modifyFields = array();
		$unsetExternalFields = array();
		$modifyExternalFields = array();

		$handlerExternalFields = array_diff_key($handlerFields, self::$whiteList[$entity]);
		if (!empty($handlerExternalFields))
			$handlerFields = array_intersect_key($handlerFields, self::$whiteList[$entity]);

		foreach ($fields as $key => $value)
		{
			if (!array_key_exists($key, $handlerFields))
			{
				$unsetFields[] = $key;
			}
			else
			{
				if (!is_array($value))
				{
					if ($value !== $handlerFields[$key])
						$modifyFields[$key] = $handlerFields[$key];
				}
				unset($handlerFields[$key]);
			}
		}
		if (!empty($handlerFields))
			$modifyFields = $modifyFields + $handlerFields;

		foreach ($externalFields as $key => $value)
		{
			if (!array_key_exists($key, $handlerExternalFields))
			{
				$unsetExternalFields[] = $key;
			}
			else
			{
				//TODO: add array check
				if (!is_array($value))
				{
					if ($value !== $handlerExternalFields[$key])
						$modifyExternalFields[$key] = $handlerExternalFields[$key];
				}
				unset($handlerExternalFields[$key]);
			}
		}
		if (!empty($handlerExternalFields))
			$modifyExternalFields = $modifyExternalFields + $handlerExternalFields;

		if (!empty($unsetFields))
			$result->unsetFields($unsetFields);
		if (!empty($modifyFields))
			$result->modifyFields($modifyFields);
		if (!empty($unsetExternalFields))
			$result->unsetExternalFields($unsetExternalFields);
		if (!empty($modifyExternalFields))
			$result->modifyExternalFields($modifyExternalFields);
		unset($modifyFields, $unsetFields);
	}
}