• Модуль: disk
  • Путь к файлу: ~/bitrix/modules/disk/lib/volume/file.php
  • Класс: BitrixDiskVolumeFile
  • Вызов: File::getMeasurementResult
public function getMeasurementResult(array $collectedData = [self::DISK_FILE, self::ATTACHED_OBJECT, self::EXTERNAL_LINK, self::UNNECESSARY_VERSION, self::CRM_OBJECT]): DBResult
{
	$connection = Application::getConnection();

	$parentFolderId = $this->getFilterValue('PARENT_ID', '=@!');
	if (!empty($parentFolderId))
	{
		$this
			->unsetFilter('PARENT_ID')
			->addFilter('@PARENT_ID', VolumeQueryHelper::prepareFolderTreeQuery($parentFolderId));
	}

	$this->unsetFilter('FILES_LEFT');

	$whereSql = VolumeQueryHelper::prepareWhere(
		$this->getFilter([
			'DELETED_TYPE' => ObjectTable::DELETED_TYPE_NONE,
		]),
		[
			'MODULE_ID' => 'storage.MODULE_ID',
			'STORAGE_ID' => 'files.STORAGE_ID',
			'FOLDER_ID' => 'files.PARENT_ID',
			'PARENT_ID' => 'files.PARENT_ID',
			'TITLE' => 'files.NAME',
			'TYPE' => 'files.TYPE_FILE',
			'DELETED_TYPE' => 'files.DELETED_TYPE',
			'ENTITY_TYPE' => 'storage.ENTITY_TYPE',
		]
	);
	if ($whereSql != '')
	{
		$whereSql = " AND {$whereSql} ";
	}

	$orderSql = VolumeQueryHelper::prepareOrder(
		$this->getOrder([
			'VERSION_COUNT' => 'DESC'
		]),
		[
			'TITLE' => 'CNT_FILES.TITLE',
			'SIZE_FILE' => 'CNT_FILES.SIZE_FILE',
			'UPDATE_TIME' => 'CNT_FILES.UPDATE_TIME',
			'VERSION_SIZE' => 'CNT_FILES.VERSION_SIZE',
			'VERSION_COUNT' => 'CNT_FILES.VERSION_COUNT',
			'UNNECESSARY_VERSION_SIZE' => 'CNT_FREE.UNNECESSARY_VERSION_SIZE',
			'UNNECESSARY_VERSION_COUNT' => 'CNT_FREE.UNNECESSARY_VERSION_COUNT',
		]
	);

	$orderKeys = array_keys($this->getOrder());
	$orderKey = array_shift($orderKeys);


	$sqlHint = '';
	if($connection instanceof DBMysqlCommonConnection)
	{
		$sqlHint = 'SQL_CALC_FOUND_ROWS';
	}

	$indicatorType = $connection->getSqlHelper()->forSql(static::className());

	/**
	 * @param string $whereSql
	 * @return string
	 */
	$buildQueryFiles = function($whereSql = '')
	{
		// language=SQL
		$querySql = "
			/* files */
			(
				SELECT
					SUM(IFNULL(ver.SIZE, 0)) AS VERSION_SIZE,
					COUNT(distinct ver.ID) AS VERSION_COUNT,
					files.NAME as TITLE,
					files.SIZE as SIZE_FILE,
					files.UPDATE_TIME as UPDATE_TIME,
					files.ID AS FID,
					files.PARENT_ID AS PARENT_ID,
					files.STORAGE_ID AS STORAGE_ID,
					storage.ENTITY_TYPE AS ENTITY_TYPE,
					storage.ENTITY_ID AS ENTITY_ID
				FROM
					b_disk_object files
					LEFT JOIN b_disk_version ver ON files.ID = ver.OBJECT_ID
					INNER JOIN b_disk_storage storage ON files.STORAGE_ID = storage.ID
				WHERE
					files.TYPE = ".ObjectTable::TYPE_FILE."
					AND files.ID = files.REAL_OBJECT_ID
					{$whereSql}
				GROUP BY
					files.PARENT_ID,
					files.STORAGE_ID,
					storage.ENTITY_ID,
					storage.ENTITY_TYPE,
					files.ID,
					files.NAME,
					files.SIZE,
					files.UPDATE_TIME
				ORDER BY NULL
			) CNT_FILES
		";
		return $querySql;
	};

	/**
	 * @param string $whereSql
	 * @return string
	 */
	$buildPreviewSql = function($whereSql = '')
	{
		// language=SQL
		$querySql = "
			/* preview */
			LEFT JOIN
			(
				SELECT
					SUM(IFNULL(preview_file.FILE_SIZE, 0)) + SUM(IFNULL(view_file.FILE_SIZE, 0)) AS PREVIEW_SIZE,
					COUNT(DISTINCT preview_file.ID) + COUNT(DISTINCT view_file.ID) AS PREVIEW_COUNT,
					files.ID AS FID
				FROM
					b_disk_object files
					INNER JOIN b_disk_storage storage ON storage.ID = files.STORAGE_ID
					LEFT JOIN b_file preview_file ON preview_file.ID = files.PREVIEW_ID
					LEFT JOIN b_file view_file ON view_file.ID = files.VIEW_ID
				WHERE
					files.TYPE = ". ObjectTable::TYPE_FILE. "
					AND files.ID = files.REAL_OBJECT_ID
					{$whereSql}
				GROUP BY
					files.STORAGE_ID,
					storage.ENTITY_ID,
					storage.ENTITY_TYPE
				ORDER BY NULL
			) CNT_PREVIEW
				ON CNT_PREVIEW.FID = CNT_FILES.FID
		";
		return $querySql;
	};

	/**
	 * @param string $whereSql
	 * @return string
	 */
	$buildQueryAttached = function($whereSql = '')
	{
		// language=SQL
		$querySql = "
			/* attached */
			LEFT JOIN
			(
				SELECT
					COUNT(distinct attached.ID) AS ATTACHED_COUNT,
					files.ID AS FID
				FROM
					b_disk_object files
					LEFT JOIN b_disk_attached_object attached ON files.ID = attached.OBJECT_ID
					INNER JOIN b_disk_storage storage ON files.STORAGE_ID = storage.ID
				WHERE
					files.TYPE = ".ObjectTable::TYPE_FILE."
					AND files.ID = files.REAL_OBJECT_ID
					{$whereSql}
				GROUP BY
					files.ID
				ORDER BY NULL
			) CNT_ATTACH
				ON CNT_ATTACH.FID = CNT_FILES.FID
		";
		return $querySql;
	};

	/**
	 * @param string $whereSql
	 * @return string
	 */
	$buildQueryExternal = function($whereSql = '')
	{
		// language=SQL
		$querySql = "
			/* external_link */
			LEFT JOIN
			(
				SELECT
					COUNT(distinct link.ID) AS LINK_COUNT,
					files.ID AS FID
				FROM
					b_disk_object files
					LEFT JOIN b_disk_external_link link ON files.ID = link.OBJECT_ID
					INNER JOIN b_disk_storage storage ON files.STORAGE_ID = storage.ID
				WHERE
					files.TYPE = ". ObjectTable::TYPE_FILE. "
					AND link.TYPE != ". DiskInternalsExternalLinkTable::TYPE_AUTO. "
					AND files.ID = files.REAL_OBJECT_ID
					{$whereSql}
				GROUP BY
					files.ID
				ORDER BY NULL
			) CNT_LINK
				ON CNT_LINK.FID = CNT_FILES.FID
		";
		return $querySql;
	};

	/**
	 * @param string $whereSql
	 * @return string
	 */
	$buildQuerySharing = function($whereSql = '')
	{
		// language=SQL
		$querySql = "
			/* sharing */
			LEFT JOIN
			(
				SELECT
					COUNT(DISTINCT sharing.ID) AS SHARING_COUNT,
					files.ID AS FID
				FROM
					b_disk_object files
					INNER JOIN b_disk_storage storage ON storage.ID = files.STORAGE_ID
					INNER JOIN b_disk_sharing sharing on sharing.REAL_OBJECT_ID = files.ID
				WHERE
					files.TYPE = ". ObjectTable::TYPE_FILE. "
					AND sharing.STATUS = ". SharingTable::STATUS_IS_APPROVED. "
					AND files.ID = files.REAL_OBJECT_ID
					{$whereSql}
				GROUP BY
					files.ID
				ORDER BY NULL
			) CNT_SHARING
				ON CNT_FILES.FID = CNT_SHARING.FID
		";
		return $querySql;
	};

	/**
	 * @param string $whereSql
	 * @return string
	 */
	$buildQueryCrm = function($whereSql = '')
	{
		// language=SQL
		$querySql = "
			/* crm */
			LEFT JOIN
			(
				SELECT
					COUNT(DISTINCT act_elem.ELEMENT_ID) AS ACT_COUNT,
					files.ID AS FID
				FROM
					b_disk_object files
					INNER JOIN b_disk_storage storage ON storage.ID = files.STORAGE_ID
					INNER JOIN b_crm_act_elem act_elem on act_elem.ELEMENT_ID = files.ID
				WHERE
					files.TYPE = ". ObjectTable::TYPE_FILE. "
					AND act_elem.STORAGE_TYPE_ID = ". BitrixCrmIntegrationStorageType::Disk. "
					AND files.ID = files.REAL_OBJECT_ID
					{$whereSql}
				GROUP BY
					files.ID
				ORDER BY NULL
			) CNT_CRM
				ON CNT_FILES.FID = CNT_CRM.FID
		";
		return $querySql;
	};

	/**
	 * @param string $whereSql
	 * @return string
	 */
	$buildQueryUnnecessary = function($whereSql = '')
	{
		// language=SQL
		$querySql = "
			/* may drop */
			LEFT JOIN
			(
				SELECT
					files.ID AS FID,
					SUM(ver.SIZE) AS UNNECESSARY_VERSION_SIZE,
					COUNT(ver.ID) AS UNNECESSARY_VERSION_COUNT

				FROM
					b_disk_version ver
					INNER JOIN b_disk_object files ON ver.OBJECT_ID = files.ID and ver.FILE_ID != files.FILE_ID
					INNER JOIN b_disk_storage storage ON files.STORAGE_ID = storage.ID

					/* head */
					INNER JOIN (
						SELECT  object_id, max(id) as id
						FROM b_disk_version
						GROUP BY object_id
						ORDER BY NULL
					) head ON head.OBJECT_ID = files.ID

					LEFT JOIN b_disk_attached_object  attached
						ON attached.OBJECT_ID  = ver.OBJECT_ID
						AND attached.VERSION_ID = ver.ID
						AND attached.VERSION_ID != head.ID

					LEFT JOIN b_disk_external_link link
						ON link.OBJECT_ID  = ver.OBJECT_ID
						AND link.VERSION_ID = ver.ID
						AND link.VERSION_ID != head.ID
						AND ifnull(link.TYPE,-1) != ". DiskInternalsExternalLinkTable::TYPE_AUTO. "

				WHERE
					files.TYPE = ". ObjectTable::TYPE_FILE. "
					AND files.ID = files.REAL_OBJECT_ID
					AND attached.VERSION_ID is null /* no attach */
					AND link.VERSION_ID is null /*no link */
					{$whereSql}

				GROUP BY
					files.ID
				ORDER BY NULL
			) CNT_FREE
				ON CNT_FREE.FID = CNT_FILES.FID
		";
		return $querySql;
	};


	$fromSql = $buildQueryFiles($whereSql);

	if ($orderKey == 'UNNECESSARY_VERSION_SIZE' || $orderKey == 'UNNECESSARY_VERSION_COUNT')
	{
		$fromSql .= $buildQueryUnnecessary($whereSql);
	}

	// query to count rows
	$queryIdsSql = "
		SELECT {$sqlHint}
			CNT_FILES.FID as FID
		FROM
			{$fromSql}
		ORDER BY
			{$orderSql}
	";

	if ($this->getLimit() > 0)
	{
		$helper = Application::getConnection()->getSqlHelper();
		$queryIdsSql = $helper->getTopSql($queryIdsSql, $this->getLimit(), $this->getOffset());
	}

	$cursor = $connection->query($queryIdsSql);

	if($connection instanceof DBMysqlCommonConnection)
	{
		$count = $connection->queryScalar('SELECT FOUND_ROWS() as CNT');
	}
	else
	{
		$queryIdsSql = "SELECT COUNT(cntholder) AS CNT FROM (SELECT 1 cntholder FROM {$fromSql}) xxx";

		$count = $connection->queryScalar($queryIdsSql);
	}

	if ($count > 0)
	{
		$ids = [];
		foreach ($cursor as $row)
		{
			$ids[] = $row['FID'];
		}

		$selectSql = '';
		$usingSql = '';
		$fromSql = $buildQueryFiles($whereSql. ' AND files.ID IN('. implode(',', $ids). ') ');

		if (in_array(self::PREVIEW_FILE, $collectedData))
		{
			$selectSql .=
				', IFNULL(CNT_PREVIEW.PREVIEW_SIZE, 0) as PREVIEW_SIZE '.
				', IFNULL(CNT_PREVIEW.PREVIEW_COUNT, 0) as PREVIEW_COUNT';
			$fromSql .= $buildPreviewSql($whereSql);
		}

		if (in_array(self::ATTACHED_OBJECT, $collectedData))
		{
			$selectSql .= ', IFNULL(CNT_ATTACH.ATTACHED_COUNT, 0) as ATTACHED_COUNT';
			$usingSql .= '+ IFNULL(CNT_ATTACH.ATTACHED_COUNT, 0)';
			$fromSql .= $buildQueryAttached($whereSql);
		}

		if (in_array(self::EXTERNAL_LINK, $collectedData))
		{
			$selectSql .= ', IFNULL(CNT_LINK.LINK_COUNT, 0) as LINK_COUNT';
			$usingSql .= '+ IFNULL(CNT_LINK.LINK_COUNT, 0)';
			$fromSql .= $buildQueryExternal($whereSql);
		}

		if (in_array(self::SHARING_OBJECT, $collectedData))
		{
			$selectSql .= ', IFNULL(CNT_SHARING.SHARING_COUNT, 0) as SHARING_COUNT';
			$fromSql .= $buildQuerySharing($whereSql);
		}

		if (in_array(self::UNNECESSARY_VERSION, $collectedData))
		{
			$selectSql .=
				', IFNULL(CNT_FREE.UNNECESSARY_VERSION_SIZE, 0) as UNNECESSARY_VERSION_SIZE '.
				', IFNULL(CNT_FREE.UNNECESSARY_VERSION_COUNT, 0) as UNNECESSARY_VERSION_COUNT';

			$fromSql .= $buildQueryUnnecessary($whereSql);
		}

		if (in_array(self::CRM_OBJECT, $collectedData))
		{
			$crmIndicator = new VolumeModuleCrm();
			if ($crmIndicator->isMeasureAvailable())
			{
				$selectSql .= ', IFNULL(CNT_CRM.ACT_COUNT, 0) as ACT_COUNT';
				$usingSql .= '+ IFNULL(CNT_CRM.ACT_COUNT, 0)';
				$fromSql .= $buildQueryCrm($whereSql);
			}
		}

		// main query
		$querySql = "
			SELECT
				'{$indicatorType}' as INDICATOR_TYPE,
				CNT_FILES.FID as ID,
				CNT_FILES.PARENT_ID as FOLDER_ID,
				CNT_FILES.*,
				0 {$usingSql} as USING_COUNT
				{$selectSql}
			FROM
				{$fromSql}
			ORDER BY
				{$orderSql}
		";

		$cursor = $connection->query($querySql);
		$cursor->setCount($count);
	}

	return $cursor;
}