Commit 2d334ba0 authored by drumm's avatar drumm
Browse files

Merge branch '3117465-remove-project_usage_week_project' into 7.x-2.x

parents f92c745d b7868fb6
......@@ -86,15 +86,9 @@ function project_usage_overview() {
//
// - We need to create a separate column for each week to allow sorting by
// usage in any week (the TableSort extender requires that anything you can
// sort on has a distinct field in the underlying query). However, some
// weeks may not have any usage data, forcing us to use a LEFT JOIN,
// rather than the more efficient INNER JOIN.
// - The LEFT JOINs mean we have to limit the entries in {node} so that
// we're not including things like forum posts, hence the WHERE IN below.
// - Each project may have multiple records in {project_usage_week_project}
// to track usage for API version. We need to SUM() them to get a total
// count forcing us to GROUP BY. Sadly, I can't explain why we need
// SUM(DISTINCT)... it just works(TM).
// sort on has a distinct field in the underlying query).
// - Each project will have multiple records in {project_usage_week_release}.
// We SUM() them, with each week’s timestamp, to get a total counts.
//
// Also, because the machine_name is an entity field, and there's no clean
// way to work that into an SQL query, then:
......@@ -108,78 +102,79 @@ function project_usage_overview() {
'data' => t('Project'),
),
);
$rows = array();
$usage_week_nids = db_query('SELECT DISTINCT(nid) FROM {project_usage_week_project}')->fetchCol();
if (!empty($usage_week_nids)) {
$query = db_select('node', 'n')
->fields('n', array('nid', 'title'))
->condition('n.nid', $usage_week_nids, 'IN')
->condition('n.status', NODE_PUBLISHED)
->groupBy('n.nid')
->groupBy('n.title')
->addTag('node_access');
foreach ($weeks as $i => $week) {
// Note that "{$i}" in these query snippets are used to add a week integer
// to the table and field aliases so we can uniquely identify each column
// for sorting purposes.
$query->addExpression("SUM(DISTINCT p{$i}.count)", "week{$i}");
$query->leftJoin('project_usage_week_project', "p{$i}", "n.nid = p{$i}.nid AND p{$i}.timestamp = :timestamp{$i}", array(":timestamp{$i}" => $week));
$header = array(
'field' => "week{$i}",
'data' => format_date($week, 'custom', variable_get('project_usage_date_short', PROJECT_USAGE_DATE_SHORT)),
'class' => array('project-usage-numbers'),
);
if ($i == 0) {
$header['sort'] = 'desc';
}
$headers[] = $header;
$query = db_select('node', 'n')
->fields('n', ['nid', 'title'])
->condition('n.status', NODE_PUBLISHED)
->groupBy('n.nid')
->addTag('node_access');
$query->innerJoin('project_usage_week_release', 'u', 'u.project_nid = n.nid AND timestamp >= :min_week', [
':min_week' => min($weeks),
]);
foreach ($weeks as $i => $week) {
// Note that "{$i}" in these query snippets are used to add a week integer
// to the table and field aliases so we can uniquely identify each column
// for sorting purposes.
$query->addExpression("SUM((u.timestamp = :week{$i}) * u.count)", "week{$i}", [
":week{$i}" => $week,
]);
$header = [
'field' => "week{$i}",
'data' => format_date($week, 'custom', variable_get('project_usage_date_short', PROJECT_USAGE_DATE_SHORT)),
'class' => ['project-usage-numbers'],
];
if ($i == 0) {
$header['sort'] = 'desc';
}
$headers[] = $header;
}
// Check for a cached page. The cache id needs to take into account the sort
// column and order.
$sort = tablesort_init($headers);
$cid = 'overview:' . $sort['sql'] . ':' . $sort['sort'] . ':' . pager_find_page();
$items_per_page = 100;
if ($cached = cache_get($cid, 'cache_project_usage')) {
$rows = $cached->data;
if ($total = cache_get('overview:total', 'cache_project_usage')) {
pager_default_initialize($total->data, $items_per_page);
}
// Check for a cached page. The cache id needs to take into account the sort
// column and order.
$sort = tablesort_init($headers);
$cid = 'overview:' . $sort['sql'] . ':' . $sort['sort'] . ':' . pager_find_page();
$items_per_page = 100;
if ($cached = cache_get($cid, 'cache_project_usage')) {
$rows = $cached->data;
if ($total = cache_get('overview:total', 'cache_project_usage')) {
pager_default_initialize($total->data, $items_per_page);
}
else {
$result = $query
->extend('TableSort')
->orderByHeader($headers)
->extend('PagerDefault')
->limit($items_per_page)
->execute();
$number = pager_find_page() * $items_per_page + 1;
$rows = array();
foreach ($result as $line) {
$machine_name = field_get_items('node', node_load($line->nid, NULL, TRUE), 'field_project_machine_name');
$row = array(
array('data' => $number++),
array('data' => l($line->title, 'project/usage/' . $machine_name[0]['value'])),
);
foreach ($weeks as $i => $week) {
$row[] = array(
'data' => number_format($line->{"week{$i}"}),
'class' => array('project-usage-numbers'),
);
}
$rows[] = $row;
}
else {
$query = $query->extend('TableSort')
->orderByHeader($headers)
->extend('PagerDefault')
->limit($items_per_page);
// Add ORDER BY NULL to the count query, overriding MySQL’s implicit GROUP
// BY ordering. This avoids a filesort.
$query->setCountQuery($count_query = $query->getCountQuery());
$count_query->getTables()['subquery']['table']->orderBy('NULL');
$result = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
$number = pager_find_page() * $items_per_page + 1;
$rows = [];
$projects = node_load_multiple(array_column($result, 'nid'));
foreach ($result as $line) {
$machine_name = field_get_items('node', $projects[$line['nid']], 'field_project_machine_name');
$row = [
['data' => $number++],
['data' => l($line['title'], 'project/usage/' . $machine_name[0]['value'])],
];
foreach ($weeks as $i => $week) {
$row[] = [
'data' => number_format($line["week{$i}"]),
'class' => ['project-usage-numbers'],
];
}
// Cache the completed page.
cache_set($cid, $rows, 'cache_project_usage', project_usage_cache_time());
// Cache number of projects.
global $pager_total_items;
cache_set('overview:total', reset($pager_total_items), 'cache_project_usage', project_usage_cache_time());
$rows[] = $row;
}
// Cache the completed page.
cache_set($cid, $rows, 'cache_project_usage', project_usage_cache_time());
// Cache number of projects.
cache_set('overview:total', $GLOBALS['pager_total_items'][0], 'cache_project_usage', project_usage_cache_time());
}
return array(
......
......@@ -203,54 +203,6 @@ function project_usage_node_view($node) {
}
}
/**
* Returns the TIDs for the active core compatibility taxonomy terms.
*
* @return array
*/
function project_usage_get_active_tids() {
static $active_tids;
if (!isset($active_tids)) {
$term_query = new EntityFieldQuery();
$result = $term_query->entityCondition('entity_type', 'taxonomy_term')
->fieldCondition('field_release_recommended', 'value', 1)
->execute();
$active_tids = array_keys($result['taxonomy_term']);
}
return $active_tids;
}
/**
* Returns the latest project usage counts for all active versions of the given
* project.
*
* @param array $nids
* The project node IDs.
*
* @return array
*/
function project_usage_get_project_usage_for_active_tids(array $nids) {
$usage = &drupal_static(__FUNCTION__, []);
$flipped_nids = array_fill_keys($nids, []);
if ($remaining_nids = array_diff($nids, array_keys($usage))) {
$usage += $flipped_nids;
module_load_include('inc', 'project_usage', 'includes/date_api');
$result = db_query('SELECT pu.nid, ttd.name, pu.count FROM {project_usage_week_project} pu INNER JOIN {taxonomy_term_data} ttd ON pu.tid = ttd.tid WHERE pu.nid IN (:nids) AND pu.tid IN (:tids) AND pu.timestamp = :timestamp', [
':nids' => $remaining_nids,
':tids' => project_usage_get_active_tids(),
':timestamp' => project_usage_get_current_active_week(),
]);
foreach ($result as $row) {
$usage[$row->nid][$row->name] = $row->count;
}
}
return array_intersect_key($usage, $flipped_nids);
}
/**
* Implements hook_restws_response_alter().
*/
......@@ -275,8 +227,39 @@ function project_usage_restws_response_alter(&$response, $function, $formatName,
}
}
if (!empty($project_nids)) {
foreach (project_usage_get_project_usage_for_active_tids($project_nids) as $nid => $usage) {
$response['list'][$nid_map[$nid]]['project_usage'] = $usage;
module_load_include('inc', 'project_usage', 'includes/date_api');
$result = db_query('SELECT pu.project_nid, pu.nid, pu.count FROM {project_usage_week_release} pu WHERE pu.project_nid IN (:nids) AND pu.timestamp = :timestamp', [
':nids' => $project_nids,
':timestamp' => project_usage_get_current_active_week(),
]);
$usage = [];
$release_nids = [];
foreach ($result as $row) {
$usage[$row->project_nid][$row->nid] = $row->count;
$release_nids[] = $row->nid;
}
$result = (new EntityFieldQuery())->entityCondition('entity_type', 'node')
->propertyCondition('status', NODE_PUBLISHED)
->propertyCondition('nid', $release_nids)
->execute();
if (!empty($result['node'])) {
field_attach_load('node', $result['node'], FIELD_LOAD_CURRENT, [
'field_id' => field_info_field('field_release_version')['id'],
]);
$release_branches = [];
foreach ($result['node'] as $release) {
$release_branches[$release->nid] = project_release_get_branch($release->field_release_version[LANGUAGE_NONE][0]['value']) . 'x';
}
foreach ($usage as $project_nid => $releases) {
foreach ($releases as $nid => $count) {
if (isset($response['list'][$nid_map[$project_nid]]['project_usage'][$release_branches[$nid]])) {
$response['list'][$nid_map[$project_nid]]['project_usage'][$release_branches[$nid]] += $count;
}
else {
$response['list'][$nid_map[$project_nid]]['project_usage'][$release_branches[$nid]] = $count;
}
}
}
}
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment