Your IP : 3.133.143.183


Current Path : /home/bitrix/ext_www/rk_shared_core/bitrix/modules/sale/lib/location/admin/
Upload File :
Current File : /home/bitrix/ext_www/rk_shared_core/bitrix/modules/sale/lib/location/admin/locationhelper.php

<?
/**
 * This class is for internal use only, not a part of public API.
 * It can be changed at any time without notification.
 *
 * @access private
 */

namespace Bitrix\Sale\Location\Admin;

use Bitrix\Main;
use Bitrix\Main\Localization\Loc;
use Bitrix\Sale\Location;

Loc::loadMessages(__FILE__);

final class LocationHelper extends NameHelper
{
	const LIST_PAGE_URL = 'sale_location_node_list.php';
	const EDIT_PAGE_URL = 'sale_location_node_edit.php';

	const MENU_MAX_ITEMS_IN = 100;
	const MENU_LOCATION_PARENT_TAG = 'menu_sale_location_tree';

	const MENU_ITEMS_QUERY_STRING_TAG = 'menu_sale_location_tree';
	const MENU_ITEMS_QUERY_STRING_DELIMITER = ':';

	const URL_PARAM_PARENT_ID = 'find_PARENT_ID';
	const URL_PARAM_ID = 'id';

	#####################################
	#### Entity settings
	#####################################

	/**
	* Function returns instructions from where and which columns we take to show in UI
	* @return string Entity class name
	*/
	public function getEntityRoadMap()
	{
		return array(
			'main' => array(
				'name' => 'Bitrix\Sale\Location\Location',
				'pages' => array(
					'list' => array(
						//'excludedColumns' => array('PARENT_ID')
					),
					'detail' => array(
						'excludedColumns' => array()
					),
				)
			),
			'name' => array(
				'name' => 'Bitrix\Sale\Location\Name\Location',
				'pages' => array(
					'list' => array(
						'includedColumns' => array('NAME', 'SHORT_NAME')
					),
					'detail' => array(
						'includedColumns' => array('NAME', 'SHORT_NAME')
					)
				)
			),
			'external' => array(
				'name' => 'Bitrix\Sale\Location\External',
				'pages' => array(
					'detail' => array(
						'includedColumns' => array('ID', 'XML_ID', 'SERVICE_ID')
					)
				)
			),
		);
	}

	##############################################
	##############################################
	##############################################

	public static function getFilterColumns()
	{
		$columns = static::getColumns('list');
		foreach($columns as $code => &$col)
		{
			$col['DEFAULT'] = in_array($code, array('ID', 'TYPE_ID', 'NAME_'.ToUpper(LANGUAGE_ID), 'SORT'));
		}

		return $columns;
	}

	public static function getListGridColumns()
	{
		$columns = static::getFilterColumns();
		unset($columns['PARENT_ID']);

		return $columns;
	}

	// generalized filter to orm filter proxy
	public static function getParametersForList($proxed)
	{
		$parameters = parent::getParametersForList($proxed);

		if(isset($parameters['order']['TYPE_ID'])) // sorting by TYPE_ID, being set, should work in different way
		{
			$parameters['order']['TYPE.SORT'] = $parameters['order']['TYPE_ID'];
			unset($parameters['order']['TYPE_ID']);
		}

		return $parameters;
	}

	public static function getFormData($id)
	{
		$formData = parent::getFormData($id);

		// external data as a separate independent table
		$formData = array_merge($formData, static::getExternalData($id));

		return $formData;
	}

	##############################################
	##############################################
	##############################################

	// high-level validators used when accepting data typed in form. There can be some misspelling, etc, so additional buisness-logic required
	public static function validateUpdateRequest($data)
	{
		$errors = parent::validateUpdateRequest($data);

		// if type is set in data and not empty, it must exist
		$typeError = false;
		if(intval($data['TYPE_ID']))
		{
			$type = Location\TypeTable::getList(array('select' => array('ID'), 'filter' => array('=ID' => intval($data['TYPE_ID']))))->fetch();

			if(!$type)
				$typeError = true;
		}
		else
			$typeError = true;

		if($typeError)
			$errors[] = Loc::getMessage('SALE_LOCATION_ADMIN_LOCATION_HELPER_ENTITY_TYPE_ID_UNKNOWN_ERROR');

		// formally check service ids in EXTERNAL parameter
		if(is_array($data['EXTERNAL']) && !empty($data['EXTERNAL']))
		{
			$services = self::getExternalServicesList();

			foreach($data['EXTERNAL'] as $external)
			{
				if(!isset($services[$external['SERVICE_ID']]))
				{
					$errors[] = Loc::getMessage('SALE_LOCATION_ADMIN_LOCATION_HELPER_ENTITY_UNKNOWN_EXTERNAL_SERVICE_ID_ERROR');
					break;
				}
			}
		}

		if(is_array($data['NAME']) && !empty($data['NAME']))
		{
			$hasValidName = false;

			foreach($data['NAME'] as $lang => $fields)
			{
				if(!empty($fields['NAME']))
				{
					$hasValidName = true;
					break;
				}
			}

			if(!$hasValidName)
			{
				$errors[] = Loc::getMessage('SALE_LOCATION_ADMIN_LOCATION_HELPER_ENTITY_NAME_EMPTY_ERROR');
			}
		}

		return $errors;
	}

