• Модуль: intranet
  • Путь к файлу: ~/bitrix/modules/intranet/lib/ustat/ustat.php
  • Класс: BitrixIntranetUStatUStat
  • Вызов: UStat::getUsersGraphData
static function getUsersGraphData($userId, TypeDateTime $dateFrom, TypeDateTime $dateTo, $interval, $section = null)
{
	if (!in_array($interval, array('hour', 'day', 'month'), true))
	{
		throw new MainArgumentException('Interval should be the "hour", or "day", or "month".');
	}

	$data = array();

	// rating for TOTAL activity or for an instrument
	$posField = ($section) === null ? 'TOTAL' : $section;

	if ($interval === 'hour')
	{
		$query = new EntityQuery(UserHourTable::getEntity());

		$query->setSelect(array('USER_ID', 'DATE' => 'HOUR', 'TOTAL'));

		foreach (UserHourTable::getSectionNames() as $sectionName)
		{
			$query->addSelect($sectionName);
		}

		$query->setFilter(array(
			'=USER_ID' => $userId,
			'> array(
				ConvertTimeStamp($dateFrom->getTimestamp(), 'FULL'),
				ConvertTimeStamp($dateTo->getTimestamp(), 'FULL')
			)
		));

		$keyFormat = 'Y-m-d H:00:00';

		// top position
		$posQuery = new EntityQuery(UserHourTable::getEntity());

		$posQuery->setFilter(array(
			'> array(
				ConvertTimeStamp($dateFrom->getTimestamp(), 'FULL'),
				ConvertTimeStamp($dateTo->getTimestamp(), 'FULL')
			),
			'>LEAD_'.$posField => 0,
			'>SUM_'.$posField => 0
		));
	}
	elseif ($interval === 'day')
	{
		$query = new EntityQuery(UserDayTable::getEntity());

		$query->setSelect(array('USER_ID', 'DATE' => 'DAY', 'TOTAL'));

		foreach (UserHourTable::getSectionNames() as $sectionName)
		{
			$query->addSelect($sectionName);
		}

		$query->setFilter(array(
			'=USER_ID' => $userId,
			'> array(
				ConvertTimeStamp($dateFrom->getTimestamp()),
				ConvertTimeStamp($dateTo->getTimestamp())
			)
		));

		$keyFormat = 'Y-m-d';

		// top position
		$posQuery = new EntityQuery(UserDayTable::getEntity());

		$posQuery->setFilter(array(
			'> array(
				ConvertTimeStamp($dateFrom->getTimestamp()),
				ConvertTimeStamp($dateTo->getTimestamp())
			),
			'>LEAD_'.$posField => 0,
			'>SUM_'.$posField => 0
		));
	}
	elseif ($interval === 'month')
	{
		$query = new EntityQuery(UserDayTable::getEntity());
		$sqlHelper = Application::getConnection()->getSqlHelper();

		$monthExpression = array(
			'data_type' => 'string',
			'expression' => array(str_replace(
				$sqlHelper->formatDate('YYYY-MM'), // get db format
				str_replace('%', '%%', $sqlHelper->formatDate('YYYY-MM')), // and quote it for sprintf
				$sqlHelper->formatDate('YYYY-MM', '%1$s') // in main expression
			), 'DAY')
		);

		$query->registerRuntimeField('DATE', $monthExpression);

		$query->setSelect(array(
			'USER_ID',
			'DATE',
			new EntityExpressionField('TOTAL_SUM', 'SUM(%s)', 'TOTAL')
		));

		foreach (UserHourTable::getSectionNames() as $sectionName)
		{
			$query->addSelect(new EntityExpressionField($sectionName.'_SUM', 'SUM(%s)', $sectionName));
		}

		$query->setFilter(array(
			'=USER_ID' => $userId,
			'> array(
				ConvertTimeStamp($dateFrom->getTimestamp()),
				ConvertTimeStamp($dateTo->getTimestamp())
			)
		));

		$query->setGroup(array('USER_ID', 'DATE'));

		$keyFormat = 'Y-m';

		// top position
		$posQuery = new EntityQuery(UserDayTable::getEntity());

		$posQuery->setFilter(array(
			'> array(
				ConvertTimeStamp($dateFrom->getTimestamp()),
				ConvertTimeStamp($dateTo->getTimestamp())
			),
			'>LEAD_'.$posField => 0,
			'>SUM_'.$posField => 0
		));
	}

	// and continue with main data
	$query->setOrder('DATE');

	$result = $query->exec();

	$posTotal = 0;

	while ($row = $result->fetch())
	{
		// back-format keys
		foreach ($row as $k => $v)
		{
			if (mb_substr($k, -4) === '_SUM')
			{
				$row[mb_substr($k, 0, -4)] = $v;
				unset($row[$k]);
			}
		}

		/** @var TypeDateTime[] $row */
		if (!is_object($row['DATE']))
		{
			$key = $row['DATE'];
			$row['DATE'] = new TypeDateTime($row['DATE'], $keyFormat);
		}
		else
		{
			$key = $row['DATE']->format($keyFormat);
		}

		$data[$key] = $row;

		$posTotal += $row[$posField];
	}

	// now get position
	$posQuery->setSelect(array(
		'USER_ID',
		new EntityExpressionField('SUM_'.$posField, 'SUM(%s)', $posField),
		new EntityExpressionField('LEAD_'.$posField, 'CASE WHEN SUM(%s) > '.$posTotal.' THEN 1 ELSE 0 END', $posField)
	));

	$posQuery->registerRuntimeField('MYSELF', array(
		'data_type' => 'integer',
		'expression' => array('CASE WHEN %s = '.(int)$userId.' THEN 1 ELSE 0 END', 'USER_ID')
	));

	$posQuery->addOrder('SUM_'.$posField, 'DESC');
	$posQuery->addOrder('MYSELF', 'DESC');

	// backup query
	$topQuery = clone $posQuery;

	if ($posTotal > 0)
	{
		$result = $posQuery->exec();
		$position = $result->getSelectedRowsCount() + 1;
	}
	else
	{
		$position = 0;
	}

	if ($position < 5)
	{
		//we need all from the top 5
		$filter = $topQuery->getFilter();
		unset($filter['>LEAD_'.$posField]);
		$topQuery->setFilter($filter);

		$topQuery->setLimit(5);

		$result = $topQuery->exec();
	}

	$topUsers = array();

	while (($row = $result->fetch()) && count($topUsers) < 5)
	{
		$topUsers[count($topUsers)+1] = array('USER_ID' => $row['USER_ID'], 'ACTIVITY' => $row['SUM_'.$posField]);
	}

	if ($position >= 5)
	{
		$topUsers[$position] = array('USER_ID' => $userId, 'ACTIVITY' => $posTotal);
	}

	$allQuery = new EntityQuery($query->getEntity());
	$allQuery->setFilter(array_diff_key($query->getFilter(), ['=USER_ID' => null]));
	$allQuery->addSelect(new EntityExpressionField('ALL_ACTIVE_USERS', 'COUNT(DISTINCT %s)', 'USER_ID'));
	$res = $allQuery->exec()->fetch();

	return array('data' => $data, 'rating' => array('top' => $topUsers, 'position' => $position, 'range' => intval($res['ALL_ACTIVE_USERS'])));
}