Your IP : 18.188.230.221


Current Path : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/landing/lib/
Upload File :
Current File : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/landing/lib/hook.php

<?php
namespace Bitrix\Landing;

use \Bitrix\Landing\Internals\HookDataTable as HookData;

class Hook
{
	/**
	 * If true, hook work in edit mode (form settings).
	 * @var boolean
	 */
	protected static $editMode = false;

	/**
	 * Entity type site.
	 */
	const ENTITY_TYPE_SITE = 'S';

	/**
	 * Entity type landing.
	 */
	const ENTITY_TYPE_LANDING = 'L';

	/**
	 * Dir of repository of common hooks.
	 */
	const HOOKS_PAGE_DIR = '/bitrix/modules/landing/lib/hook/page';

	/**
	 * Namespace of repoitory of common hooks (relative current).
	 */
	const HOOKS_NAMESPACE = '\\Hook\\Page\\';

	/**
	 * Get classes from dir.
	 * @param string $dir Relative dir.
	 * @return array
	 */
	protected static function getClassesFromDir($dir)
	{
		$classes = array();

		$path = Manager::getDocRoot() . $dir;
		if (($handle = opendir($path)))
		{
			while ((($entry = readdir($handle)) !== false))
			{
				if ($entry != '.' && $entry != '..')
				{
					$classes[] = strtoupper(pathinfo($entry, PATHINFO_FILENAME));
				}
			}
		}

		return $classes;
	}

	/**
	 * Get data by entity id ant type.
	 * @param int $id Entity id.
	 * @param string $type Entity type.
	 * @param boolean $asIs Return row as is.
	 * @return array
	 */
	protected static function getData($id, $type, $asIs = false)
	{
		$data = array();
		$res = HookData::getList(array(
			'select' => array(
				'ID', 'HOOK', 'CODE', 'VALUE'
			),
			'filter' => array(
				'ENTITY_ID' => $id,
				'=ENTITY_TYPE' => $type
			)
		));
		while ($row = $res->fetch())
		{
			if (!isset($data[$row['HOOK']]))
			{
				$data[$row['HOOK']] = array();
			}
			$data[$row['HOOK']][$row['CODE']] = $asIs ? $row : $row['VALUE'];
		}

		return $data;
	}

	/**
	 * Get available hooks for this landing.
	 * @param int $id Entity id.
	 * @param string $type Entity type.
	 * @param array $data Data array (optional).
	 * @return array
	 */
	protected static function getList($id, $type, array $data = array())
	{
		$hooks = array();
		$classDir = self::HOOKS_PAGE_DIR;
		$classNamespace = self::HOOKS_NAMESPACE;

		// first read all hooks in base dir
		foreach (self::getClassesFromDir($classDir) as $class)
		{
			$classFull = __NAMESPACE__  . $classNamespace . $class;
			if (class_exists($classFull))
			{
				$hooks[$class] = new $classFull(self::$editMode);
			}
		}

		// sort hooks
		uasort($hooks, function($a, $b)
		{
			if ($a->getSort() == $b->getSort())
			{
				return 0;
			}
			return ($a->getSort() < $b->getSort()) ? -1 : 1;
		});

		// then fill hook with data
		if (!empty($hooks) && $id > 0)
		{
			if (empty($data))
			{
				$data = self::getData($id, $type);
			}
			foreach ($hooks as $code => $hook)
			{
				if (isset($data[$code]))
				{
					$hook->setData($data[$code]);
				}
			}
		}

		return $hooks;
	}

	/**
	 * Set edit mode to true.
	 * @return void
	 */
	public static function setEditMode()
	{
		self::$editMode = true;
	}

	/**
	 * Get hooks for site.
	 * @param int $id Site id.
	 * @return array
	 */
	public static function getForSite($id)
	{
		return self::getList($id, self::ENTITY_TYPE_SITE);
	}

	/**
	 * Get hooks for landing.
	 * @param int $id Landing id.
	 * @return array
	 */
	public static function getForLanding($id)
	{
		return self::getList($id, self::ENTITY_TYPE_LANDING);
	}