	public static function proxyUpdateRequest($data)
	{
		$externals = $data['EXTERNAL'];
		unset($data['EXTERNAL']);

		if(is_array($externals) && !empty($externals))
		{
			foreach($externals as $eId => $external)
			{
				if(!strlen($external['XML_ID']))
					unset($externals[$eId]);
			}
		}

		$data = parent::proxyUpdateRequest($data);

		if(!empty($externals))
			$data['EXTERNAL'] = $externals;

		return $data;
	}

	public static function proxyListRequest($page = 'list')
	{
		$parameters = parent::proxyListRequest($page);

		if($page == 'list') // filter by parent_id in list
		{
			if(!isset($parameters['filter']['=PARENT_ID'])) // value has not came from filter
			{
				if(isset($_REQUEST['find_PARENT_ID']))
					$parameters['filter']['=PARENT_ID'] = intval($_REQUEST['find_PARENT_ID']);
				//else
				//	$parameters['filter']['=PARENT_ID'] = 0;
			}
		}

		if(isset($parameters['order']['TYPE_ID'])) // sorting by TYPE_ID, being set, should work in different way
		{
			$parameters['order']['TYPE.SORT'] = $parameters['order']['TYPE_ID'];
			unset($parameters['order']['TYPE_ID']);
		}

		return $parameters;
	}

	// crud over entity: update
	public static function update($primary, $data, $batch = false)
	{
		$success = true;
		$entityClass = static::getEntityClass();

		$data = static::convertToArray($data);
		$data = static::proxyUpdateRequest($data);
		$errors = static::validateUpdateRequest($data);

		if(empty($errors))
		{
			$res = $entityClass::update($primary, $data, array('RESET_LEGACY' => !$batch));
			if(!$res->isSuccess())
			{
				$success = false;
				$errors = $res->getErrorMessages();
			}
		}
		else
			$success = false;

		return array(
			'success' => $success,
			'errors' => $errors
		);
	}

	// crud over entity: delete
	public static function delete($primary, $batch = false)
	{
		$success = true;
		$errors = array();
		$entityClass = static::getEntityClass();

		$res = $entityClass::deleteExtended($primary, array('RESET_LEGACY' => !$batch));
		if(!$res->isSuccess())
		{
			$success = false;
			$errors = $res->getErrorMessages();
		}

		return array(
			'success' => $success,
			'errors' => $errors
		);
	}

	#####################################
	#### Entity-specific
	#####################################

	public static function checkFirstImportDone()
	{
		return \Bitrix\Main\Config\Option::get('sale', 'sale_locationpro_import_performed', '') == 'Y';
	}

	public static function getParentId($id)
	{
		if(!($id = intval($id)))
			return 0;

		$class = static::getEntityClass('main');
		$item = $class::getList(array(
			'filter' => array('=ID' => $id),
			'select' => array('PARENT_ID')
		))->fetch();

		return $item['PARENT_ID'];
	}

	public static function getExternalData($id)
	{
		$res = Location\LocationTable::getExternalData($id);
		$result = array();
		while($item = $res->Fetch())
			$result['EXTERNAL'][$item['ID']] = $item;

		return $result;
	}

	public static function getExternalServicesList()
	{
		static $services;

		if($services == null)
		{
			$res = Location\ExternalServiceTable::getList();
			$services = array();
			while($item = $res->Fetch())
				$services[$item['ID']] = $item;
		}

		return $services;
	}

