403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/cvetdv.ru/bitrix/modules/catalog/lib/controller/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/cvetdv.ru/bitrix/modules/catalog/lib/controller/price.php
<?php

namespace Bitrix\Catalog\Controller;

use Bitrix\Catalog\Access\ActionDictionary;
use Bitrix\Catalog\PriceTable;
use Bitrix\Main\Error;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Result;
use Bitrix\Rest\Event\EventBindInterface;
use Bitrix\Catalog\GroupTable;
use Bitrix\Catalog\Config\Feature;

final class Price extends Controller implements EventBindInterface
{
	use ListAction; // default listAction realization
	use GetAction; // default getAction realization
	use CheckExists; // default implementation of existence check

	//region Actions
	/**
	 * @return array
	 */
	public function getFieldsAction(): array
	{
		return [$this->getServiceItemName() => $this->getViewFields()];
	}

	/**
	 * public function listAction
	 * @see ListAction::listAction
	 */

	/**
	 * public function getAction
	 * @see GetAction::getAction
	 */

	/**
	 * Update all product prices.
	 *
	 * @param array $fields
	 * @return array|null
	 */
	public function modifyAction(array $fields): ?array
	{
		if (!is_array($fields['PRODUCT']['PRICES']))
		{
			$this->addError(new Error('Product prices are empty'));

			return null;
		}

		$r = $this->modifyValidate($fields['PRODUCT']['PRICES']);

		if ($r->isSuccess())
		{
			$r = $this->modifyBefore($fields);
			if($r->isSuccess())
			{
				$r = $this->modify($fields);
			}
		}

		if (!$r->isSuccess())
		{
			$this->addErrors($r->getErrors());

			return null;
		}

		$ids = $r->getData()[0];
		$entityTable = $this->getEntityTable();

		return [
			'PRICES' =>
				$entityTable::getList(
					['filter' => ['=ID' => $ids]]
				)
				->fetchAll()
		];
	}

	/**
	 * @param int $id
	 * @return bool|null
	 */
	public function deleteAction(int $id): ?bool
	{
		$r = $this->exists($id);
		if ($r->isSuccess())
		{
			$r = $this->deleteValidate($id);
			if ($r->isSuccess())
			{
				$r = \Bitrix\Catalog\Model\Price::delete($id);
			}
		}

		if (!$r->isSuccess())
		{
			$this->addErrors($r->getErrors());

			return null;
		}

		return true;
	}

	/**
	 * @param int $id
	 * @param array $fields
	 * @return array|null
	 */
	public function updateAction(int $id, array $fields): ?array
	{
		$price = $this->get($id);
		if (!$price)
		{
			$this->addError(new Error('Price is not exists'));

			return null;
		}

		$fields = array_merge($price, $fields);
		return $this->modifySingleProductPrice($fields);
	}

	/**
	 * @param array $fields
	 * @return array|null
	 */
	public function addAction(array $fields): ?array
	{
		unset($fields['ID']);

		return $this->modifySingleProductPrice($fields);
	}
	//endregion

	private function modifySingleProductPrice(array $fields): ?array
	{
		$resultGroupType = GroupTable::getRowById((int)$fields['CATALOG_GROUP_ID']);
		if (!$resultGroupType)
		{
			$this->addError(new Error('Validate price error. Catalog price group is wrong'));

			return null;
		}

		$entityTable = $this->getEntityTable();
		$prices =
			$entityTable::getList(
				[
					'filter' => [
						'=PRODUCT_ID' => $fields['PRODUCT_ID'],
						'=CATALOG_GROUP_ID' => $fields['CATALOG_GROUP_ID'],
					]
				]
			)
			->fetchAll()
		;

		$prices = array_combine(array_column($prices, 'ID'), $prices);
		$prices[$fields['ID']] = $fields;

		$r = $this->modifyValidate($prices);
		if ($r->isSuccess())
		{
			$r = $this->modify([
				'PRODUCT' => [
					'ID' => $fields['PRODUCT_ID'],
					'PRICES' => [$fields]
				]
			]);
		}

		if (!$r->isSuccess())
		{
			$this->addErrors($r->getErrors());
			return null;
		}

		$ids = $r->getData()[0];

		return [
			$this->getServiceItemName() => $this->get($ids[0])
		];
	}

