• Модуль: disk
  • Путь к файлу: ~/bitrix/modules/disk/lib/volume/module/crm.php
  • Класс: BitrixDiskVolumeModuleCrm
  • Вызов: Crm::measure
public function measure(array $collectData = []): self
{
	if (!$this->isMeasureAvailable())
	{
		$this->addError(new BitrixMainError('', self::ERROR_MEASURE_UNAVAILABLE));
		return $this;
	}

	$connection = BitrixMainApplication::getConnection();
	$indicatorType = $connection->getSqlHelper()->forSql(static::className());
	$ownerId = (string)$this->getOwner();

	$tableName = VolumeTable::getTableName();

	$stageId = $this->getStage();
	if (empty($stageId))
	{
		$stageId = 'UserFields';
		$this->setStage($stageId);
	}

	switch($stageId)
	{
		case 'UserFields':
		{
			// Scan User fields specific to module
			$entityUserFieldSource = $this->prepareUserFieldSourceSql(null, [CUserTypeFile::USER_TYPE_ID]);
			if ($entityUserFieldSource != '')
			{
				$querySql = "
					INSERT INTO {$tableName}
					(
						INDICATOR_TYPE,
						OWNER_ID,
						CREATE_TIME,
						TITLE,
						FILE_SIZE,
						FILE_COUNT,
						DISK_SIZE,
						DISK_COUNT,
						VERSION_COUNT
					)
					SELECT 
						'{$indicatorType}' as INDICATOR_TYPE,
						{$ownerId} as OWNER_ID,
						". $connection->getSqlHelper()->getCurrentDateTimeFunction(). " as CREATE_TIME,
						'UserFields',
						SUM(src.FILE_SIZE) as FILE_SIZE,
						SUM(src.FILE_COUNT) as FILE_COUNT,
						SUM(src.DISK_SIZE) as DISK_SIZE,
						SUM(src.DISK_COUNT) as DISK_COUNT,
						SUM(src.VERSION_COUNT) as VERSION_COUNT
					FROM 
					(
						{$entityUserFieldSource}
					) src
				";
				$connection->queryExecute($querySql);
			}
			unset($querySql);

			$this->setStage('ActElemFile');// go next

			if (!$this->checkTimeEnd())
			{
				break;
			}
		}


		case 'ActElemFile':
		{
			$crmActivityElememtTable = CCrmActivity::ELEMENT_TABLE_NAME;

			$querySql = "
				INSERT INTO {$tableName}
				(
					INDICATOR_TYPE,
					OWNER_ID,
					CREATE_TIME,
					TITLE,
					FILE_SIZE,
					FILE_COUNT,
					DISK_SIZE,
					DISK_COUNT,
					VERSION_COUNT
				)
				SELECT
					'{$indicatorType}' as INDICATOR_TYPE,
					{$ownerId} as OWNER_ID,
					". $connection->getSqlHelper()->getCurrentDateTimeFunction(). " as CREATE_TIME,
					'ActElemFile' as TITLE, 
					SUM(f.FILE_SIZE) as FILE_SIZE,
					COUNT(f.id) as FILE_COUNT, 
					0 as DISK_SIZE,
					0 as DISK_COUNT,
					0 as VERSION_COUNT
				FROM 
					b_file f
					INNER JOIN (
						SELECT ELEMENT_ID
						FROM {$crmActivityElememtTable}
						WHERE STORAGE_TYPE_ID = '".BitrixCrmIntegrationStorageType::File."'
						GROUP BY ELEMENT_ID  
						ORDER BY NULL
					) elem
						ON elem.ELEMENT_ID = f.ID
			";
			$connection->queryExecute($querySql);
			unset($querySql);

			$this->setStage('ActElemDisk');// go next

			if (!$this->checkTimeEnd())
			{
				break;
			}
		}


		case 'ActElemDisk':
		{
			/**
			 * @param VolumeIVolumeIndicatorModule $indicator
			 * @return int[]
			 */
			$getExcludeFolderId = function ($indicator)
			{
				$folderIds = [];
				$storageList = $indicator->getStorageList();
				foreach ($storageList as $storage)
				{
					$folderList = $indicator->getFolderList($storage);
					foreach ($folderList as $folder)
					{
						$folderIds[] = $folder->getId();

						$childFolders = DiskInternalsFolderTable::getList([
							'select' => ['ID'],
							'filter' => [
								'=TYPE' => DiskInternalsObjectTable::TYPE_FOLDER,
								'=PATH_CHILD.PARENT_ID' => $folder->getId()
							]
						]);
						foreach ($childFolders as $row)
						{
							$folderIds[] = $row['ID'];
						}
					}
				}

				return $folderIds;
			};

			// exclude CRM regular folders content
			$excludeFolderIds = $getExcludeFolderId($this);

			// exclude voximplant folders content
			$vox = new VolumeModuleVoximplant();
			$excludeFolderIds = array_merge($excludeFolderIds, $getExcludeFolderId($vox));

			$excludeFolderSql = '';
			if (count($excludeFolderIds) > 0)
			{
				$excludeFolderSql = '
					AND files.PARENT_ID NOT IN(
						SELECT object_id FROM b_disk_object_path 
						WHERE PARENT_id IN('. implode(',', $excludeFolderIds). ')
					)
				';
			}

			$crmActivityElememtTable = CCrmActivity::ELEMENT_TABLE_NAME;

			$querySql = "
				INSERT INTO {$tableName}
				(
					INDICATOR_TYPE,
					OWNER_ID,
					CREATE_TIME,
					TITLE,
					FILE_SIZE,
					FILE_COUNT,
					DISK_SIZE,
					DISK_COUNT,
					VERSION_COUNT
				)
				SELECT
					'{$indicatorType}' as INDICATOR_TYPE,
					{$ownerId} as OWNER_ID,
					". $connection->getSqlHelper()->getCurrentDateTimeFunction(). " as CREATE_TIME,
					'ActElemDisk' as TITLE, 
					SUM(f.FILE_SIZE) as FILE_SIZE,
					COUNT(f.id) as FILE_COUNT, 
					SUM(f.FILE_SIZE) as DISK_SIZE,
					COUNT(f.id) as DISK_COUNT,
					COUNT(f.id) as VERSION_COUNT
				FROM 
					b_disk_object files 
					INNER JOIN b_file f 
						ON files.FILE_ID = f.ID 
					INNER JOIN 
					(
						SELECT ELEMENT_ID 
						FROM {$crmActivityElememtTable} 
						WHERE STORAGE_TYPE_ID = '".BitrixCrmIntegrationStorageType::Disk."'
						GROUP BY ELEMENT_ID
						ORDER BY NULL
					) elem
						ON files.ID = elem.ELEMENT_ID
				WHERE
					files.TYPE = '".DiskInternalsObjectTable::TYPE_FILE."'
					AND files.ID = files.REAL_OBJECT_ID
					{$excludeFolderSql}
			";
			$connection->queryExecute($querySql);
			unset($querySql);

			$this->setStage('CrmEvent');// go next

			if (!$this->checkTimeEnd())
			{
				break;
			}
		}


		case 'CrmEvent':
		{
			$crmEventTable = BitrixCrmEventTable::getTableName();

			// analise b_crm_event with non empty field FILES
			$querySql = "
				INSERT INTO {$tableName}
				(
					INDICATOR_TYPE,
					OWNER_ID,
					CREATE_TIME,
					TITLE,
					FILE_SIZE,
					FILE_COUNT,
					DISK_SIZE,
					DISK_COUNT,
					VERSION_COUNT
				)
				SELECT 
					'{$indicatorType}' as INDICATOR_TYPE,
					{$ownerId} as OWNER_ID,
					". $connection->getSqlHelper()->getCurrentDateTimeFunction(). " as CREATE_TIME,
					'CrmEvent' as TITLE,
					SUM(f.FILE_SIZE) as FILE_SIZE,
					count(f.ID) as FILE_COUNT,
					0 as DISK_SIZE,
					0 as DISK_COUNT,
					0 as VERSION_COUNT
				FROM 
				(
					select  
						CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(src.fids, ' ', NS.n), ' ', -1) AS UNSIGNED) as ID
					from (
						select 1 as n union
						select 2 union
						select 3 union
						select 4 union
						select 5 union
						select 6 union
						select 7 union
						select 8 union
						select 9 union
						select 10 union
						select 11 union
						select 12 union
						select 13 union
						select 14 union
						select 15 union
						select 16 union
						select 17 union
						select 18 union
						select 19 union
						select 20
					) NS
					inner join
					(
						select
							@xml := replace(
								replace(
									replace(
										replace(
											e.FILES, 
											'a:',''
										),
										';}',''
									),
									':{i:',''
								),
								';i:',''
							) as xml,
							CAST(ExtractValue(@xml, '/a/len') AS UNSIGNED) as len,
							ExtractValue(@xml, '/a/i[position() mod 2 = 0]') as fids
						from 
							{$crmEventTable} e
						where 
							e.FILES is not null
							and e.FILES <> ''
							and e.FILES <> 'a:0:{}'
					) src 
					ON NS.n <= src.len
					
				) file_ids
				INNER JOIN b_file f
						ON file_ids.ID = f.ID
			";
			$connection->queryExecute($querySql);
			unset($querySql);

			$this->setStage('CrmFolder');// go next

			if (!$this->checkTimeEnd())
			{
				break;
			}
		}


		case 'CrmFolder':
		{
			// Scan specific folder list in a storage
			VolumeTable::createTemporally();
			$temporallyTableName = VolumeTable::getTemporallyName();

			$storageList = $this->getStorageList();
			foreach ($storageList as $storage)
			{
				$storageId = $storage->getId();
				$parentId = $storage->getRootObjectId();
				$folderIds = [];

				$folders = $this->getFolderList($storage);
				foreach ($folders as $folder)
				{
					$folderIds[] = $folder->getId();
				}
				if (count($folderIds) > 0)
				{
					$agr = new VolumeFolderTree;
					$agr
						->setOwner($this->getOwner())
						->addFilter('STORAGE_ID', $storageId)
						->addFilter('@FOLDER_ID', $folderIds)
						->purify()
						->measure([self::DISK_FILE]);

					$indicatorTypeFolder = $connection->getSqlHelper()->forSql(VolumeFolder::className());

					$folderIdSql = implode(',', $folderIds);

					$querySql = "
						INSERT INTO {$temporallyTableName}
						(
							INDICATOR_TYPE,
							OWNER_ID,
							CREATE_TIME,
							TITLE,
							FILE_SIZE,
							FILE_COUNT,
							DISK_SIZE,
							DISK_COUNT,
							VERSION_COUNT,
							ATTACHED_COUNT,
							LINK_COUNT,
							SHARING_COUNT,
							UNNECESSARY_VERSION_SIZE,
							UNNECESSARY_VERSION_COUNT
						)
						SELECT 
							'{$indicatorType}',
							{$ownerId},
							".$connection->getSqlHelper()->getCurrentDateTimeFunction()." as CREATE_TIME,
							'CrmFolder' as TITLE,
							SUM(FILE_SIZE),
							SUM(FILE_COUNT),
							SUM(DISK_SIZE),
							SUM(DISK_COUNT),
							SUM(VERSION_COUNT),
							SUM(ATTACHED_COUNT),
							SUM(LINK_COUNT),
							SUM(SHARING_COUNT),
							SUM(UNNECESSARY_VERSION_SIZE),
							SUM(UNNECESSARY_VERSION_COUNT)
						FROM 
							b_disk_volume
						WHERE 
							INDICATOR_TYPE = '{$indicatorTypeFolder}'
							and OWNER_ID = {$ownerId}
							and STORAGE_ID = '{$storageId}'
							and FOLDER_ID IN( {$folderIdSql} ) 
							and PARENT_ID = '{$parentId}'
					";

					$connection->queryExecute($querySql);
					unset($querySql);
				}
			}

			$querySql = "
				SELECT 
					INDICATOR_TYPE,
					OWNER_ID,
					CREATE_TIME,
					TITLE,
					SUM(FILE_SIZE),
					SUM(FILE_COUNT),
					SUM(DISK_SIZE),
					SUM(DISK_COUNT),
					SUM(VERSION_COUNT),
					SUM(ATTACHED_COUNT),
					SUM(LINK_COUNT),
					SUM(SHARING_COUNT),
					SUM(UNNECESSARY_VERSION_SIZE),
					SUM(UNNECESSARY_VERSION_COUNT)
				FROM 
					{$temporallyTableName}
				WHERE 
					INDICATOR_TYPE = '{$indicatorType}'
				GROUP BY
					INDICATOR_TYPE
				ORDER BY NULL
			";
			$columnList = VolumeQueryHelper::prepareInsert(
				[
					'INDICATOR_TYPE',
					'OWNER_ID',
					'CREATE_TIME',
					'TITLE',
					'FILE_SIZE',
					'FILE_COUNT',
					'DISK_SIZE',
					'DISK_COUNT',
					'VERSION_COUNT',
					'ATTACHED_COUNT',
					'LINK_COUNT',
					'SHARING_COUNT',
					'UNNECESSARY_VERSION_SIZE',
					'UNNECESSARY_VERSION_COUNT',
				],
				$this->getSelect()
			);
			$connection->queryExecute("INSERT INTO {$tableName} ({$columnList}) {$querySql}");

			VolumeTable::clearTemporally();

			$this->setStage(null);
		}
	}

	return $this;
}