AnonSec Shell
Server IP : 85.193.89.191  /  Your IP : 18.216.142.2
Web Server : Apache
System : Linux 956367-cx40159.tmweb.ru 3.10.0-1160.105.1.el7.x86_64 #1 SMP Thu Dec 7 15:39:45 UTC 2023 x86_64
User : bitrix ( 600)
PHP Version : 8.1.27
Disable Function : NONE
MySQL : OFF  |  cURL : OFF  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/bitrix/www/bitrix/modules/catalog/lib/controller/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home/bitrix/www/bitrix/modules/catalog/lib/controller/document.php
<?php

namespace Bitrix\Catalog\Controller;

use Bitrix\Catalog\Access\ActionDictionary;
use Bitrix\Catalog\Access\Model\StoreDocument;
use Bitrix\Catalog\Config\Feature;
use Bitrix\Main\Engine\CurrentUser;
use Bitrix\Catalog\StoreDocumentTable;
use Bitrix\Main\Engine\Response\DataType\Page;
use Bitrix\Main\Error;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Result;
use Bitrix\Main\UI\PageNavigation;
use CApplicationException;
use CCatalogDocs;
use CMain;

class Document extends Controller
{
	//region Actions
	/**
	 * @return array
	 */
	public function getFieldsAction(): array
	{
		return ['DOCUMENT' => $this->getViewFields()];
	}

	/**
	 * @param array $documentIds
	 *
	 * @return null|bool
	 */
	public function conductListAction(array $documentIds): ?bool
	{
		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		if (!\Bitrix\Catalog\Component\UseStore::isUsed())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_MANAGEMENT_NOT_ENABLED')));

			return null;
		}

		global $APPLICATION;

		$documentData = $this->getDocumentData($documentIds);

		$userId = CurrentUser::get()->getId();
		foreach ($documentIds as $documentId)
		{
			$document = $documentData[$documentId] ?? null;
			if (!$document)
			{
				$this->addError(
					new Error(Loc::getMessage(
						'CATALOG_CONTROLLER_DOCUMENT_CONDUCT_GENERAL_ERROR',
						[
							'#ERROR#' => Loc::getMessage('CATALOG_CONTROLLER_DOCUMENT_NOT_FOUND'),
						]
					))
				);
				continue;
			}

			$documentTitle = $document['TITLE'] ?: StoreDocumentTable::getTypeList(true)[$document['DOC_TYPE']];

			$can = $this->accessController->check(
				ActionDictionary::ACTION_STORE_DOCUMENT_CONDUCT,
				StoreDocument::createFromArray($document)
			);
			if (!$can)
			{
				$this->addError(
					new Error(Loc::getMessage('CATALOG_CONTROLLER_DOCUMENT_CONDUCT_ERROR',
						[
							'#DOC_TITLE#' => htmlspecialcharsbx($documentTitle),
							'#ERROR#' => Loc::getMessage('DOCUMENT_CONTROLLER_NO_RIGHTS_ERROR'),
						]
					))
				);
				continue;
			}

			$isConducted = \CCatalogDocs::conductDocument($documentId, $userId);
			if (!$isConducted)
			{
				if ($APPLICATION->GetException())
				{
					$this->addError(
						new Error(Loc::getMessage(
							'DOCUMENT_CONTROLLER_CONDUCT_ERROR',
							[
								'#DOC_TITLE#' => htmlspecialcharsbx($documentTitle),
								'#ERROR#' => htmlspecialcharsbx($APPLICATION->GetException()->GetString()),
							]
						))
					);
					$APPLICATION->ResetException();
				}
				else
				{
					$this->addError(
						new Error(Loc::getMessage('CATALOG_CONTROLLER_DOCUMENT_CONDUCT_GENERAL_ERROR',
							[
								'#DOC_TITLE#' => htmlspecialcharsbx($documentTitle),
							]
						))
					);
				}
			}
		}

		if (!$this->errorCollection->isEmpty())
		{
			return null;
		}