	protected function modify($fields)
	{
		$ids = [];
		$productId = $fields['PRODUCT']['ID'];
		$prices = $fields['PRODUCT']['PRICES'];

		$r = $this->checkPermissionIBlockElementPriceModify($productId);
		if($r->isSuccess())
		{
			foreach ($prices as $price)
			{
				if(isset($price['ID']))
				{
					self::normalizeFields($price);

					$result = \Bitrix\Catalog\Model\Price::update($price['ID'], $price);
					if($result->isSuccess())
					{
						$ids[] = $price['ID'];
					}
				}
				else
				{
					$result = \Bitrix\Catalog\Model\Price::add([
						'PRODUCT_ID' => $productId,
						'CATALOG_GROUP_ID' => $price['CATALOG_GROUP_ID'],
						'CURRENCY' => $price['CURRENCY'],
						'PRICE' => $price['PRICE'],
						'QUANTITY_FROM' => isset($price['QUANTITY_FROM']) ? $price['QUANTITY_FROM']:null,
						'QUANTITY_TO' => isset($price['QUANTITY_TO']) ? $price['QUANTITY_TO']:null,
						'EXTRA_ID' => isset($price['EXTRA_ID']) ? $price['EXTRA_ID']:null,
					]);

					if($result->isSuccess())
					{
						$ids[] = $result->getId();
					}
				}

				if($result->isSuccess() == false)
				{
					$r->addErrors($result->getErrors());
				}
			}

			if($r->isSuccess())
				$r->setData([$ids]);
		}

		return $r;
	}

	protected function modifyBefore($fields)
	{
		$productId = $fields['PRODUCT']['ID'];

		$ids = [];
		$prices = $fields['PRODUCT']['PRICES'];
		foreach ($prices as $price)
		{
			$ids[]=$price['ID'];
		}

		$entityTable = $this->getEntityTable();

		$res = $entityTable::getList(['filter'=>['PRODUCT_ID'=>$productId]]);
		while ($item = $res->fetch())
		{
			if(in_array($item['ID'], $ids) == false)
			{
				$entityTable::delete($item['ID']);
			}
		}

		return new Result();
	}

	private static function normalizeFields(array &$fields)
	{
		if (isset($fields['QUANTITY_FROM']))
		{
			if (is_string($fields['QUANTITY_FROM']) && $fields['QUANTITY_FROM'] === '')
				$fields['QUANTITY_FROM'] = null;
			elseif ($fields['QUANTITY_FROM'] === false || $fields['QUANTITY_FROM'] === 0)
				$fields['QUANTITY_FROM'] = null;
		}
		else
		{
			$fields['QUANTITY_FROM'] = null;
		}

		if (isset($fields['QUANTITY_TO']))
		{
			if (is_string($fields['QUANTITY_TO']) && $fields['QUANTITY_TO'] === '')
				$fields['QUANTITY_TO'] = null;
			elseif ($fields['QUANTITY_TO'] === false || $fields['QUANTITY_TO'] === 0)
				$fields['QUANTITY_TO'] = null;
		}
		else
		{
			$fields['QUANTITY_TO'] = null;
		}

		if (isset($fields['EXTRA_ID']))
		{
			if (is_string($fields['EXTRA_ID']) && $fields['EXTRA_ID'] === '')
				$fields['EXTRA_ID'] = null;
			elseif ($fields['EXTRA_ID'] === false)
				$fields['EXTRA_ID'] = null;
		}
		else
		{
			$fields['EXTRA_ID'] = null;
		}
	}

