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;
}