	/**
	 * @deprecated
	 * 
	 * Use TypeHelper::getTypes() instead
	 */
	public static function getTypeList()
	{
		static $types;

		if($types == null)
		{
			$types = array();
			$typesWithNames = Location\Admin\TypeHelper::getTypes();
			foreach($typesWithNames as $type)
			{
				$types[intval($type['ID'])] = $type['NAME_CURRENT'];
			}
		}

		return $types;
	}

	public static function getExternalMap()
	{
		return static::readMap('external', 'detail');
	}

	public static function checkRequestIsMenuRequest()
	{
		return strpos($_REQUEST['admin_mnu_menu_id'], self::MENU_ITEMS_QUERY_STRING_TAG) !== false;
	}

	public static function getLocationSubMenu()
	{
		// how it works: every time when we call for the next sub-level, we must 
		// obtain not sublevel itself, but a whole parent-tree of it

		$queryParams = self::unPackItemsQueryString();

		$requiredToShow = false;
		// three situations:
		// 1) node id comes in $_REQUEST['admin_mnu_menu_id'] parameter when user walks along left menu tree
		$id = false;
		if(self::checkRequestIsMenuRequest())
		{
			$requiredToShow = true;
			$id = $queryParams['ID'];
		}
		if(!$id)
		{
			// 2) node id comes in $_REQUEST['id'] or in $_REQUEST['parent_id'] when user enters self::LIST_PAGE_URL or self::EDIT_PAGE_URL page
			$page = $GLOBALS['APPLICATION']->GetCurPage();
			if($page == '/bitrix/admin/'.self::LIST_PAGE_URL || $page == '/bitrix/admin/'.self::EDIT_PAGE_URL)
			{
				$requiredToShow = true;

				/*
				if(intval($_REQUEST['id']))
					$id = intval($_REQUEST['id']);
				*/
				if(intval($_REQUEST['find_PARENT_ID']))
					$id = intval($_REQUEST['find_PARENT_ID']);
				elseif(intval($_REQUEST['parent_id']))
					$id = intval($_REQUEST['parent_id']);
			}
		}
		// 3) there is no node id at all

		$tree = array();
		if($requiredToShow)
		{
			$parameters = array(
				'select' => array(
					'ID', 
					'LOCATION_NAME' => 'NAME.NAME',
					'DEPTH_LEVEL',
					'PARENT_ID',
					'CHILD_CNT'
				),
				'filter' => array(
					'=NAME.LANGUAGE_ID' => LANGUAGE_ID
				),
				'order' => array(
					'LOCATION_NAME' => 'asc' // result always come sorted by LEFT_MARGIN, we must resort it by NAME
				)
			);

			if($id)
			{
				try
				{
					$res = Location\LocationTable::getParentTree($id, $parameters, array('SHOW_CHILDREN' => true));
				}
				catch(Main\SystemException $e)
				{
					return array();
				}
			}
			else
			{
				$res = Location\LocationTable::getChildren(false, $parameters);
			}

			$index = array();
			while($item = $res->Fetch())
			{
				$index[$item['PARENT_ID']][$item['ID']] = array(
					'NAME' => htmlspecialcharsbx($item['LOCATION_NAME']),
					'PARENT_ID' => intval($item['PARENT_ID']),
					'CHILD_CNT' => intval($item['CHILD_CNT'])
				);
			}

			unset($res);
			unset($item);

			self::appendMenuChildren($tree, 0, $index, $queryParams);
		}

		return $tree;
	}

	// transcendental thing that makes location menu work
	public static function packItemsQueryString($parameters = array())
	{
		$inRequest = self::unPackItemsQueryString();

		$query = array(self::MENU_ITEMS_QUERY_STRING_TAG, intval($parameters['ID']));
		if(isset($parameters['LIMIT'])) // limit taken from the argument
			$query[] = intval($parameters['LIMIT']);
		else
		{
			if(self::checkRequestIsMenuRequest() && isset($inRequest['LIMIT'])) // limit taken from request
				$query[] = intval($inRequest['LIMIT']);
			else // limit taken by default
				$query[] = self::MENU_MAX_ITEMS_IN;
		}

		if(isset($parameters['SHOW_CHECKBOX']))
			$query[] = $parameters['SHOW_CHECKBOX'] ? '1' : '0';
		else
		{
			if(self::checkRequestIsMenuRequest() && isset($inRequest['SHOW_CHECKBOX']))
				$query[] = $inRequest['SHOW_CHECKBOX'] ? '1' : '0';
			else
				$query[] = '0';
		}

		return implode(self::MENU_ITEMS_QUERY_STRING_DELIMITER, $query);
	}