	private function modifyValidate(array $items): Result
	{
		$r = new Result();
		$items = array_values($items);
		$basePriceType = GroupTable::getBasePriceType();
		$basePriceTypeId = $basePriceType['ID'];
		$groupTypes = GroupTable::getTypeList();
		$sortedByType = [];
		$extendPrices = false;
		foreach ($items as $fields)
		{
			$groupId = (int)$fields['CATALOG_GROUP_ID'];
			if (!isset($groupTypes[$groupId]))
			{
				$r->addError(new Error('Validate price error. Catalog price group is wrong'));

				return $r;
			}

			if (!$extendPrices)
			{
				$extendPrices = (isset($fields['QUANTITY_FROM']) || isset($fields['QUANTITY_TO']));
			}
			$sortedByType[$groupId][] = $fields;
		}

		$allowEmptyRange = Option::get('catalog', 'save_product_with_empty_price_range') === 'Y';
		$enableQuantityRanges = Feature::isPriceQuantityRangesEnabled();

		if (!$extendPrices)
		{
			if (count($items) > count($sortedByType))
			{
				$r->addError(new Error('Validate price error. Catalog product is allowed has only single price without ranges in price group.'));
			}

			return $r;
		}

		if ($enableQuantityRanges === false)
		{
			$r->addError(new Error('Validate price error. Price quantity ranges disabled'));

			return $r;
		}

		$basePrices = $sortedByType[$basePriceTypeId];
		if (!$basePrices)
		{
			$r->addError(new Error('Validate price error. Ranges of base price are not equal to another price group range'));

			return $r;
		}

		$basePrices = $this->sortPriceRanges($basePrices);

		foreach ($sortedByType as $typeId => $prices)
		{
			$count = count($prices);
			$prices = $this->sortPriceRanges($prices);

			foreach ($prices as $i => $item)
			{
				$quantityFrom = (float)$item['QUANTITY_FROM'];
				$quantityTo = (float)$item['QUANTITY_TO'];

				if (
					$typeId !== $basePriceTypeId
					&& (
						!isset($basePrices[$i])
						|| $quantityFrom !== (float)$basePrices[$i]['QUANTITY_FROM']
						|| $quantityTo !== (float)$basePrices[$i]['QUANTITY_TO']
					)
				)
				{
					$r->addError(
						new Error(
							'Validate price error. Ranges of base price are not equal to another price group range'
						)
					);

					return $r;
				}

				if (
					($i !== 0 && $quantityFrom <= 0)
					|| ($i === 0 && $quantityFrom < 0)
				)
				{
					$r->addError(
						new Error(
							"Quantity bounds error: lower bound {$quantityFrom} must be above zero (for the first range)"
						)
					);
				}

				if (
					($i !== $count-1 && $quantityTo <= 0)
					|| ($i === $count-1 && $quantityTo < 0)
				)
				{
					$r->addError(
						new Error(
							"Quantity bounds error: higher bound {$quantityTo} must be above zero (for the last range)"
						)
					);

				}

				if ($quantityFrom > $quantityTo	&& ($i !== $count-1 || $quantityTo > 0))
				{
					$r->addError(
						new Error(
							"Quantity bounds error: range {$quantityFrom}-{$quantityTo} is incorrect"
						)
					);
				}

				$nextQuantityFrom = (float)$prices[$i + 1]["QUANTITY_FROM"];
				$nextQuantityTo = (float)$prices[$i + 1]["QUANTITY_TO"];
				if ($i < $count-1 && $quantityTo >= $nextQuantityFrom)
				{
					$r->addError(
						new Error(
							"Quantity bounds error: ranges {$quantityFrom}-{$quantityTo} and {$nextQuantityFrom}-{$nextQuantityTo} overlap"
						)
					);
				}

				if (
					$i < $count-1
					&& $nextQuantityFrom - $quantityTo > 1
					&& !$allowEmptyRange
				)
				{
					$validRangeFrom = $quantityTo + 1;
					$validRangeTo = $nextQuantityFrom - 1;

					$r->addError(
						new Error(
							"Invalid quantity range entry: no price is specified for range {$validRangeFrom}-{$validRangeTo})"
						)
					);
				}

				if ($i >= $count-1 && $quantityTo > 0)
				{
					$r->addError(
						new Error(
							"Invalid quantity range entry: no price is specified for quantity over {$quantityTo}"
						)
					);
				}
			}
		}

		return $r;
	}

	private function sortPriceRanges(array $prices): array
	{
		$count = count($prices);

		for ($i = 0; $i < $count - 1; $i++)
		{
			for ($j = $i + 1; $j < $count; $j++)
			{
				if ($prices[$i]["QUANTITY_FROM"] > $prices[$j]["QUANTITY_FROM"])
				{
					$tmp = $prices[$i];
					$prices[$i] = $prices[$j];
					$prices[$j] = $tmp;
				}
			}
		}

		return $prices;
	}

	protected function getEntityTable()
	{
		return new PriceTable();
	}

	protected function deleteValidate($id)
	{
		return new Result();
	}

	//region checkPermissionController
	protected function checkPermissionEntity($name, $arguments=[])
	{
		$name = mb_strtolower($name); //for ajax mode

		if($name == 'modify')
		{
			$r = $this->checkModifyPermissionEntity();
		}
		else
		{
			$r = parent::checkPermissionEntity($name);
		}
		return $r;
	}

	protected function checkModifyPermissionEntity()
	{
		$r = $this->checkReadPermissionEntity();
		if ($r->isSuccess())
		{
			if (!$this->accessController->check(ActionDictionary::ACTION_PRICE_EDIT))
			{
				$r->addError($this->getErrorModifyAccessDenied());
			}
		}

		return $r;
	}

	protected function checkReadPermissionEntity()
	{
		$r = new Result();

		if (
			!$this->accessController->check(ActionDictionary::ACTION_CATALOG_READ)
			&& !$this->accessController->check(ActionDictionary::ACTION_PRICE_EDIT)
		)
		{
			$r->addError($this->getErrorReadAccessDenied());
		}
		return $r;
	}
	//endregion

	//region checkPermissionIBlock
	private function checkPermissionIBlockElementPriceModify($productId)
	{
		$r = new Result();

		$iblockId = \CIBlockElement::GetIBlockByID($productId);
		if(!\CIBlockElementRights::UserHasRightTo($iblockId, $productId, self::IBLOCK_ELEMENT_EDIT_PRICE))
		{
			$r->addError(new Error('Access Denied', 200040300030));
		}
		return $r;
	}
	//endregion
}

Youez - 2016 - github.com/yon3zu
LinuXploit