		return true;
	}

	/**
	 * @param $documentIds
	 *
	 * @return bool|null
	 */
	public function cancelListAction(array $documentIds): ?bool
	{
		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		if (!\Bitrix\Catalog\Component\UseStore::isUsed())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_MANAGEMENT_NOT_ENABLED')));

			return null;
		}

		global $APPLICATION;

		$documentData = $this->getDocumentData($documentIds);
		$userId = CurrentUser::get()->getId();
		foreach ($documentIds as $documentId)
		{
			$document = $documentData[$documentId] ?? null;
			if (!$document)
			{
				$this->addError(
					new Error(Loc::getMessage(
						'CATALOG_CONTROLLER_DOCUMENT_CANCEL_ERROR',
						[
							'#ERROR#' => Loc::getMessage('CATALOG_CONTROLLER_DOCUMENT_NOT_FOUND'),
						]
					))
				);
				continue;
			}

			$documentTitle = $document['TITLE'] ?: StoreDocumentTable::getTypeList(true)[$document['DOC_TYPE']];

			$can = $this->accessController->check(
				ActionDictionary::ACTION_STORE_DOCUMENT_CONDUCT,
				StoreDocument::createFromArray($document)
			);
			if (!$can)
			{
				$this->addError(
					new Error(Loc::getMessage('DOCUMENT_CONTROLLER_CANCEL_ERROR',
						[
							'#DOC_TITLE#' => htmlspecialcharsbx($documentTitle),
							'#ERROR#' => Loc::getMessage('DOCUMENT_CONTROLLER_NO_RIGHTS_ERROR'),
						]
					))
				);
				continue;
			}

			$isCancelled = \CCatalogDocs::cancellationDocument($documentId, $userId);
			if (!$isCancelled)
			{
				if ($APPLICATION->GetException())
				{
					$this->addError(
						new Error(Loc::getMessage(
							'DOCUMENT_CONTROLLER_CANCEL_ERROR',
							[
								'#DOC_TITLE#' => htmlspecialcharsbx($documentTitle),
								'#ERROR#' => htmlspecialcharsbx($APPLICATION->GetException()->GetString()),
							]
						))
					);
					$APPLICATION->ResetException();
				}
				else
				{
					$documentTitle = $documentData[$documentId]['TITLE'] ?: StoreDocumentTable::getTypeList(true)[$documentData[$documentId]['DOC_TYPE']];
					$this->addError(
						new Error(Loc::getMessage(
							'CATALOG_CONTROLLER_DOCUMENT_CANCEL_ERROR',
							[
								'#ERROR#' => htmlspecialcharsbx($documentTitle),
							]
						))
					);
				}
			}
		}

		if (!$this->errorCollection->isEmpty())
		{
			return null;
		}

		return true;
	}

	private function prepareFieldsAdd($fields)
	{
		if (!array_key_exists('SITE_ID', $fields))
		{
			if (defined('SITE_ID'))
			{
				$fields['SITE_ID'] = SITE_ID;
			}
			else
			{
				$fields['SITE_ID'] = 's1';
			}
		}

		if (!CurrentUser::get()->isAdmin() || !array_key_exists('CREATED_BY', $fields))
		{
			$fields['CREATED_BY'] = CurrentUser::get()->getId();
		}

		if (!CurrentUser::get()->isAdmin() || !array_key_exists('MODIFIED_BY', $fields))
		{
			$fields['MODIFIED_BY'] = CurrentUser::get()->getId();
		}

		return $fields;
	}

	/**
	 * Adds new document.
	 * @param array $fields
	 *
	 * @return null|array
	 */
	public function addAction(array $fields): ?array
	{
		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		$docType = $fields['DOC_TYPE'] ?? null;

		$availableTypes = self::getAvailableRestDocumentTypes();
		if (!isset($availableTypes[$docType]))
		{
			$this->addError(new Error('DOC_TYPE isn\'t available'));

			return null;
		}

		if (!$this->accessController->check(ActionDictionary::ACTION_STORE_DOCUMENT_MODIFY, StoreDocument::createFromArray($fields)))
		{
			$this->addError(
				new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_RIGHTS_ERROR'))
			);

			return null;
		}

		$fields = $this->prepareFieldsAdd($fields);
		$addResult = CCatalogDocs::add($fields);
		if (!$addResult)
		{
			global $APPLICATION;
			if ($APPLICATION->GetException())
			{
				$exception = $APPLICATION->GetException();
				$this->addError(new Error($exception->GetString()));
				$APPLICATION->ResetException();

				return null;
			}
		}

		return ['DOCUMENT' => $this->get($addResult)];
	}

	/**
	 * @deprecated
	 *
	 * Return documents fields.
	 *
	 * @return array
	 */
	public function fieldsAction(): array
	{
		return [$this->getViewFields()];
	}

	/**
	 * Updates document.
	 * @param int $id
	 * @param array $fields
	 *
	 * @return null|array
	 */
	public function updateAction(int $id, array $fields): ?array
	{
		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		if (!$this->checkDocumentAccess(ActionDictionary::ACTION_STORE_DOCUMENT_MODIFY, $id))
		{
			return null;
		}

		$user = CurrentUser::get();
		if (!array_key_exists('MODIFIED_BY', $fields) || !$user->isAdmin())
		{
			$fields['MODIFIED_BY'] = $user->getId();
		}

		$result = CCatalogDocs::update($id, $fields);
		if (!$result)
		{
			global $APPLICATION;
			if ($APPLICATION->GetException())
			{
				$exception = $APPLICATION->GetException();
				$this->addError(new Error($exception->GetString()));
				$APPLICATION->ResetException();

				return null;
			}
		}

		return ['DOCUMENT' => $this->get($id)];
	}

	/**
	 * @param array $documentIds
	 *
	 * @return bool|null
	 */
	public function deleteListAction(array $documentIds): ?bool
	{
		global $APPLICATION;

		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		/**
		 * @var CMain $APPLICATION
		 */

		$documentData = $this->getDocumentData($documentIds);

		foreach ($documentIds as $documentId)
		{
			$exception = null;
			$document = $documentData[(int)$documentId] ?? null;

			if (!$document)
			{
				$this->addError(
					new Error(Loc::getMessage(
						'DOCUMENT_CONTROLLER_DELETE_ERROR',
						[
							'#DOC_TITLE#' => "#{$documentId}",
							'#ERROR#' => Loc::getMessage('CATALOG_CONTROLLER_DOCUMENT_NOT_FOUND'),
						]
					))
				);
				continue;
			}

			$can = $this->accessController->check(
				ActionDictionary::ACTION_STORE_DOCUMENT_DELETE,
				StoreDocument::createFromArray($document)
			);
			if ($can)
			{
				\CCatalogDocs::delete($documentId);

				$exception = $APPLICATION->GetException();
			}
			else
			{
				$exception = new CApplicationException(
					Loc::getMessage('DOCUMENT_CONTROLLER_NO_RIGHTS_ERROR')
				);
			}

			if ($exception)
			{
				$documentTitle = $document['TITLE'] ?: StoreDocumentTable::getTypeList(true)[$document['DOC_TYPE']];
				if ($exception->GetID() === CCatalogDocs::DELETE_CONDUCTED_ERROR)
				{
					$this->addError(
						new Error(Loc::getMessage(
							'DOCUMENT_CONTROLLER_DELETE_CONDUCTED_ERROR',
							[
								'#DOC_TITLE#' => htmlspecialcharsbx($documentTitle),
							]
						))
					);
				}
				else
				{
					$this->addError(
						new Error(Loc::getMessage(
							'DOCUMENT_CONTROLLER_DELETE_ERROR',
							[
								'#DOC_TITLE#' => htmlspecialcharsbx($documentTitle),
								'#ERROR#' => htmlspecialcharsbx($exception->GetString()),
							]
						))
					);
				}

				$APPLICATION->ResetException();
			}
		}

		return $this->errorCollection->isEmpty() ? true : null;
	}

	/**
	 * Deletes document by id.
	 * @param int $id
	 *
	 * @return null|bool
	 */
	public function deleteAction(int $id): ?bool
	{
		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		if (!$this->checkDocumentAccess(ActionDictionary::ACTION_STORE_DOCUMENT_DELETE, $id))
		{
			return null;
		}

		$deleteResult = CCatalogDocs::delete($id);
		if (!$deleteResult)
		{
			$message = Loc::getMessage('CATALOG_CONTROLLER_DOCUMENT_NOT_FOUND');

			$this->addError(
				new Error($message)
			);

			return null;
		}

		global $APPLICATION;
		if ($exception = $APPLICATION->getException())
		{
			if ($exception->getID() === CCatalogDocs::DELETE_CONDUCTED_ERROR)
			{
				$message = Loc::getMessage(
					'DOCUMENT_CONTROLLER_DELETE_CONDUCTED_ERROR',
					[
						'#DOC_TITLE#' => $id,
					]
				);
			}
			else
			{
				$message = Loc::getMessage(
					'DOCUMENT_CONTROLLER_DELETE_ERROR',
					[
						'#DOC_TITLE#' => $id,
						'#ERROR#' => htmlspecialcharsbx($exception->getString()),
					]
				);
			}

			$this->addError(
				new Error($message)
			);

			$APPLICATION->ResetException();

			return null;
		}

		return $deleteResult;
	}

	/**
	 * Returns list of document.
	 *
	 * @param array $order
	 * @param array $filter
	 * @param array $select
	 * @param PageNavigation $pageNavigation
	 *
	 * @return array
	 */
	public function listAction(
		PageNavigation $pageNavigation,
		array $order = [],
		array $filter = [],
		array $select = []
	): Page
	{
		// set available types for REST
		$filter = [
			'=DOC_TYPE' => array_keys(self::getAvailableRestDocumentTypes()),
			$filter,
		];

		$accessFilter = $this->accessController->getEntityFilter(
			ActionDictionary::ACTION_STORE_DOCUMENT_VIEW,
			get_class($this->getEntityTable())
		);
		if ($accessFilter)
		{
			// combines through a new array so that the `OR` condition does not bypass the access filter.
			$filter = [
				$accessFilter,
				$filter,
			];
		}

		return new Page('DOCUMENTS',
			$this->getList($select, $filter, $order, $pageNavigation),
			$this->count($filter)
		);
	}

	/**
	 * Conducts document.
	 *
	 * @param int $id
	 *
	 * @return bool|null
	 */
	public function conductAction(int $id): ?bool
	{
		return $this->confirmAction($id);
	}

	/**
	 * Conducts document.
	 *
	 * @deprecated
	 *
	 * @param int $id
	 *
	 * @return bool|null
	 */
	public function confirmAction(int $id): ?bool
	{
		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		if (!$this->checkDocumentAccess(ActionDictionary::ACTION_STORE_DOCUMENT_CONDUCT, $id))
		{
			return null;
		}

		$document = StoreDocumentTable::getById($id)->fetch();
		if (!$document)
		{
			$message = Loc::getMessage('CATALOG_CONTROLLER_DOCUMENT_NOT_FOUND');
			$this->addError(
				new Error($message)
			);

			return null;
		}

		$userId = CurrentUser::get()->getId();

		if (!CCatalogDocs::conductDocument($id, $userId))
		{
			$error = '';

			global $APPLICATION;

			if ($APPLICATION->GetException())
			{
				$error = $APPLICATION->GetException()->GetString();
				$APPLICATION->ResetException();
			}

			$message = Loc::getMessage(
				'CATALOG_CONTROLLER_DOCUMENT_CONDUCT_ERROR',
				[
					'#ERROR#' => $error,
				]
			);

			$this->addError(new Error($message));

			return null;
		}

		return true;
	}

	/**
	 * Cancel document.
	 *
	 * @param int $id
	 *
	 * @return bool|null
	 */
	public function cancelAction(int $id): ?bool
	{
		return $this->unconfirmAction($id);
	}

	/**
	 * Cancellations document.
	 *
	 * @param int $id
	 *
	 * @return bool|null
	 */
	public function unconfirmAction(int $id): ?bool
	{
		if (!Feature::isInventoryManagementEnabled())
		{
			$this->addError(new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_INVENTORY_MANAGEMENT_ENABLED_ERROR')));

			return null;
		}

		if (!$this->checkDocumentAccess(ActionDictionary::ACTION_STORE_DOCUMENT_CONDUCT, $id))
		{
			return null;
		}

		$userId = CurrentUser::get()->getId();
		if (!CCatalogDocs::cancellationDocument($id, $userId))
		{
			$error = '';

			global $APPLICATION;
			if ($APPLICATION->GetException())
			{
				$error = $APPLICATION->GetException()->GetString();
				$APPLICATION->ResetException();
			}

				$message = Loc::getMessage(
				'CATALOG_CONTROLLER_DOCUMENT_CANCEL_ERROR',
				[
					'#ERROR#' => $error,
				]
			);
			$this->addError(new Error($message));

			return null;
		}

		return true;
	}

	/**
	 * @return array
	 */
	public static function getAvailableRestDocumentTypes(): array
	{
		$types = StoreDocumentTable::getTypeList(true);
		unset($types[StoreDocumentTable::TYPE_UNDO_RESERVE]);

		return $types;
	}

	/**
	 * @param $name
	 * @param $arguments
	 * @return Result
	 * @throws \Bitrix\Main\NotImplementedException
	 */
	protected function checkPermissionEntity($name, $arguments=[])
	{
		$name = mb_strtolower($name);
		if ($name === 'fields')
		{
			return $this->checkGetFieldsPermissionEntity();
		}

		if (in_array($name, ['conductlist', 'cancellist', 'unconfirm', 'confirm', 'conduct', 'cancel'], true))
		{
			return $this->checkUpdatePermissionEntity();
		}

		if ($name === 'deletelist')
		{
			return $this->checkDeletePermissionEntity();
		}

		return parent::checkPermissionEntity($name, $arguments);
	}

	/**
	 * @inheritDoc
	 */
	protected function getEntityTable()
	{
		return new \Bitrix\Catalog\StoreDocumentTable();
	}

	protected function checkModifyPermissionEntity()
	{
		$r = $this->checkReadPermissionEntity();
		if ($r->isSuccess())
		{
			if (!$this->accessController->check(Controller::CATALOG_STORE))
			{
				$message = Loc::getMessage('DOCUMENT_CONTROLLER_NO_STORE_RIGHTS_ERROR');
				$r->addError(new Error($message));
			}
		}

		return $r;
	}

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

		if (
			!$this->accessController->check(Controller::CATALOG_STORE)
			&& !$this->accessController->check(Controller::CATALOG_READ)
		)
		{
			$message = Loc::getMessage('DOCUMENT_CONTROLLER_NO_RIGHTS_ERROR');
			$r->addError(new Error($message));
		}

		return $r;
	}

	private function getDocumentData(array $documentIds): array
	{
		$documentTitlesRes = StoreDocumentTable::getList(['select' => ['ID', 'DOC_TYPE', 'TITLE'], 'filter' => ['ID' => $documentIds]]);
		$documentTitles = [];
		while ($document = $documentTitlesRes->fetch())
		{
			$documentTitles[$document['ID']] = [
				'ID' => $document['ID'],
				'TITLE' => $document['TITLE'],
				'DOC_TYPE' => $document['DOC_TYPE'],
			];
		}

		return $documentTitles;
	}

	/**
	 * Check access to document store and add error to controller.
	 *
	 * Adds error if user does not have access.
	 *
	 * @param string $action
	 * @param int $documentId
	 *
	 * @return bool false - if is access denied.
	 */
	private function checkDocumentAccess(string $action, int $documentId): bool
	{
		$can = $this->accessController->check($action, StoreDocument::createFromId($documentId));
		if (!$can)
		{
			$this->addError(
				new Error(Loc::getMessage('DOCUMENT_CONTROLLER_NO_RIGHTS_ERROR'))
			);

			return false;
		}

		return true;
	}
}

Anon7 - 2022
AnonSec Team