	/**
	 * Prepare data for save in hooks.
	 * @param array $data Input data.
	 * @return array
	 */
	protected static function prepareData(array $data)
	{
		$newData = array();

		foreach ($data as $code => $val)
		{
			if (strpos($code, '_') !== false)
			{
				$codeHook = substr($code, 0, strpos($code, '_'));
				$codeVal = substr($code, strpos($code, '_') + 1);
				if (!isset($newData[$codeHook]))
				{
					$newData[$codeHook] = array();
				}
				$newData[$codeHook][$codeVal] = $val;
			}
		}

		return $newData;
	}

	/**
	 * Set data hooks for entity.
	 * @param int $id Entity id.
	 * @param string $type Entity type.
	 * @param array $data Data array.
	 * @return void
	 */
	protected static function saveData($id, $type, array $data)
	{
		$data = self::prepareData($data);
		$hooks = self::getList($id, $type, $data);
		$dataSave = self::getData($id, $type, true);

		// get hooks with new new data (not saved yet)
		foreach ($hooks as $hook)
		{
			$codeHook = $hook->getCode();
			// modify $dataSave ...
			foreach ($hook->getFields() as $field)
			{
				$codeVal = $field->getCode();
				if (!isset($data[$codeHook][$codeVal]))
				{
					continue;
				}
				// ... for changed
				if (isset($dataSave[$codeHook][$codeVal]))
				{
					$dataSave[$codeHook][$codeVal]['CHANGED'] = true;
					$dataSave[$codeHook][$codeVal]['VALUE'] = $field->getValue();
				}
				// ... and new fields
				else
				{
					if (!isset($dataSave[$codeHook]))
					{
						$dataSave[$codeHook] = array();
					}
					$dataSave[$codeHook][$codeVal] = array(
						'HOOK' => $codeHook,
						'CODE' => $codeVal,
						'VALUE' => $field->getValue()
					);
				}
			}
		}

		// now save the data
		foreach ($dataSave as $codeHook => $dataHook)
		{
			foreach ($dataHook as $code => $row)
			{
				if (trim($row['VALUE']) == '')
				{
					if (isset($row['ID']))
					{
						HookData::delete($row['ID']);
					}
				}
				else
				{
					if (!isset($row['ID']))
					{
						$row['ENTITY_ID'] = $id;
						$row['ENTITY_TYPE'] = $type;
						HookData::add($row);
					}
					elseif (isset($row['CHANGED']) && $row['CHANGED'])
					{
						unset($row['CHANGED']);
						HookData::update($row['ID'], $row);
					}
				}
			}
		}
	}

	/**
	 * Set data hooks for site.
	 * @param int $id Site id.
	 * @param array $data Data array.
	 * @return void
	 */
	public static function saveForSite($id, array $data)
	{
		self::saveData($id, self::ENTITY_TYPE_SITE, $data);
	}

	/**
	 * Get hooks for landing.
	 * @param int $id Landing id.
	 * @param array $data Data array.
	 * @return void
	 */
	public static function saveForLanding($id, array $data)
	{
		self::saveData($id, self::ENTITY_TYPE_LANDING, $data);
	}

	/**
	 * Delete data hooks for entity.
	 * @param int $id Entity id.
	 * @param string $type Entity type.
	 * @return void
	 */
	protected static function deleteData($id, $type)
	{
		foreach (self::getData($id, $type, true) as $row)
		{
			$res = HookData::getList(array(
				'select' => array(
					'ID'
				),
				'filter' => array(
					'ENTITY_ID' => $id,
					'=ENTITY_TYPE' => $type
				)
			));
			while ($row = $res->fetch())
			{
				HookData::delete($row['ID']);
			}
		}
	}

	/**
	 * Delete data hooks for site.
	 * @param int $id Landing id.
	 * @return void
	 */
	public static function deleteForSite($id)
	{
		self::deleteData($id, self::ENTITY_TYPE_SITE);
	}

	/**
	 * Delete data hooks for landing.
	 * @param int $id Landing id.
	 * @return void
	 */
	public static function deleteForLanding($id)
	{
		self::deleteData($id, self::ENTITY_TYPE_LANDING);
	}
}