	public static function unPackItemsQueryString()
	{
		$path = explode(self::MENU_ITEMS_QUERY_STRING_DELIMITER, $_REQUEST['admin_mnu_menu_id']);

		return array(
			'ID' => intval($path[1]) ? intval($path[1]) : false,
			'LIMIT' => intval($path[2]),
			'SHOW_CHECKBOX' => !!$path[3]
		);
	}

	public static function getListUrl($parent = false, $parameters = array())
	{
		if(!is_array($parameters))
			$parameters = array();

		if($parent !== false)
		{
			//$parameters['filter'] = 'Y';
			//$parameters['set_filter'] = 'Y';
			$parameters[static::URL_PARAM_PARENT_ID] = intval($parent);
			//$parameters['adm_filter_applied'] = '0';
		}

		return parent::getListUrl($parameters);
	}

	public static function getEditUrl($node = false, $parameters = array())
	{
		if(!is_array($parameters))
			$parameters = array();

		if($node != false)
			$parameters[static::URL_PARAM_ID] = $node;

		return self::getUrl(static::EDIT_PAGE_URL, $parameters);
	}

	public static function appendMenuChildren(&$attachTo, $attachWhat, $index, $queryParams)
	{
		$i = 0;
		$overflow = false;
		$inChain = false;
		$limit = self::MENU_MAX_ITEMS_IN; // set always limited to self::MENU_MAX_ITEMS_IN (originally was intval($queryParams['LIMIT']));

		if(empty($index))
			return;

		if(is_array($index[$attachWhat]))
		{
			foreach($index[$attachWhat] as $id => $item)
			{
				if($limit && (!$overflow && $i >= $limit) || ($overflow && $inChain/* the previous item was significant */))
				{
					$overflow = true;

					$attachTo[] =  array(
						"text" => Loc::getMessage("SALE_MENU_LOCATION_THE_REST_OF"),
						"url" => static::getListUrl(intval($item['PARENT_ID'])),
						"module_id" => "sale",
						"parent_menu" => self::packItemsQueryString(array('ID' => $item['PARENT_ID'], 'LIMIT' => $limit, 'SHOW_CHECKBOX' => $queryParams['SHOW_CHECKBOX'])),
					);
				}

				$inChain = isset($index[$id]); // this is important node - it belongs to the chain being displayed

				if(!$overflow || $inChain)
				{
					$node = array(
						"text" => ($queryParams['SHOW_CHECKBOX'] ? '<input type="checkbox" value="'.intval($id).'" />&nbsp;' : '').$item['NAME'],
						"fav_id" => intval($id), // allows javascript to know what item it is
						"url" => static::getListUrl(intval($id)),
						"module_id" => "sale",
						"items_id" => self::packItemsQueryString(array('ID' => $id, 'LIMIT' => $limit, 'SHOW_CHECKBOX' => $queryParams['SHOW_CHECKBOX'])),
						//"skip_chain" => true, // uncomment, if you dont want this menu item figure in breadcrumbs
						"parent_menu" => self::packItemsQueryString(array('ID' => $item['PARENT_ID'], 'LIMIT' => $limit, 'SHOW_CHECKBOX' => $queryParams['SHOW_CHECKBOX'])),
						"more_url" => array( // additional route, which will be treated as an alias when calculating selected menu path
							self::getEditUrl(intval($id)), // when editing existed node
							self::getEditUrl(false, array('parent_id' => intval($id))) // when adding a new node
						)
					);

					if($item['CHILD_CNT'])
					{
						$node['dynamic'] = true;
						$node['items'] = array();

						if($inChain)
							self::appendMenuChildren($node['items'], $id, $index, $queryParams);
					}

					$attachTo[] = $node;

				}
				$i++;
			}
		}
	}

	public static function getLocationStringById($primary, $behaviour = array('INVERSE' => false, 'DELIMITER' => ', ', 'LANGUAGE_ID' => LANGUAGE_ID))
	{
		return static::getLocationStringByCondition(array('=ID' => $primary), $behaviour);
	}

	public static function getLocationStringByCode($primary, $behaviour = array('INVERSE' => false, 'DELIMITER' => ', ', 'LANGUAGE_ID' => LANGUAGE_ID))
	{
		return static::getLocationStringByCondition(array('=CODE' => $primary), $behaviour);
	}

	protected static function getLocationStringByCondition($condition, $behaviour = array('INVERSE' => false, 'DELIMITER' => ', ', 'LANGUAGE_ID' => LANGUAGE_ID))
	{
		if(isset($behaviour) && !is_array($behaviour))
			$behaviour = array();

		if(!isset($behaviour['DELIMITER']))
			$behaviour['DELIMITER'] = ', ';

		if(!isset($behaviour['LANGUAGE_ID']))
			$behaviour['LANGUAGE_ID'] = LANGUAGE_ID;

		try
		{
			$res = Location\LocationTable::getPathToNodeByCondition($condition, array('select' => array('LNAME' => 'NAME.NAME'), 'filter' => array('=NAME.LANGUAGE_ID' => $behaviour['LANGUAGE_ID'])));
			$path = array();
			while($item = $res->fetch())
			{
				$path[] = $item['LNAME'];
			}

			if($behaviour['INVERSE'])
				$path = array_reverse($path);

			return implode($behaviour['DELIMITER'], $path);
		}
		catch(\Bitrix\Main\SystemException $e)
		{
			return '';
		}
	}

	public static function getLocationsByZip($zip, $parameters = array())
	{
		$zip = trim($zip);

		if(!strlen($zip) || !preg_match('#^\d+$#', $zip))
			throw new Main\SystemException('Empty or incorrect zip code passed');

		if(!is_array($parameters))
			$parameters = array();

		$parameters['filter'][] = array(
			'LOGIC' => 'OR',
			array('=SERVICE.CODE' => 'ZIP'),
			array('=SERVICE.CODE' => 'ZIP_LOWER')
		);

		$parameters['filter']['=XML_ID'] = $zip;
		$parameters['order']['SERVICE_CODE'] = 'ASC';
		$parameters['select'][] = '*';
		$parameters['select']['SERVICE_CODE'] = 'SERVICE.CODE';

		return \Bitrix\Sale\Location\ExternalTable::getList($parameters);
	}

	public static function getZipByLocation($locationCode, $parameters = array())
	{
		if(strlen($locationCode) <= 0)
			return new \Bitrix\Main\DB\ArrayResult(array());

		if(!is_array($parameters))
			$parameters = array();

		$parameters['filter'][] = array(
			'LOGIC' => 'OR',
			array('=SERVICE.CODE' => 'ZIP'),
			array('=SERVICE.CODE' => 'ZIP_LOWER')
		);
		$parameters['order']['SERVICE_CODE'] = 'ASC';
		$parameters['filter']['=LOCATION.CODE'] = $locationCode;
		$parameters['select'][] = '*';
		$parameters['select']['SERVICE_CODE'] = 'SERVICE.CODE';

		return \Bitrix\Sale\Location\ExternalTable::getList($parameters);
	}

	public static function checkLocationMigrated()
	{
		return Main\Config\Option::get('sale', 'sale_locationpro_migrated', '') == 'Y';
	}

	// checks if new location enabled or not
	public static function checkLocationEnabled()
	{
		return static::checkLocationMigrated();
	}

	// informers
	public static function informAdminLocationDatabaseFailure()
	{
		static::deleteInformer('SALE_LOCATIONPRO_DATABASE_FAILURE');

		$fields = array(
			"MESSAGE" => Loc::getMessage('SALE_LOCATION_ADMIN_LOCATION_HELPER_DATABASE_FAILURE', array(
				'#ANCHOR_IMPORT_URL#' => '<a target="_blank" href="'.static::getImportUrl().'">',
				'#ANCHOR_END#' => '</a>'
			)),
			"TAG" => 'SALE_LOCATIONPRO_DATABASE_FAILURE',
			"MODULE_ID" => "sale",
			"ENABLE_CLOSE" => "Y",
			"PUBLIC_SECTION" => "N"
		);
		\CAdminNotify::Add($fields);
	}
	public static function deleteInformer($informerTag)
	{
		if((string) $informerTag == '')
			return;

		$rsAdminNotify = \CAdminNotify::GetList(array(), array('MODULE_ID'=>'sale', 'TAG' => $informerTag));
		if ($arAdminNotify = $rsAdminNotify->Fetch())
		{
			\CAdminNotify::DeleteByTag($informerTag);
		}
	}

	/**
	 * @deprecated
	 */
	public static function getLocationPathDisplay($primary)
	{
		if(!strlen($primary))
			return '';

		if((string) $primary === (string) intval($primary))
			return static::getLocationStringById($primary);
		else
			return static::getLocationStringByCode($primary);
	}
}