Exemple #1
0
function echo_main_dashboard_JSON($project_instance, $date)
{
    $start = microtime_float();
    $noforcelogin = 1;
    include_once dirname(dirname(dirname(__DIR__))) . '/config/config.php';
    require_once 'include/pdo.php';
    include 'public/login.php';
    include_once 'models/banner.php';
    include_once 'models/build.php';
    include_once 'models/subproject.php';
    $response = array();
    $db = pdo_connect("{$CDASH_DB_HOST}", "{$CDASH_DB_LOGIN}", "{$CDASH_DB_PASS}");
    if (!$db) {
        $response['error'] = 'Error connecting to CDash database server';
        echo json_encode($response);
        return;
    }
    if (!pdo_select_db("{$CDASH_DB_NAME}", $db)) {
        $response['error'] = 'Error selecting CDash database';
        echo json_encode($response);
        return;
    }
    $projectid = $project_instance->Id;
    $project = pdo_query("SELECT * FROM project WHERE id='{$projectid}'");
    if (pdo_num_rows($project) > 0) {
        $project_array = pdo_fetch_array($project);
        $projectname = $project_array['name'];
        if (isset($project_array['testingdataurl']) && $project_array['testingdataurl'] != '') {
            $testingdataurl = make_cdash_url(htmlentities($project_array['testingdataurl']));
        }
    } else {
        $response['error'] = "This project doesn't exist. Maybe the URL you are trying to access is wrong.";
        echo json_encode($response);
        return;
    }
    if (!checkUserPolicy(@$_SESSION['cdash']['loginid'], $project_array['id'], 1)) {
        $response['requirelogin'] = 1;
        echo json_encode($response);
        return;
    }
    $response = begin_JSON_response();
    $response['title'] = "CDash - {$projectname}";
    $response['feed'] = $CDASH_ENABLE_FEED;
    $response['showcalendar'] = 1;
    $Banner = new Banner();
    $Banner->SetProjectId(0);
    $text = $Banner->GetText();
    $banners = array();
    if ($text !== false) {
        $banners[] = $text;
    }
    $Banner->SetProjectId($projectid);
    $text = $Banner->GetText();
    if ($text !== false) {
        $banners[] = $text;
    }
    $response['banners'] = $banners;
    $site_response = array();
    // If parentid is set we need to lookup the date for this build
    // because it is not specified as a query string parameter.
    if (isset($_GET['parentid'])) {
        $parentid = pdo_real_escape_numeric($_GET['parentid']);
        $parent_build = new Build();
        $parent_build->Id = $parentid;
        $date = $parent_build->GetDate();
        $response['parentid'] = $parentid;
    } else {
        $response['parentid'] = -1;
    }
    list($previousdate, $currentstarttime, $nextdate) = get_dates($date, $project_array['nightlytime']);
    // Main dashboard section
    get_dashboard_JSON($projectname, $date, $response);
    $response['displaylabels'] = $project_array['displaylabels'];
    $page_id = 'index.php';
    $response['childview'] = 0;
    if ($CDASH_USE_LOCAL_DIRECTORY && file_exists('local/models/proProject.php')) {
        include_once 'local/models/proProject.php';
        $pro = new proProject();
        $pro->ProjectId = $projectid;
        $response['proedition'] = $pro->GetEdition(1);
    }
    if ($currentstarttime > time() && !isset($_GET['parentid'])) {
        $response['error'] = 'CDash cannot predict the future (yet)';
        echo json_encode($response);
        return;
    }
    // Menu definition
    $response['menu'] = array();
    $beginning_timestamp = $currentstarttime;
    $end_timestamp = $currentstarttime + 3600 * 24;
    $beginning_UTCDate = gmdate(FMT_DATETIME, $beginning_timestamp);
    $end_UTCDate = gmdate(FMT_DATETIME, $end_timestamp);
    if ($project_instance->GetNumberOfSubProjects($end_UTCDate) > 0) {
        $response['menu']['subprojects'] = 1;
    }
    if (isset($_GET['parentid'])) {
        $page_id = 'indexchildren.php';
        $response['childview'] = 1;
        // When a parentid is specified, we should link to the next build,
        // not the next day.
        $previous_buildid = $parent_build->GetPreviousBuildId();
        $current_buildid = $parent_build->GetCurrentBuildId();
        $next_buildid = $parent_build->GetNextBuildId();
        $base_url = 'index.php?project=' . urlencode($projectname);
        if ($previous_buildid > 0) {
            $response['menu']['previous'] = "{$base_url}&parentid={$previous_buildid}";
        } else {
            $response['menu']['noprevious'] = '1';
        }
        $response['menu']['current'] = "{$base_url}&parentid={$current_buildid}";
        if ($next_buildid > 0) {
            $response['menu']['next'] = "{$base_url}&parentid={$next_buildid}";
        } else {
            $response['menu']['nonext'] = '1';
        }
    } elseif (!has_next_date($date, $currentstarttime)) {
        $response['menu']['nonext'] = 1;
    }
    // Check if a SubProject parameter was specified.
    $subproject_name = @$_GET['subproject'];
    $subprojectid = false;
    if ($subproject_name) {
        $SubProject = new SubProject();
        $subproject_name = htmlspecialchars(pdo_real_escape_string($subproject_name));
        $SubProject->SetName($subproject_name);
        $SubProject->SetProjectId($projectid);
        $subprojectid = $SubProject->GetId();
        if ($subprojectid) {
            // Add an extra URL argument for the menu
            $response['extraurl'] = '&subproject=' . urlencode($subproject_name);
            $response['subprojectname'] = $subproject_name;
            $subproject_response = array();
            $subproject_response['name'] = $SubProject->GetName();
            $dependencies = $SubProject->GetDependencies();
            if ($dependencies) {
                $dependencies_response = array();
                foreach ($dependencies as $dependency) {
                    $dependency_response = array();
                    $DependProject = new SubProject();
                    $DependProject->SetId($dependency);
                    $dependency_response['name'] = $DependProject->GetName();
                    $dependency_response['name_encoded'] = urlencode($DependProject->GetName());
                    $dependency_response['nbuilderror'] = $DependProject->GetNumberOfErrorBuilds($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['nbuildwarning'] = $DependProject->GetNumberOfWarningBuilds($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['nbuildpass'] = $DependProject->GetNumberOfPassingBuilds($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['nconfigureerror'] = $DependProject->GetNumberOfErrorConfigures($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['nconfigurewarning'] = $DependProject->GetNumberOfWarningConfigures($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['nconfigurepass'] = $DependProject->GetNumberOfPassingConfigures($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['ntestpass'] = $DependProject->GetNumberOfPassingTests($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['ntestfail'] = $DependProject->GetNumberOfFailingTests($beginning_UTCDate, $end_UTCDate);
                    $dependency_response['ntestnotrun'] = $DependProject->GetNumberOfNotRunTests($beginning_UTCDate, $end_UTCDate);
                    if (strlen($DependProject->GetLastSubmission()) == 0) {
                        $dependency_response['lastsubmission'] = 'NA';
                    } else {
                        $dependency_response['lastsubmission'] = $DependProject->GetLastSubmission();
                    }
                    $dependencies_response[] = $dependency_response;
                }
                $subproject_response['dependencies'] = $dependencies_response;
            }
            $response['subproject'] = $subproject_response;
        } else {
            add_log("SubProject '{$subproject_name}' does not exist", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_WARNING);
        }
    }
    if (isset($testingdataurl)) {
        $response['testingdataurl'] = $testingdataurl;
    }
    // updates
    $updates_response = array();
    $gmdate = gmdate(FMT_DATE, $currentstarttime);
    $updates_response['url'] = 'viewChanges.php?project=' . urlencode($projectname) . '&date=' . $gmdate;
    $dailyupdate = pdo_query("SELECT count(ds.dailyupdateid),count(distinct ds.author)\n            FROM dailyupdate AS d LEFT JOIN dailyupdatefile AS ds ON (ds.dailyupdateid = d.id)\n            WHERE d.date='{$gmdate}' and d.projectid='{$projectid}' GROUP BY ds.dailyupdateid");
    if (pdo_num_rows($dailyupdate) > 0) {
        $dailupdate_array = pdo_fetch_array($dailyupdate);
        $updates_response['nchanges'] = $dailupdate_array[0];
        $updates_response['nauthors'] = $dailupdate_array[1];
    } else {
        $updates_response['nchanges'] = -1;
    }
    $updates_response['timestamp'] = date('l, F d Y - H:i T', $currentstarttime);
    $response['updates'] = $updates_response;
    // This array is used to track if expected builds are found or not.
    $received_builds = array();
    // Get info about our buildgroups.
    $buildgroups_response = array();
    $buildgroup_result = pdo_query("SELECT bg.id, bg.name, bgp.position FROM buildgroup AS bg\n            LEFT JOIN buildgroupposition AS bgp ON (bgp.buildgroupid=bg.id)\n            WHERE bg.projectid={$projectid} AND bg.starttime < '{$beginning_UTCDate}' AND\n            (bg.endtime > '{$beginning_UTCDate}' OR\n             bg.endtime='1980-01-01 00:00:00')");
    while ($buildgroup_array = pdo_fetch_array($buildgroup_result)) {
        $buildgroup_response = array();
        $groupname = $buildgroup_array['name'];
        $buildgroup_response['id'] = $buildgroup_array['id'];
        $buildgroup_response['name'] = $groupname;
        $buildgroup_response['linkname'] = str_replace(' ', '_', $groupname);
        $buildgroup_response['position'] = $buildgroup_array['position'];
        $buildgroup_response['numupdatedfiles'] = 0;
        $buildgroup_response['numupdateerror'] = 0;
        $buildgroup_response['numupdatewarning'] = 0;
        $buildgroup_response['updateduration'] = 0;
        $buildgroup_response['configureduration'] = 0;
        $buildgroup_response['numconfigureerror'] = 0;
        $buildgroup_response['numconfigurewarning'] = 0;
        $buildgroup_response['numbuilderror'] = 0;
        $buildgroup_response['numbuildwarning'] = 0;
        $buildgroup_response['numtestnotrun'] = 0;
        $buildgroup_response['numtestfail'] = 0;
        $buildgroup_response['numtestpass'] = 0;
        $buildgroup_response['testduration'] = 0;
        $buildgroup_response['hasupdatedata'] = false;
        $buildgroup_response['hasconfiguredata'] = false;
        $buildgroup_response['hascompilationdata'] = false;
        $buildgroup_response['hastestdata'] = false;
        $buildgroup_response['hasnormalbuilds'] = false;
        $buildgroup_response['hasparentbuilds'] = false;
        $buildgroup_response['builds'] = array();
        $received_builds[$groupname] = array();
        $buildgroups_response[] = $buildgroup_response;
    }
    // Filters:
    //
    $filterdata = get_filterdata_from_request($page_id);
    $filter_sql = $filterdata['sql'];
    $limit_sql = '';
    if ($filterdata['limit'] > 0) {
        $limit_sql = ' LIMIT ' . $filterdata['limit'];
    }
    unset($filterdata['xml']);
    $response['filterdata'] = $filterdata;
    $response['filterurl'] = get_filterurl();
    // Check if we should be excluding some SubProjects from our
    // build results.
    $include_subprojects = false;
    $exclude_subprojects = false;
    $included_subprojects = array();
    $excluded_subprojects = array();
    $selected_subprojects = '';
    $num_selected_subprojects = 0;
    $filter_on_labels = false;
    $share_label_filters = false;
    foreach ($filterdata['filters'] as $filter) {
        if ($filter['field'] == 'subprojects') {
            if ($filter['compare'] == 92) {
                $excluded_subprojects[] = $filter['value'];
            } elseif ($filter['compare'] == 93) {
                $included_subprojects[] = $filter['value'];
            }
        } elseif ($filter['field'] == 'label') {
            $filter_on_labels = true;
        }
    }
    if ($filter_on_labels && $project_instance->ShareLabelFilters) {
        $share_label_filters = true;
        $response['sharelabelfilters'] = true;
        $label_ids_array = get_label_ids_from_filterdata($filterdata);
        $label_ids = '(' . implode(', ', $label_ids_array) . ')';
    }
    // Include takes precedence over exclude.
    if (!empty($included_subprojects)) {
        $num_selected_subprojects = count($included_subprojects);
        $selected_subprojects = implode("','", $included_subprojects);
        $selected_subprojects = "('" . $selected_subprojects . "')";
        $include_subprojects = true;
    } elseif (!empty($excluded_subprojects)) {
        $num_selected_subprojects = count($excluded_subprojects);
        $selected_subprojects = implode("','", $excluded_subprojects);
        $selected_subprojects = "('" . $selected_subprojects . "')";
        $exclude_subprojects = true;
    }
    // add a request for the subproject
    $subprojectsql = '';
    if ($subproject_name && is_numeric($subprojectid)) {
        $subprojectsql = ' AND sp2b.subprojectid=' . $subprojectid;
    }
    // Use this as the default date clause, but if $filterdata has a date clause,
    // then cancel this one out:
    //
    $date_clause = "AND b.starttime<'{$end_UTCDate}' AND b.starttime>='{$beginning_UTCDate}' ";
    if ($filterdata['hasdateclause']) {
        $date_clause = '';
    }
    $parent_clause = '';
    if (isset($_GET['parentid'])) {
        // If we have a parentid, then we should only show children of that build.
        // Date becomes irrelevant in this case.
        $parent_clause = 'AND (b.parentid = ' . qnum($_GET['parentid']) . ') ';
        $date_clause = '';
    } elseif (empty($subprojectsql)) {
        // Only show builds that are not children.
        $parent_clause = 'AND (b.parentid = -1 OR b.parentid = 0) ';
    }
    $build_rows = array();
    // If the user is logged in we display if the build has some changes for him
    $userupdatesql = '';
    if (isset($_SESSION['cdash']) && array_key_exists('loginid', $_SESSION['cdash'])) {
        $userupdatesql = "(SELECT count(updatefile.updateid) FROM updatefile,build2update,user2project,\n            user2repository\n                WHERE build2update.buildid=b.id\n                AND build2update.updateid=updatefile.updateid\n                AND user2project.projectid=b.projectid\n                AND user2project.userid='" . $_SESSION['cdash']['loginid'] . "'\n                AND user2repository.userid=user2project.userid\n                AND (user2repository.projectid=0 OR user2repository.projectid=b.projectid)\n                AND user2repository.credential=updatefile.author) AS userupdates,";
    }
    $sql = get_index_query();
    $sql .= "WHERE b.projectid='{$projectid}' AND g.type='Daily'\n        {$parent_clause} {$date_clause} {$subprojectsql} {$filter_sql} {$limit_sql}";
    // We shouldn't get any builds for group that have been deleted (otherwise something is wrong)
    $builds = pdo_query($sql);
    // Log any errors
    $pdo_error = pdo_error();
    if (strlen($pdo_error) > 0) {
        add_log('SQL error: ' . $pdo_error, 'Index.php', LOG_ERR);
    }
    // Gather up results from this query.
    $build_data = array();
    while ($build_row = pdo_fetch_array($builds)) {
        $build_data[] = $build_row;
    }
    $dynamic_builds = array();
    if (empty($filter_sql)) {
        $dynamic_builds = get_dynamic_builds($projectid, $end_UTCDate);
        $build_data = array_merge($build_data, $dynamic_builds);
    }
    // Check if we need to summarize coverage by subproject groups.
    // This happens when we have subprojects and we're looking at the children
    // of a specific build.
    $coverage_groups = array();
    if (isset($_GET['parentid']) && $_GET['parentid'] > 0 && $project_instance->GetNumberOfSubProjects($end_UTCDate) > 0) {
        $groups = $project_instance->GetSubProjectGroups();
        foreach ($groups as $group) {
            // Keep track of coverage info on a per-group basis.
            $groupId = $group->GetId();
            $coverage_groups[$groupId] = array();
            $coverageThreshold = $group->GetCoverageThreshold();
            $coverage_groups[$groupId]['thresholdgreen'] = $coverageThreshold;
            $coverage_groups[$groupId]['thresholdyellow'] = $coverageThreshold * 0.7;
            $coverage_groups[$groupId]['label'] = $group->GetName();
            $coverage_groups[$groupId]['loctested'] = 0;
            $coverage_groups[$groupId]['locuntested'] = 0;
            $coverage_groups[$groupId]['position'] = $group->GetPosition();
            $coverage_groups[$groupId]['coverages'] = array();
        }
        if (count($groups) > 1) {
            // Add a Total group too.
            $coverage_groups[0] = array();
            $coverageThreshold = $project_array['coveragethreshold'];
            $coverage_groups[0]['thresholdgreen'] = $coverageThreshold;
            $coverage_groups[0]['thresholdyellow'] = $coverageThreshold * 0.7;
            $coverage_groups[0]['label'] = 'Total';
            $coverage_groups[0]['loctested'] = 0;
            $coverage_groups[0]['locuntested'] = 0;
            $coverage_groups[0]['position'] = 0;
        }
    }
    // Fetch all the rows of builds into a php array.
    // Compute additional fields for each row that we'll need to generate the xml.
    //
    $build_rows = array();
    foreach ($build_data as $build_row) {
        // Fields that come from the initial query:
        //  id
        //  sitename
        //  stamp
        //  name
        //  siteid
        //  type
        //  generator
        //  starttime
        //  endtime
        //  submittime
        //  groupname
        //  position
        //  groupid
        //  countupdatefiles
        //  updatestatus
        //  countupdatewarnings
        //  countbuildwarnings
        //  countbuilderrors
        //  countbuilderrordiff
        //  countbuildwarningdiff
        //  configureduration
        //  countconfigureerrors
        //  countconfigurewarnings
        //  countconfigurewarningdiff
        //  counttestsnotrun
        //  counttestsnotrundiff
        //  counttestsfailed
        //  counttestsfaileddiff
        //  counttestspassed
        //  counttestspasseddiff
        //  countteststimestatusfailed
        //  countteststimestatusfaileddiff
        //  testduration
        //
        // Fields that we add within this loop:
        //  maxstarttime
        //  buildids (array of buildids for summary rows)
        //  countbuildnotes (added by users)
        //  labels
        //  updateduration
        //  countupdateerrors
        //  test
        //
        $buildid = $build_row['id'];
        $groupid = $build_row['groupid'];
        $siteid = $build_row['siteid'];
        $parentid = $build_row['parentid'];
        $build_row['buildids'][] = $buildid;
        $build_row['maxstarttime'] = $build_row['starttime'];
        // Updates
        if (!empty($build_row['updatestarttime'])) {
            $build_row['updateduration'] = round((strtotime($build_row['updateendtime']) - strtotime($build_row['updatestarttime'])) / 60, 1);
        } else {
            $build_row['updateduration'] = 0;
        }
        if (strlen($build_row['updatestatus']) > 0 && $build_row['updatestatus'] != '0') {
            $build_row['countupdateerrors'] = 1;
        } else {
            $build_row['countupdateerrors'] = 0;
        }
        // Error/Warnings differences
        if (empty($build_row['countbuilderrordiffp'])) {
            $build_row['countbuilderrordiffp'] = 0;
        }
        if (empty($build_row['countbuilderrordiffn'])) {
            $build_row['countbuilderrordiffn'] = 0;
        }
        if (empty($build_row['countbuildwarningdiffp'])) {
            $build_row['countbuildwarningdiffp'] = 0;
        }
        if (empty($build_row['countbuildwarningdiffn'])) {
            $build_row['countbuildwarningdiffn'] = 0;
        }
        $build_row['hasconfigure'] = 0;
        if ($build_row['countconfigureerrors'] != -1 || $build_row['countconfigurewarnings'] != -1) {
            $build_row['hasconfigure'] = 1;
        }
        if ($build_row['countconfigureerrors'] < 0) {
            $build_row['countconfigureerrors'] = 0;
        }
        if ($build_row['countconfigurewarnings'] < 0) {
            $build_row['countconfigurewarnings'] = 0;
        }
        if (empty($build_row['countconfigurewarningdiff'])) {
            $build_row['countconfigurewarningdiff'] = 0;
        }
        $build_row['hastest'] = 0;
        if ($build_row['counttestsfailed'] != -1) {
            $build_row['hastest'] = 1;
        }
        if (empty($build_row['testduration'])) {
            $time_array = pdo_fetch_array(pdo_query("SELECT SUM(time) FROM build2test WHERE buildid='{$buildid}'"));
            $build_row['testduration'] = round($time_array[0], 1);
        } else {
            $build_row['testduration'] = round($build_row['testduration'], 1);
        }
        $build_rows[] = $build_row;
    }
    // Generate the JSON response from the rows of builds.
    $response['coverages'] = array();
    $response['dynamicanalyses'] = array();
    $num_nightly_coverages_builds = 0;
    $show_aggregate = false;
    $response['comparecoverage'] = 0;
    foreach ($build_rows as $build_array) {
        $groupid = $build_array['groupid'];
        // Find the buildgroup array for this build.
        $i = -1;
        for ($j = 0; $j < count($buildgroups_response); $j++) {
            if ($buildgroups_response[$j]['id'] == $groupid) {
                $i = $j;
                break;
            }
        }
        if ($i == -1) {
            add_log("BuildGroup '{$groupid}' not found for build #" . $build_array['id'], __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_WARNING);
            continue;
        }
        $groupname = $buildgroups_response[$i]['name'];
        $build_response = array();
        $received_builds[$groupname][] = $build_array['sitename'] . '_' . $build_array['name'];
        $buildid = $build_array['id'];
        $siteid = $build_array['siteid'];
        $countChildrenResult = pdo_single_row_query('SELECT count(id) AS numchildren
                FROM build WHERE parentid=' . qnum($buildid));
        $numchildren = $countChildrenResult['numchildren'];
        $build_response['numchildren'] = $numchildren;
        $child_builds_hyperlink = '';
        $selected_configure_errors = 0;
        $selected_configure_warnings = 0;
        $selected_configure_duration = 0;
        $selected_build_errors = 0;
        $selected_build_warnings = 0;
        $selected_build_duration = 0;
        $selected_tests_not_run = 0;
        $selected_tests_failed = 0;
        $selected_tests_passed = 0;
        $selected_test_duration = 0;
        if ($numchildren > 0) {
            $child_builds_hyperlink = get_child_builds_hyperlink($build_array['id'], $filterdata);
            $build_response['multiplebuildshyperlink'] = $child_builds_hyperlink;
            $buildgroups_response[$i]['hasparentbuilds'] = true;
            // Compute selected (excluded or included) SubProject results.
            if ($selected_subprojects) {
                $select_query = "\n                    SELECT configureerrors, configurewarnings, configureduration,\n                           builderrors, buildwarnings, buildduration,\n                           b.starttime, b.endtime, testnotrun, testfailed, testpassed,\n                           btt.time AS testduration, sb.name\n                    FROM build AS b\n                    INNER JOIN subproject2build AS sb2b ON (b.id = sb2b.buildid)\n                    INNER JOIN subproject AS sb ON (sb2b.subprojectid = sb.id)\n                    LEFT JOIN buildtesttime AS btt ON (b.id=btt.buildid)\n                    WHERE b.parentid={$buildid}\n                    AND sb.name IN {$selected_subprojects}";
                $select_results = pdo_query($select_query);
                while ($select_array = pdo_fetch_array($select_results)) {
                    $selected_configure_errors += max(0, $select_array['configureerrors']);
                    $selected_configure_warnings += max(0, $select_array['configurewarnings']);
                    $selected_configure_duration += max(0, $select_array['configureduration']);
                    $selected_build_errors += max(0, $select_array['builderrors']);
                    $selected_build_warnings += max(0, $select_array['buildwarnings']);
                    $selected_build_duration += max(0, $select_array['buildduration']);
                    $selected_tests_not_run += max(0, $select_array['testnotrun']);
                    $selected_tests_failed += max(0, $select_array['testfailed']);
                    $selected_tests_passed += max(0, $select_array['testpassed']);
                    $selected_test_duration += max(0, $select_array['testduration']);
                }
            }
        } else {
            $buildgroups_response[$i]['hasnormalbuilds'] = true;
        }
        if (strtolower($build_array['type']) == 'continuous') {
            $buildgroups_response[$i]['sorttype'] = 'time';
        }
        // Attempt to determine the platform based on the OSName and the buildname
        $buildplatform = '';
        if (strtolower(substr($build_array['osname'], 0, 7)) == 'windows') {
            $buildplatform = 'windows';
        } elseif (strtolower(substr($build_array['osname'], 0, 8)) == 'mac os x') {
            $buildplatform = 'mac';
        } elseif (strtolower(substr($build_array['osname'], 0, 5)) == 'linux' || strtolower(substr($build_array['osname'], 0, 3)) == 'aix') {
            $buildplatform = 'linux';
        } elseif (strtolower(substr($build_array['osname'], 0, 7)) == 'freebsd') {
            $buildplatform = 'freebsd';
        } elseif (strtolower(substr($build_array['osname'], 0, 3)) == 'gnu') {
            $buildplatform = 'gnu';
        }
        // Add link based on changeid if appropriate.
        $changelink = null;
        $changeicon = null;
        if ($build_array['changeid'] && $project_instance->CvsViewerType === 'github') {
            $changelink = $project_instance->CvsUrl . '/pull/' . $build_array['changeid'];
            $changeicon = 'img/Octocat.png';
        }
        if (isset($_GET['parentid'])) {
            if (empty($site_response)) {
                $site_response['site'] = $build_array['sitename'];
                $site_response['siteoutoforder'] = $build_array['siteoutoforder'];
                $site_response['siteid'] = $siteid;
                $site_response['buildname'] = $build_array['name'];
                $site_response['buildplatform'] = $buildplatform;
                $site_response['generator'] = $build_array['generator'];
                if (!is_null($changelink)) {
                    $site_response['changelink'] = $changelink;
                    $site_response['changeicon'] = $changeicon;
                }
            }
        } else {
            $build_response['site'] = $build_array['sitename'];
            $build_response['siteoutoforder'] = $build_array['siteoutoforder'];
            $build_response['siteid'] = $siteid;
            $build_response['buildname'] = $build_array['name'];
            $build_response['buildplatform'] = $buildplatform;
            if (!is_null($changelink)) {
                $build_response['changelink'] = $changelink;
                $build_response['changeicon'] = $changeicon;
            }
        }
        if (isset($build_array['userupdates'])) {
            $build_response['userupdates'] = $build_array['userupdates'];
        }
        $build_response['id'] = $build_array['id'];
        $build_response['done'] = $build_array['done'];
        $build_response['uploadfilecount'] = $build_array['builduploadfiles'];
        $build_response['buildnotes'] = $build_array['countbuildnotes'];
        $build_response['notes'] = $build_array['countnotes'];
        // Figure out how many labels to report for this build.
        if (!array_key_exists('numlabels', $build_array) || $build_array['numlabels'] == 0) {
            $num_labels = 0;
        } else {
            $num_labels = $build_array['numlabels'];
        }
        $label_query = 'SELECT l.text FROM label AS l
            INNER JOIN label2build AS l2b ON (l.id=l2b.labelid)
            INNER JOIN build AS b ON (l2b.buildid=b.id)
            WHERE b.id=' . qnum($buildid);
        $build_labels = array();
        if ($num_selected_subprojects > 0) {
            // Special handling for whitelisting/blacklisting SubProjects.
            if ($include_subprojects) {
                $num_labels = 0;
            }
            $labels_result = pdo_query($label_query);
            while ($label_row = pdo_fetch_array($labels_result)) {
                // Whitelist case
                if ($include_subprojects && in_array($label_row['text'], $included_subprojects)) {
                    $num_labels++;
                    $build_labels[] = $label_row['text'];
                }
                // Blacklist case
                if ($exclude_subprojects) {
                    if (in_array($label_row['text'], $excluded_subprojects)) {
                        $num_labels--;
                    } else {
                        $build_labels[] = $label_row['text'];
                    }
                }
            }
            if ($num_labels === 0) {
                // Skip this build entirely if none of its SubProjects
                // survived filtering.
                continue;
            }
        }
        // Assign a label to this build based on how many labels it has.
        if ($num_labels == 0) {
            $build_label = '(none)';
        } elseif ($num_labels == 1) {
            // Exactly one label for this build
            if (!empty($build_labels)) {
                // If we're whitelisting or blacklisting we've already figured
                // out what this label is.
                $build_label = $build_labels[0];
            } else {
                // Otherwise we look it up here.
                $label_result = pdo_single_row_query($label_query);
                $build_label = $label_result['text'];
            }
        } else {
            // More than one label, just report the number.
            $build_label = "({$num_labels} labels)";
        }
        $build_response['label'] = $build_label;
        // Calculate this build's total duration.
        $duration = strtotime($build_array['endtime']) - strtotime($build_array['starttime']);
        $build_response['time'] = time_difference($duration, true);
        $build_response['timefull'] = $duration;
        $update_response = array();
        $countupdatefiles = $build_array['countupdatefiles'];
        $update_response['files'] = $countupdatefiles;
        $buildgroups_response[$i]['numupdatedfiles'] += $countupdatefiles;
        $build_response['hasupdate'] = false;
        if (!empty($build_array['updatestarttime'])) {
            $build_response['hasupdate'] = true;
            if ($build_array['countupdateerrors'] > 0) {
                $update_response['errors'] = 1;
                $buildgroups_response[$i]['numupdateerror'] += 1;
            } else {
                $update_response['errors'] = 0;
                if ($build_array['countupdatewarnings'] > 0) {
                    $update_response['warning'] = 1;
                    $buildgroups_response[$i]['numupdatewarning'] += 1;
                }
            }
            $duration = $build_array['updateduration'];
            $update_response['time'] = time_difference($duration * 60.0, true);
            $update_response['timefull'] = $duration;
            $buildgroups_response[$i]['updateduration'] += $duration;
            $buildgroups_response[$i]['hasupdatedata'] = true;
            $build_response['update'] = $update_response;
        }
        $compilation_response = array();
        if ($build_array['countbuilderrors'] >= 0) {
            if ($include_subprojects) {
                $nerrors = $selected_build_errors;
                $nwarnings = $selected_build_warnings;
                $buildduration = $selected_build_duration;
            } else {
                $nerrors = $build_array['countbuilderrors'] - $selected_build_errors;
                $nwarnings = $build_array['countbuildwarnings'] - $selected_build_warnings;
                $buildduration = $build_array['buildduration'] - $selected_build_duration;
            }
            $compilation_response['error'] = $nerrors;
            $buildgroups_response[$i]['numbuilderror'] += $nerrors;
            $compilation_response['warning'] = $nwarnings;
            $buildgroups_response[$i]['numbuildwarning'] += $nwarnings;
            $compilation_response['time'] = time_difference($buildduration, true);
            $compilation_response['timefull'] = $buildduration;
            if (!$include_subprojects && !$exclude_subprojects) {
                // Don't show diff when filtering by SubProject.
                $compilation_response['nerrordiffp'] = $build_array['countbuilderrordiffp'];
                $compilation_response['nerrordiffn'] = $build_array['countbuilderrordiffn'];
                $compilation_response['nwarningdiffp'] = $build_array['countbuildwarningdiffp'];
                $compilation_response['nwarningdiffn'] = $build_array['countbuildwarningdiffn'];
            }
        }
        $build_response['hascompilation'] = false;
        if (!empty($compilation_response)) {
            $build_response['hascompilation'] = true;
            $build_response['compilation'] = $compilation_response;
            $buildgroups_response[$i]['hascompilationdata'] = true;
        }
        $build_response['hasconfigure'] = false;
        if ($build_array['hasconfigure'] != 0) {
            $build_response['hasconfigure'] = true;
            $configure_response = array();
            if ($include_subprojects) {
                $nconfigureerrors = $selected_configure_errors;
                $nconfigurewarnings = $selected_configure_warnings;
                $configureduration = $selected_configure_duration;
            } else {
                $nconfigureerrors = $build_array['countconfigureerrors'] - $selected_configure_errors;
                $nconfigurewarnings = $build_array['countconfigurewarnings'] - $selected_configure_warnings;
                $configureduration = $build_array['configureduration'] - $selected_configure_duration;
            }
            $configure_response['error'] = $nconfigureerrors;
            $buildgroups_response[$i]['numconfigureerror'] += $nconfigureerrors;
            $configure_response['warning'] = $nconfigurewarnings;
            $buildgroups_response[$i]['numconfigurewarning'] += $nconfigurewarnings;
            if (!$include_subprojects && !$exclude_subprojects) {
                $configure_response['warningdiff'] = $build_array['countconfigurewarningdiff'];
            }
            $configure_response['time'] = time_difference($configureduration, true);
            $configure_response['timefull'] = $configureduration;
            $build_response['configure'] = $configure_response;
            $buildgroups_response[$i]['hasconfiguredata'] = true;
            $buildgroups_response[$i]['configureduration'] += $configureduration;
        }
        $build_response['hastest'] = false;
        if ($build_array['hastest'] != 0) {
            $build_response['hastest'] = true;
            $buildgroups_response[$i]['hastestdata'] = true;
            $test_response = array();
            if ($include_subprojects) {
                $nnotrun = $selected_tests_not_run;
                $nfail = $selected_tests_failed;
                $npass = $selected_tests_passed;
                $testduration = $selected_test_duration;
            } else {
                $nnotrun = $build_array['counttestsnotrun'] - $selected_tests_not_run;
                $nfail = $build_array['counttestsfailed'] - $selected_tests_failed;
                $npass = $build_array['counttestspassed'] - $selected_tests_passed;
                $testduration = $build_array['testduration'] - $selected_test_duration;
            }
            if (!$include_subprojects && !$exclude_subprojects) {
                $test_response['nnotrundiffp'] = $build_array['counttestsnotrundiffp'];
                $test_response['nnotrundiffn'] = $build_array['counttestsnotrundiffn'];
                $test_response['nfaildiffp'] = $build_array['counttestsfaileddiffp'];
                $test_response['nfaildiffn'] = $build_array['counttestsfaileddiffn'];
                $test_response['npassdiffp'] = $build_array['counttestspasseddiffp'];
                $test_response['npassdiffn'] = $build_array['counttestspasseddiffn'];
            }
            if ($project_array['showtesttime'] == 1) {
                $test_response['timestatus'] = $build_array['countteststimestatusfailed'];
                $test_response['ntimediffp'] = $build_array['countteststimestatusfaileddiffp'];
                $test_response['ntimediffn'] = $build_array['countteststimestatusfaileddiffn'];
            }
            if ($share_label_filters) {
                $label_query_base = "SELECT b2t.status, b2t.newstatus\n                    FROM build2test AS b2t\n                    INNER JOIN label2test AS l2t ON\n                    (l2t.testid=b2t.testid AND l2t.buildid=b2t.buildid)\n                    WHERE b2t.buildid = '{$buildid}' AND\n                    l2t.labelid IN {$label_ids}";
                $label_filter_query = $label_query_base . $limit_sql;
                $labels_result = pdo_query($label_filter_query);
                $nnotrun = 0;
                $nfail = 0;
                $npass = 0;
                $test_response['nfaildiffp'] = 0;
                $test_response['nfaildiffn'] = 0;
                $test_response['npassdiffp'] = 0;
                $test_response['npassdiffn'] = 0;
                $test_response['nnotrundiffp'] = 0;
                $test_response['nnotrundiffn'] = 0;
                while ($label_row = pdo_fetch_array($labels_result)) {
                    switch ($label_row['status']) {
                        case 'passed':
                            $npass++;
                            if ($label_row['newstatus'] == 1) {
                                $test_response['npassdiffp']++;
                            }
                            break;
                        case 'failed':
                            $nfail++;
                            if ($label_row['newstatus'] == 1) {
                                $test_response['nfaildiffp']++;
                            }
                            break;
                        case 'notrun':
                            $nnotrun++;
                            if ($label_row['newstatus'] == 1) {
                                $test_response['nnotrundiffp']++;
                            }
                            break;
                    }
                }
            }
            $test_response['notrun'] = $nnotrun;
            $test_response['fail'] = $nfail;
            $test_response['pass'] = $npass;
            $buildgroups_response[$i]['numtestnotrun'] += $nnotrun;
            $buildgroups_response[$i]['numtestfail'] += $nfail;
            $buildgroups_response[$i]['numtestpass'] += $npass;
            $test_response['time'] = time_difference($testduration, true);
            $test_response['timefull'] = $testduration;
            $buildgroups_response[$i]['testduration'] += $testduration;
            $build_response['test'] = $test_response;
        }
        $starttimestamp = strtotime($build_array['starttime'] . ' UTC');
        $submittimestamp = strtotime($build_array['submittime'] . ' UTC');
        // Use the default timezone.
        $build_response['builddatefull'] = $starttimestamp;
        // If the data is more than 24h old then we switch from an elapsed to a normal representation
        if (time() - $starttimestamp < 86400) {
            $build_response['builddate'] = date(FMT_DATETIMEDISPLAY, $starttimestamp);
            $build_response['builddateelapsed'] = time_difference(time() - $starttimestamp, false, 'ago');
        } else {
            $build_response['builddateelapsed'] = date(FMT_DATETIMEDISPLAY, $starttimestamp);
            $build_response['builddate'] = time_difference(time() - $starttimestamp, false, 'ago');
        }
        $build_response['submitdate'] = date(FMT_DATETIMEDISPLAY, $submittimestamp);
        // Generate a string summarizing this build's timing.
        $timesummary = $build_response['builddate'];
        if ($build_response['hasupdate'] && array_key_exists('time', $build_response['update'])) {
            $timesummary .= ', Update time: ' . $build_response['update']['time'];
        }
        if ($build_response['hasconfigure'] && array_key_exists('time', $build_response['configure'])) {
            $timesummary .= ', Configure time: ' . $build_response['configure']['time'];
        }
        if ($build_response['hascompilation'] && array_key_exists('time', $build_response['compilation'])) {
            $timesummary .= ', Build time: ' . $build_response['compilation']['time'];
        }
        if ($build_response['hastest'] && array_key_exists('time', $build_response['test'])) {
            $timesummary .= ', Test time: ' . $build_response['test']['time'];
        }
        $timesummary .= ', Total time: ' . $build_response['time'];
        $build_response['timesummary'] = $timesummary;
        if ($include_subprojects || $exclude_subprojects) {
            // Check if this build should be filtered out now that its
            // numbers have been updated by the SubProject include/exclude
            // filter.
            if (!build_survives_filter($build_response, $filterdata)) {
                continue;
            }
        }
        if ($build_array['name'] != 'Aggregate Coverage') {
            $buildgroups_response[$i]['builds'][] = $build_response;
        }
        // Coverage
        //
        // Determine if this is a parent build with no actual coverage of its own.
        $linkToChildCoverage = false;
        if ($numchildren > 0) {
            $countChildrenResult = pdo_single_row_query('SELECT count(fileid) AS nfiles FROM coverage
                    WHERE buildid=' . qnum($buildid));
            if ($countChildrenResult['nfiles'] == 0) {
                $linkToChildCoverage = true;
            }
        }
        $coverageIsGrouped = false;
        $loctested = $build_array['loctested'];
        $locuntested = $build_array['locuntested'];
        if ($loctested + $locuntested > 0) {
            $coverage_response = array();
            $coverage_response['buildid'] = $build_array['id'];
            if ($linkToChildCoverage) {
                $coverage_response['childlink'] = "{$child_builds_hyperlink}##Coverage";
            }
            if ($build_array['type'] === 'Nightly' && $build_array['name'] !== 'Aggregate Coverage') {
                $num_nightly_coverages_builds++;
                if ($num_nightly_coverages_builds > 1) {
                    $show_aggregate = true;
                    if ($linkToChildCoverage) {
                        $response['comparecoverage'] = 1;
                    }
                }
            }
            $percent = round(compute_percentcoverage($loctested, $locuntested), 2);
            if ($build_array['subprojectgroup']) {
                $groupId = $build_array['subprojectgroup'];
                if (array_key_exists($groupId, $coverage_groups)) {
                    $coverageIsGrouped = true;
                    $coverageThreshold = $coverage_groups[$groupId]['thresholdgreen'];
                    $coverage_groups[$groupId]['loctested'] += $loctested;
                    $coverage_groups[$groupId]['locuntested'] += $locuntested;
                    if (count($coverage_groups) > 1) {
                        // Add to Total.
                        $coverage_groups[0]['loctested'] += $loctested;
                        $coverage_groups[0]['locuntested'] += $locuntested;
                    }
                }
            }
            $coverage_response['percentage'] = $percent;
            $coverage_response['locuntested'] = intval($locuntested);
            $coverage_response['loctested'] = intval($loctested);
            // Compute the diff
            if (!empty($build_array['loctesteddiff'])) {
                $loctesteddiff = $build_array['loctesteddiff'];
                $locuntesteddiff = $build_array['locuntesteddiff'];
                @($previouspercent = round(($loctested - $loctesteddiff) / ($loctested - $loctesteddiff + $locuntested - $locuntesteddiff) * 100, 2));
                $percentdiff = round($percent - $previouspercent, 2);
                $coverage_response['percentagediff'] = $percentdiff;
                $coverage_response['locuntesteddiff'] = $locuntesteddiff;
                $coverage_response['loctesteddiff'] = $loctesteddiff;
            }
            $starttimestamp = strtotime($build_array['starttime'] . ' UTC');
            $coverage_response['datefull'] = $starttimestamp;
            // If the data is more than 24h old then we switch from an elapsed to a normal representation
            if (time() - $starttimestamp < 86400) {
                $coverage_response['date'] = date(FMT_DATETIMEDISPLAY, $starttimestamp);
                $coverage_response['dateelapsed'] = time_difference(time() - $starttimestamp, false, 'ago');
            } else {
                $coverage_response['dateelapsed'] = date(FMT_DATETIMEDISPLAY, $starttimestamp);
                $coverage_response['date'] = time_difference(time() - $starttimestamp, false, 'ago');
            }
            // Are there labels for this build?
            //
            $coverage_response['label'] = $build_label;
            if ($coverageIsGrouped) {
                $coverage_groups[$groupId]['coverages'][] = $coverage_response;
            } else {
                $coverage_response['site'] = $build_array['sitename'];
                $coverage_response['buildname'] = $build_array['name'];
                $response['coverages'][] = $coverage_response;
            }
        }
        if (!$coverageIsGrouped) {
            $coverageThreshold = $project_array['coveragethreshold'];
            $response['thresholdgreen'] = $coverageThreshold;
            $response['thresholdyellow'] = $coverageThreshold * 0.7;
        }
        // Dynamic Analysis
        //
        if (!empty($build_array['checker'])) {
            // Determine if this is a parent build with no dynamic analysis
            // of its own.
            $linkToChildren = false;
            if ($numchildren > 0) {
                $countChildrenResult = pdo_single_row_query('SELECT count(id) AS num FROM dynamicanalysis
                        WHERE buildid=' . qnum($build_array['id']));
                if ($countChildrenResult['num'] == 0) {
                    $linkToChildren = true;
                }
            }
            $DA_response = array();
            $DA_response['site'] = $build_array['sitename'];
            $DA_response['buildname'] = $build_array['name'];
            $DA_response['buildid'] = $build_array['id'];
            $DA_response['checker'] = $build_array['checker'];
            $DA_response['defectcount'] = $build_array['numdefects'];
            $starttimestamp = strtotime($build_array['starttime'] . ' UTC');
            $DA_response['datefull'] = $starttimestamp;
            if ($linkToChildren) {
                $DA_response['childlink'] = "{$child_builds_hyperlink}##DynamicAnalysis";
            }
            // If the data is more than 24h old then we switch from an elapsed to a normal representation
            if (time() - $starttimestamp < 86400) {
                $DA_response['date'] = date(FMT_DATETIMEDISPLAY, $starttimestamp);
                $DA_response['dateelapsed'] = time_difference(time() - $starttimestamp, false, 'ago');
            } else {
                $DA_response['dateelapsed'] = date(FMT_DATETIMEDISPLAY, $starttimestamp);
                $DA_response['date'] = time_difference(time() - $starttimestamp, false, 'ago');
            }
            // Are there labels for this build?
            //
            $DA_response['label'] = $build_label;
            $response['dynamicanalyses'][] = $DA_response;
        }
    }
    // Put some finishing touches on our buildgroups now that we're done
    // iterating over all the builds.
    $addExpected = empty($filter_sql) && pdo_num_rows($builds) + count($dynamic_builds) > 0;
    for ($i = 0; $i < count($buildgroups_response); $i++) {
        $buildgroups_response[$i]['testduration'] = time_difference($buildgroups_response[$i]['testduration'], true);
        $num_expected_builds = 0;
        if (!$filter_sql) {
            $groupname = $buildgroups_response[$i]['name'];
            $expected_builds = add_expected_builds($buildgroups_response[$i]['id'], $currentstarttime, $received_builds[$groupname]);
            if (is_array($expected_builds)) {
                $num_expected_builds = count($expected_builds);
                $buildgroups_response[$i]['builds'] = array_merge($buildgroups_response[$i]['builds'], $expected_builds);
            }
        }
        // Show how many builds this group has.
        $num_builds = count($buildgroups_response[$i]['builds']);
        $num_builds_label = '';
        if ($num_expected_builds > 0) {
            $num_actual_builds = $num_builds - $num_expected_builds;
            $num_builds_label = "{$num_actual_builds} of {$num_builds} builds";
        } else {
            if ($num_builds === 1) {
                $num_builds_label = '1 build';
            } else {
                $num_builds_label = "{$num_builds} builds";
            }
        }
        $buildgroups_response[$i]['numbuildslabel'] = $num_builds_label;
    }
    // Create a separate "all buildgroups" section of our response.
    // This is used to allow project admins to move builds between groups.
    $response['all_buildgroups'] = array();
    foreach ($buildgroups_response as $group) {
        $response['all_buildgroups'][] = array('id' => $group['id'], 'name' => $group['name']);
    }
    // At this point it is safe to remove any empty buildgroups from our response.
    function is_buildgroup_nonempty($group)
    {
        return !empty($group['builds']);
    }
    $buildgroups_response = array_filter($buildgroups_response, 'is_buildgroup_nonempty');
    // Report buildgroups as a list, not an associative array.
    // Otherwise any missing buildgroups will cause our view to
    // not honor the order specified by the project admins.
    $buildgroups_response = array_values($buildgroups_response);
    // Remove Aggregate Coverage if it should not be displayed.
    if (!$show_aggregate) {
        for ($i = 0; $i < count($response['coverages']); $i++) {
            if ($response['coverages'][$i]['buildname'] === 'Aggregate Coverage') {
                unset($response['coverages'][$i]);
            }
        }
        $response['coverages'] = array_values($response['coverages']);
    }
    if ($response['childview'] == 1) {
        // Report number of children.
        if (!empty($buildgroups_response)) {
            $numchildren = count($buildgroups_response[0]['builds']);
        } else {
            $row = pdo_single_row_query('SELECT count(id) AS numchildren
                    FROM build WHERE parentid=' . qnum($parentid));
            $numchildren = $row['numchildren'];
        }
        $response['numchildren'] = $numchildren;
    }
    // Generate coverage by group here.
    if (!empty($coverage_groups)) {
        $response['coveragegroups'] = array();
        foreach ($coverage_groups as $groupid => $group) {
            $loctested = $group['loctested'];
            $locuntested = $group['locuntested'];
            if ($loctested == 0 && $locuntested == 0) {
                continue;
            }
            $percentage = round($loctested / ($loctested + $locuntested) * 100, 2);
            $group['percentage'] = $percentage;
            $group['id'] = $groupid;
            $response['coveragegroups'][] = $group;
        }
    }
    $response['buildgroups'] = $buildgroups_response;
    $response['enableTestTiming'] = $project_array['showtesttime'];
    $end = microtime_float();
    $response['generationtime'] = round($end - $start, 3);
    if (!empty($site_response)) {
        $response = array_merge($response, $site_response);
    }
    echo json_encode(cast_data_for_JSON($response));
}
Exemple #2
0
$start = microtime_float();
$db = pdo_connect("{$CDASH_DB_HOST}", "{$CDASH_DB_LOGIN}", "{$CDASH_DB_PASS}");
pdo_select_db("{$CDASH_DB_NAME}", $db);
if ($projectname == '') {
    $project = pdo_single_row_query("SELECT * FROM project LIMIT 1");
} else {
    $project = pdo_single_row_query("SELECT * FROM project WHERE name='{$projectname}'");
}
checkUserPolicy(@$_SESSION['cdash']['loginid'], $project['id']);
list($previousdate, $currentstarttime, $nextdate) = get_dates($date, $project['nightlytime']);
$xml = begin_XML_for_XSLT();
$xml .= "<title>CDash : " . $project['name'] . "</title>";
$xml .= get_cdash_dashboard_xml_by_name($project['name'], $date);
// Filters:
//
$filterdata = get_filterdata_from_request();
$filter_sql = $filterdata['sql'];
$limit_sql = '';
if ($filterdata['limit'] > 0) {
    $limit_sql = ' LIMIT ' . $filterdata['limit'];
}
$xml .= $filterdata['xml'];
$xml .= "<menu>";
if ($date == '') {
    $back = "index.php?project=" . urlencode($project['name']);
} else {
    $back = "index.php?project=" . urlencode($project['name']) . "&date=" . $date;
}
$xml .= add_XML_value("back", $back);
$limit_param = "&limit=" . $filterdata['limit'];
$xml .= add_XML_value("previous", "queryTests.php?project=" . urlencode($project['name']) . "&date=" . $previousdate . $limit_param);
Exemple #3
0
/** Generate the main dashboard XML */
function generate_main_dashboard_XML($project_instance, $date)
{
    $start = microtime_float();
    $noforcelogin = 1;
    include_once "cdash/config.php";
    require_once "cdash/pdo.php";
    include 'login.php';
    include_once "models/banner.php";
    include_once "models/subproject.php";
    $db = pdo_connect("{$CDASH_DB_HOST}", "{$CDASH_DB_LOGIN}", "{$CDASH_DB_PASS}");
    if (!$db) {
        echo "Error connecting to CDash database server<br>\n";
        return;
    }
    if (!pdo_select_db("{$CDASH_DB_NAME}", $db)) {
        echo "Error selecting CDash database<br>\n";
        return;
    }
    $projectid = $project_instance->Id;
    $project = pdo_query("SELECT * FROM project WHERE id='{$projectid}'");
    if (pdo_num_rows($project) > 0) {
        $project_array = pdo_fetch_array($project);
        $svnurl = make_cdash_url(htmlentities($project_array["cvsurl"]));
        $homeurl = make_cdash_url(htmlentities($project_array["homeurl"]));
        $bugurl = make_cdash_url(htmlentities($project_array["bugtrackerurl"]));
        $googletracker = htmlentities($project_array["googletracker"]);
        $docurl = make_cdash_url(htmlentities($project_array["documentationurl"]));
        $projectpublic = $project_array["public"];
        $projectname = $project_array["name"];
        if (isset($project_array['testingdataurl']) && $project_array['testingdataurl'] != '') {
            $testingdataurl = make_cdash_url(htmlentities($project_array['testingdataurl']));
        }
    } else {
        redirect_error('This project doesn\'t exist. Maybe the URL you are trying to access is wrong.');
        return false;
    }
    checkUserPolicy(@$_SESSION['cdash']['loginid'], $project_array["id"]);
    $xml = begin_XML_for_XSLT();
    $xml .= "<title>CDash - " . $projectname . "</title>";
    $Banner = new Banner();
    $Banner->SetProjectId(0);
    $text = $Banner->GetText();
    if ($text !== false) {
        $xml .= "<banner>";
        $xml .= add_XML_value("text", $text);
        $xml .= "</banner>";
    }
    $Banner->SetProjectId($projectid);
    $text = $Banner->GetText();
    if ($text !== false) {
        $xml .= "<banner>";
        $xml .= add_XML_value("text", $text);
        $xml .= "</banner>";
    }
    $sitexml = "";
    list($previousdate, $currentstarttime, $nextdate) = get_dates($date, $project_array["nightlytime"]);
    $logoid = getLogoID($projectid);
    // Main dashboard section
    $xml .= "<dashboard>\n  <datetime>" . date("l, F d Y H:i:s T", time()) . "</datetime>\n  <date>" . $date . "</date>\n  <unixtimestamp>" . $currentstarttime . "</unixtimestamp>\n  <svn>" . $svnurl . "</svn>\n  <bugtracker>" . $bugurl . "</bugtracker>\n  <googletracker>" . $googletracker . "</googletracker>\n  <documentation>" . $docurl . "</documentation>\n  <logoid>" . $logoid . "</logoid>\n  <projectid>" . $projectid . "</projectid>\n  <projectname>" . $projectname . "</projectname>\n  <projectname_encoded>" . urlencode($projectname) . "</projectname_encoded>\n  <previousdate>" . $previousdate . "</previousdate>\n  <projectpublic>" . $projectpublic . "</projectpublic>\n  <displaylabels>" . $project_array["displaylabels"] . "</displaylabels>\n  <nextdate>" . $nextdate . "</nextdate>";
    if (empty($project_array["homeurl"])) {
        $xml .= "<home>index.php?project=" . urlencode($projectname) . "</home>";
    } else {
        $xml .= "<home>" . $homeurl . "</home>";
    }
    if (isset($_GET["parentid"])) {
        $xml .= "<childview>1</childview>";
    } else {
        $xml .= "<childview>0</childview>";
    }
    if ($CDASH_USE_LOCAL_DIRECTORY && file_exists("local/models/proProject.php")) {
        include_once "local/models/proProject.php";
        $pro = new proProject();
        $pro->ProjectId = $projectid;
        $xml .= "<proedition>" . $pro->GetEdition(1) . "</proedition>";
    }
    if ($currentstarttime > time()) {
        $xml .= "<future>1</future>";
    } else {
        $xml .= "<future>0</future>";
    }
    $xml .= "</dashboard>";
    // Menu definition
    $xml .= "<menu>";
    if (!has_next_date($date, $currentstarttime)) {
        $xml .= add_XML_value("nonext", "1");
    }
    $xml .= "</menu>";
    // Check the builds
    $beginning_timestamp = $currentstarttime;
    $end_timestamp = $currentstarttime + 3600 * 24;
    $beginning_UTCDate = gmdate(FMT_DATETIME, $beginning_timestamp);
    $end_UTCDate = gmdate(FMT_DATETIME, $end_timestamp);
    // Add the extra url if necessary
    if (isset($_GET["display"]) && $_GET["display"] == "project") {
        $xml .= add_XML_value("extraurl", "&display=project");
    }
    // If we have a subproject
    $subproject_name = @$_GET["subproject"];
    $subprojectid = false;
    if ($subproject_name) {
        $SubProject = new SubProject();
        $subproject_name = htmlspecialchars(pdo_real_escape_string($subproject_name));
        $SubProject->SetName($subproject_name);
        $SubProject->SetProjectId($projectid);
        $subprojectid = $SubProject->GetId();
        if ($subprojectid) {
            // Add an extra URL argument for the menu
            $xml .= add_XML_value("extraurl", "&subproject=" . urlencode($subproject_name));
            $xml .= add_XML_value("subprojectname", $subproject_name);
            $xml .= "<subproject>";
            $xml .= add_XML_value("name", $SubProject->GetName());
            $rowparity = 0;
            $dependencies = $SubProject->GetDependencies();
            if ($dependencies) {
                foreach ($dependencies as $dependency) {
                    $xml .= "<dependency>";
                    $DependProject = new SubProject();
                    $DependProject->SetId($dependency);
                    $xml .= add_XML_value("rowparity", $rowparity);
                    $xml .= add_XML_value("name", $DependProject->GetName());
                    $xml .= add_XML_value("name_encoded", urlencode($DependProject->GetName()));
                    $xml .= add_XML_value("nbuilderror", $DependProject->GetNumberOfErrorBuilds($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("nbuildwarning", $DependProject->GetNumberOfWarningBuilds($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("nbuildpass", $DependProject->GetNumberOfPassingBuilds($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("nconfigureerror", $DependProject->GetNumberOfErrorConfigures($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("nconfigurewarning", $DependProject->GetNumberOfWarningConfigures($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("nconfigurepass", $DependProject->GetNumberOfPassingConfigures($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("ntestpass", $DependProject->GetNumberOfPassingTests($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("ntestfail", $DependProject->GetNumberOfFailingTests($beginning_UTCDate, $end_UTCDate));
                    $xml .= add_XML_value("ntestnotrun", $DependProject->GetNumberOfNotRunTests($beginning_UTCDate, $end_UTCDate));
                    if (strlen($DependProject->GetLastSubmission()) == 0) {
                        $xml .= add_XML_value("lastsubmission", "NA");
                    } else {
                        $xml .= add_XML_value("lastsubmission", $DependProject->GetLastSubmission());
                    }
                    $rowparity = $rowparity == 1 ? 0 : 1;
                    $xml .= "</dependency>";
                }
            }
            $xml .= "</subproject>";
        } else {
            add_log("SubProject '{$subproject_name}' does not exist", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_WARNING);
        }
    }
    if (isset($testingdataurl)) {
        $xml .= add_XML_value("testingdataurl", $testingdataurl);
    }
    // updates
    $xml .= "<updates>";
    $gmdate = gmdate(FMT_DATE, $currentstarttime);
    $xml .= "<url>viewChanges.php?project=" . urlencode($projectname) . "&amp;date=" . $gmdate . "</url>";
    $dailyupdate = pdo_query("SELECT count(ds.dailyupdateid),count(distinct ds.author)\n                            FROM dailyupdate AS d LEFT JOIN dailyupdatefile AS ds ON (ds.dailyupdateid = d.id)\n                            WHERE d.date='{$gmdate}' and d.projectid='{$projectid}' GROUP BY ds.dailyupdateid");
    if (pdo_num_rows($dailyupdate) > 0) {
        $dailupdate_array = pdo_fetch_array($dailyupdate);
        $xml .= "<nchanges>" . $dailupdate_array[0] . "</nchanges>";
        $xml .= "<nauthors>" . $dailupdate_array[1] . "</nauthors>";
    } else {
        $xml .= "<nchanges>-1</nchanges>";
    }
    $xml .= add_XML_value("timestamp", date("l, F d Y - H:i T", $currentstarttime));
    $xml .= "</updates>";
    // User
    if (isset($_SESSION['cdash'])) {
        $xml .= "<user>";
        $userid = $_SESSION['cdash']['loginid'];
        $user2project = pdo_query("SELECT role FROM user2project WHERE userid='{$userid}' and projectid='{$projectid}'");
        $user2project_array = pdo_fetch_array($user2project);
        $user = pdo_query("SELECT admin FROM " . qid("user") . "  WHERE id='{$userid}'");
        $user_array = pdo_fetch_array($user);
        $xml .= add_XML_value("id", $userid);
        $isadmin = 0;
        if ($user2project_array["role"] > 1 || $user_array["admin"]) {
            $isadmin = 1;
        }
        $xml .= add_XML_value("admin", $isadmin);
        $xml .= add_XML_value("projectrole", $user2project_array['role']);
        $xml .= "</user>";
    }
    // Filters:
    //
    $filterdata = get_filterdata_from_request();
    $filter_sql = $filterdata['sql'];
    $limit_sql = '';
    if ($filterdata['limit'] > 0) {
        $limit_sql = ' LIMIT ' . $filterdata['limit'];
    }
    $xml .= $filterdata['xml'];
    // Local function to add expected builds
    function add_expected_builds($groupid, $currentstarttime, $received_builds)
    {
        include 'cdash/config.php';
        $currentUTCTime = gmdate(FMT_DATETIME, $currentstarttime + 3600 * 24);
        $xml = "";
        $build2grouprule = pdo_query("SELECT g.siteid,g.buildname,g.buildtype,s.name,s.outoforder FROM build2grouprule AS g,site as s\n                                  WHERE g.expected='1' AND g.groupid='{$groupid}' AND s.id=g.siteid\n                                  AND g.starttime<'{$currentUTCTime}' AND (g.endtime>'{$currentUTCTime}' OR g.endtime='1980-01-01 00:00:00')\n                                  ");
        while ($build2grouprule_array = pdo_fetch_array($build2grouprule)) {
            $key = $build2grouprule_array["name"] . "_" . $build2grouprule_array["buildname"];
            if (array_search($key, $received_builds) === FALSE) {
                $site = $build2grouprule_array["name"];
                $siteid = $build2grouprule_array["siteid"];
                $siteoutoforder = $build2grouprule_array["outoforder"];
                $buildtype = $build2grouprule_array["buildtype"];
                $buildname = $build2grouprule_array["buildname"];
                $xml .= "<build>";
                $xml .= add_XML_value("site", $site);
                $xml .= add_XML_value("siteoutoforder", $siteoutoforder);
                $xml .= add_XML_value("siteid", $siteid);
                $xml .= add_XML_value("buildname", $buildname);
                $xml .= add_XML_value("buildtype", $buildtype);
                $xml .= add_XML_value("buildgroupid", $groupid);
                $xml .= add_XML_value("expected", "1");
                // compute historical average to get approximate expected time
                // PostgreSQL doesn't have the necessary functions for this
                if ($CDASH_DB_TYPE == 'pgsql') {
                    $query = pdo_query("SELECT submittime FROM build,build2group\n                              WHERE build2group.buildid=build.id AND siteid='{$siteid}' AND name='{$buildname}'\n                              AND type='{$buildtype}' AND build2group.groupid='{$groupid}'\n                              ORDER BY id DESC LIMIT 5");
                    $time = 0;
                    while ($query_array = pdo_fetch_array($query)) {
                        $time += strtotime(date("H:i:s", strtotime($query_array['submittime'])));
                    }
                    if (pdo_num_rows($query) > 0) {
                        $time /= pdo_num_rows($query);
                    }
                    $nextExpected = strtotime(date("H:i:s", $time) . " UTC");
                } else {
                    $query = pdo_query("SELECT AVG(TIME_TO_SEC(TIME(submittime))) FROM (SELECT submittime FROM build,build2group\n                                WHERE build2group.buildid=build.id AND siteid='{$siteid}' AND name='{$buildname}'\n                                AND type='{$buildtype}' AND build2group.groupid='{$groupid}'\n                                ORDER BY id DESC LIMIT 5) as t");
                    $query_array = pdo_fetch_array($query);
                    $time = $query_array[0];
                    $hours = floor($time / 3600);
                    $time = $time % 3600;
                    $minutes = floor($time / 60);
                    $seconds = $time % 60;
                    $nextExpected = strtotime($hours . ":" . $minutes . ":" . $seconds . " UTC");
                }
                $divname = $build2grouprule_array["siteid"] . "_" . $build2grouprule_array["buildname"];
                $divname = str_replace("+", "_", $divname);
                $divname = str_replace(".", "_", $divname);
                $divname = str_replace(':', "_", $divname);
                $divname = str_replace(' ', "_", $divname);
                $xml .= add_XML_value("expecteddivname", $divname);
                $xml .= add_XML_value("submitdate", "No Submission");
                $xml .= add_XML_value("expectedstarttime", date(FMT_TIME, $nextExpected));
                $xml .= "</build>";
            }
        }
        return $xml;
    }
    // add a request for the subproject
    $subprojectsql = "";
    $subprojecttablesql = "";
    if ($subproject_name && is_numeric($subprojectid)) {
        $subprojectsql = " AND sp2b.subprojectid=" . $subprojectid;
    }
    // Use this as the default date clause, but if $filterdata has a date clause,
    // then cancel this one out:
    //
    $date_clause = "AND b.starttime<'{$end_UTCDate}' AND b.starttime>='{$beginning_UTCDate}' ";
    if ($filterdata['hasdateclause']) {
        $date_clause = '';
    }
    $parent_clause = "";
    if (isset($_GET["parentid"])) {
        // If we have a parentid, then we should only show children of that build.
        // Date becomes irrelevant in this case.
        $parent_clause = "AND (b.parentid = " . qnum($_GET["parentid"]) . ") ";
        $date_clause = "";
    } else {
        if (empty($subprojectsql)) {
            // Only show builds that are not children.
            $parent_clause = "AND (b.parentid = -1 OR b.parentid = 0) ";
        }
    }
    $build_rows = array();
    // If the user is logged in we display if the build has some changes for him
    $userupdatesql = "";
    if (isset($_SESSION['cdash'])) {
        $userupdatesql = "(SELECT count(updatefile.updateid) FROM updatefile,build2update,user2project,\n                      user2repository\n                      WHERE build2update.buildid=b.id\n                      AND build2update.updateid=updatefile.updateid\n                      AND user2project.projectid=b.projectid\n                      AND user2project.userid='" . $_SESSION['cdash']['loginid'] . "'\n                      AND user2repository.userid=user2project.userid\n                      AND (user2repository.projectid=0 OR user2repository.projectid=b.projectid)\n                      AND user2repository.credential=updatefile.author) AS userupdates,";
    }
    // Postgres differs from MySQL on how to aggregate results
    // into a single column.
    $label_sql = "";
    $groupby_sql = "";
    if ($CDASH_DB_TYPE != 'pgsql') {
        $label_sql = "GROUP_CONCAT(l.text SEPARATOR ', ') AS labels,";
        $groupby_sql = " GROUP BY b.id";
    }
    $sql = "SELECT b.id,b.siteid,b.parentid,\n                  bu.status AS updatestatus,\n                  i.osname AS osname,\n                  bu.starttime AS updatestarttime,\n                  bu.endtime AS updateendtime,\n                  bu.nfiles AS countupdatefiles,\n                  bu.warnings AS countupdatewarnings,\n                  c.status AS configurestatus,\n                  c.starttime AS configurestarttime,\n                  c.endtime AS configureendtime,\n                  be_diff.difference_positive AS countbuilderrordiffp,\n                  be_diff.difference_negative AS countbuilderrordiffn,\n                  bw_diff.difference_positive AS countbuildwarningdiffp,\n                  bw_diff.difference_negative AS countbuildwarningdiffn,\n                  ce_diff.difference AS countconfigurewarningdiff,\n                  btt.time AS testsduration,\n                  tnotrun_diff.difference_positive AS counttestsnotrundiffp,\n                  tnotrun_diff.difference_negative AS counttestsnotrundiffn,\n                  tfailed_diff.difference_positive AS counttestsfaileddiffp,\n                  tfailed_diff.difference_negative AS counttestsfaileddiffn,\n                  tpassed_diff.difference_positive AS counttestspasseddiffp,\n                  tpassed_diff.difference_negative AS counttestspasseddiffn,\n                  tstatusfailed_diff.difference_positive AS countteststimestatusfaileddiffp,\n                  tstatusfailed_diff.difference_negative AS countteststimestatusfaileddiffn,\n                  (SELECT count(buildid) FROM build2note WHERE buildid=b.id)  AS countnotes,\n                  (SELECT count(buildid) FROM buildnote WHERE buildid=b.id) AS countbuildnotes," . $userupdatesql . "\n                  s.name AS sitename,\n                  s.outoforder AS siteoutoforder,\n                  b.stamp,b.name,b.type,b.generator,b.starttime,b.endtime,b.submittime,\n                  b.configureerrors AS countconfigureerrors,\n                  b.configurewarnings AS countconfigurewarnings,\n                  b.builderrors AS countbuilderrors,\n                  b.buildwarnings AS countbuildwarnings,\n                  b.testnotrun AS counttestsnotrun,\n                  b.testfailed AS counttestsfailed,\n                  b.testpassed AS counttestspassed,\n                  b.testtimestatusfailed AS countteststimestatusfailed,\n                  sp.id AS subprojectid,\n                  sp.groupid AS subprojectgroup,\n                  g.name as groupname,gp.position,g.id as groupid,\n                  {$label_sql}\n                  (SELECT count(buildid) FROM errorlog WHERE buildid=b.id) AS nerrorlog,\n                  (SELECT count(buildid) FROM build2uploadfile WHERE buildid=b.id) AS builduploadfiles\n                  FROM build AS b\n                  LEFT JOIN build2group AS b2g ON (b2g.buildid=b.id)\n                  LEFT JOIN buildgroup AS g ON (g.id=b2g.groupid)\n                  LEFT JOIN buildgroupposition AS gp ON (gp.buildgroupid=g.id)\n                  LEFT JOIN site AS s ON (s.id=b.siteid)\n                  LEFT JOIN build2update AS b2u ON (b2u.buildid=b.id)\n                  LEFT JOIN buildupdate AS bu ON (b2u.updateid=bu.id)\n                  LEFT JOIN configure AS c ON (c.buildid=b.id)\n                  LEFT JOIN buildinformation AS i ON (i.buildid=b.id)\n                  LEFT JOIN builderrordiff AS be_diff ON (be_diff.buildid=b.id AND be_diff.type=0)\n                  LEFT JOIN builderrordiff AS bw_diff ON (bw_diff.buildid=b.id AND bw_diff.type=1)\n                  LEFT JOIN configureerrordiff AS ce_diff ON (ce_diff.buildid=b.id AND ce_diff.type=1)\n                  LEFT JOIN buildtesttime AS btt ON (btt.buildid=b.id)\n                  LEFT JOIN testdiff AS tnotrun_diff ON (tnotrun_diff.buildid=b.id AND tnotrun_diff.type=0)\n                  LEFT JOIN testdiff AS tfailed_diff ON (tfailed_diff.buildid=b.id AND tfailed_diff.type=1)\n                  LEFT JOIN testdiff AS tpassed_diff ON (tpassed_diff.buildid=b.id AND tpassed_diff.type=2)\n                  LEFT JOIN testdiff AS tstatusfailed_diff ON (tstatusfailed_diff.buildid=b.id AND tstatusfailed_diff.type=3)\n                  LEFT JOIN subproject2build AS sp2b ON (sp2b.buildid = b.id)\n                  LEFT JOIN subproject as sp ON (sp2b.subprojectid = sp.id)\n                  LEFT JOIN label2build AS l2b ON (l2b.buildid = b.id)\n                  LEFT JOIN label AS l ON (l.id = l2b.labelid)\n                  WHERE b.projectid='{$projectid}' AND g.type='Daily'\n                  {$parent_clause} {$date_clause}\n                  " . $subprojectsql . " " . $filter_sql . " " . $groupby_sql . $limit_sql;
    // We shouldn't get any builds for group that have been deleted (otherwise something is wrong)
    $builds = pdo_query($sql);
    echo pdo_error();
    // Sort results from this query.
    // We used to do this in MySQL with the following directive:
    // ORDER BY gp.position ASC,b.name ASC,b.siteid ASC,b.stamp DESC
    // But this dramatically impacted performance when the number of rows was
    // relatively large (in the thousands).  So now we accomplish the same
    // sorting within PHP instead.
    $build_data = array();
    while ($build_row = pdo_fetch_array($builds)) {
        $build_data[] = $build_row;
    }
    $dynamic_builds = array();
    if (empty($filter_sql)) {
        $dynamic_builds = get_dynamic_builds($projectid);
        $build_data = array_merge($build_data, $dynamic_builds);
    }
    $positions = array();
    $names = array();
    $siteids = array();
    $stamps = array();
    foreach ($build_data as $key => $row) {
        $positions[$key] = $row['position'];
        $names[$key] = $row['name'];
        $siteids[$key] = $row['siteid'];
        $stamps[$key] = $row['stamp'];
    }
    array_multisort($positions, SORT_ASC, $names, SORT_ASC, $siteids, SORT_ASC, $stamps, SORT_DESC, $build_data);
    // The SQL results are ordered by group so this should work
    // Group position have to be continuous
    $previousgroupposition = -1;
    $received_builds = array();
    // Find the last position of the group
    $groupposition_array = pdo_fetch_array(pdo_query("SELECT gp.position FROM buildgroupposition AS gp,buildgroup AS g\n                                                        WHERE g.projectid='{$projectid}' AND g.id=gp.buildgroupid\n                                                        AND gp.starttime<'{$end_UTCDate}' AND (gp.endtime>'{$end_UTCDate}' OR gp.endtime='1980-01-01 00:00:00')\n                                                        ORDER BY gp.position DESC LIMIT 1"));
    $lastGroupPosition = $groupposition_array["position"];
    // Check if we need to summarize coverage by subproject groups.
    // This happens when we have subprojects and we're looking at the children
    // of a specific build.
    $subproject_groups = array();
    $subproject_group_coverage = array();
    if (isset($_GET["parentid"]) && $_GET["parentid"] > 0 && $project_instance->GetNumberOfSubProjects($end_UTCDate) > 0) {
        $groups = $project_instance->GetSubProjectGroups();
        foreach ($groups as $group) {
            // Create an Id -> Object mapping for our subproject groups.
            $subproject_groups[$group->GetId()] = $group;
            // Also keep track of coverage info on a per-group basis.
            $subproject_group_coverage[$group->GetId()] = array();
            $subproject_group_coverage[$group->GetId()]["tested"] = 0;
            $subproject_group_coverage[$group->GetId()]["untested"] = 0;
        }
    }
    // Fetch all the rows of builds into a php array.
    // Compute additional fields for each row that we'll need to generate the xml.
    //
    $build_rows = array();
    foreach ($build_data as $build_row) {
        // Fields that come from the initial query:
        //  id
        //  sitename
        //  stamp
        //  name
        //  siteid
        //  type
        //  generator
        //  starttime
        //  endtime
        //  submittime
        //  groupname
        //  position
        //  groupid
        //  countupdatefiles
        //  updatestatus
        //  countupdatewarnings
        //  countbuildwarnings
        //  countbuilderrors
        //  countbuilderrordiff
        //  countbuildwarningdiff
        //  configurestatus
        //  countconfigureerrors
        //  countconfigurewarnings
        //  countconfigurewarningdiff
        //  counttestsnotrun
        //  counttestsnotrundiff
        //  counttestsfailed
        //  counttestsfaileddiff
        //  counttestspassed
        //  counttestspasseddiff
        //  countteststimestatusfailed
        //  countteststimestatusfaileddiff
        //  testsduration
        //
        // Fields that we add within this loop:
        //  maxstarttime
        //  buildids (array of buildids for summary rows)
        //  countbuildnotes (added by users)
        //  labels
        //  updateduration
        //  countupdateerrors
        //  buildduration
        //  hasconfigurestatus
        //  configureduration
        //  test
        //
        $buildid = $build_row['id'];
        $groupid = $build_row['groupid'];
        $siteid = $build_row['siteid'];
        $parentid = $build_row['parentid'];
        $build_row['buildids'][] = $buildid;
        $build_row['maxstarttime'] = $build_row['starttime'];
        // Split out labels
        if (empty($build_row['labels'])) {
            $build_row['labels'] = array();
        } else {
            $build_row['labels'] = explode(",", $build_row['labels']);
        }
        // If this is a parent build get the labels from all the children too.
        if ($parentid == -1) {
            $query = "SELECT l.text FROM build AS b\n        INNER JOIN label2build AS l2b ON l2b.buildid = b.id\n        INNER JOIN label AS l ON l.id = l2b.labelid\n        WHERE b.parentid='{$buildid}'";
            $childLabelsResult = pdo_query($query);
            while ($childLabelsArray = pdo_fetch_array($childLabelsResult)) {
                $build_row['labels'][] = $childLabelsArray['text'];
            }
        }
        // Updates
        if (!empty($build_row['updatestarttime'])) {
            $build_row['updateduration'] = round((strtotime($build_row['updateendtime']) - strtotime($build_row['updatestarttime'])) / 60, 1);
        } else {
            $build_row['updateduration'] = 0;
        }
        if (strlen($build_row["updatestatus"]) > 0 && $build_row["updatestatus"] != "0") {
            $build_row['countupdateerrors'] = 1;
        } else {
            $build_row['countupdateerrors'] = 0;
        }
        $build_row['buildduration'] = round((strtotime($build_row['endtime']) - strtotime($build_row['starttime'])) / 60, 1);
        // Error/Warnings differences
        if (empty($build_row['countbuilderrordiffp'])) {
            $build_row['countbuilderrordiffp'] = 0;
        }
        if (empty($build_row['countbuilderrordiffn'])) {
            $build_row['countbuilderrordiffn'] = 0;
        }
        if (empty($build_row['countbuildwarningdiffp'])) {
            $build_row['countbuildwarningdiffp'] = 0;
        }
        if (empty($build_row['countbuildwarningdiffn'])) {
            $build_row['countbuildwarningdiffn'] = 0;
        }
        if ($build_row['countconfigureerrors'] < 0) {
            $build_row['countconfigureerrors'] = 0;
        }
        if ($build_row['countconfigurewarnings'] < 0) {
            $build_row['countconfigurewarnings'] = 0;
        }
        $build_row['hasconfigurestatus'] = 0;
        $build_row['configureduration'] = 0;
        if (strlen($build_row['configurestatus']) > 0) {
            $build_row['hasconfigurestatus'] = 1;
            $build_row['configureduration'] = round((strtotime($build_row["configureendtime"]) - strtotime($build_row["configurestarttime"])) / 60, 1);
        }
        if (empty($build_row['countconfigurewarningdiff'])) {
            $build_row['countconfigurewarningdiff'] = 0;
        }
        $build_row['hastest'] = 0;
        if ($build_row['counttestsfailed'] != -1) {
            $build_row['hastest'] = 1;
        }
        if (empty($build_row['testsduration'])) {
            $time_array = pdo_fetch_array(pdo_query("SELECT SUM(time) FROM build2test WHERE buildid='{$buildid}'"));
            $build_row['testsduration'] = round($time_array[0] / 60, 1);
        } else {
            $build_row['testsduration'] = round($build_row['testsduration'], 1);
            //already in minutes
        }
        $build_rows[] = $build_row;
    }
    // Generate the xml from the rows of builds:
    //
    $totalUpdatedFiles = 0;
    $totalUpdateError = 0;
    $totalUpdateWarning = 0;
    $totalUpdateDuration = 0;
    $totalConfigureError = 0;
    $totalConfigureWarning = 0;
    $totalConfigureDuration = 0;
    $totalerrors = 0;
    $totalwarnings = 0;
    $totalBuildDuration = 0;
    $totalnotrun = 0;
    $totalfail = 0;
    $totalpass = 0;
    $totalTestsDuration = 0;
    foreach ($build_rows as $build_array) {
        $groupposition = $build_array["position"];
        if ($previousgroupposition != $groupposition) {
            $groupname = $build_array["groupname"];
            if ($previousgroupposition != -1) {
                if (!$filter_sql) {
                    $xml .= add_expected_builds($groupid, $currentstarttime, $received_builds);
                }
                $xml .= add_XML_value("totalUpdatedFiles", $totalUpdatedFiles);
                $xml .= add_XML_value("totalUpdateError", $totalUpdateError);
                $xml .= add_XML_value("totalUpdateWarning", $totalUpdateWarning);
                $xml .= add_XML_value("totalUpdateDuration", $totalUpdateDuration);
                $xml .= add_XML_value("totalConfigureDuration", $totalConfigureDuration);
                $xml .= add_XML_value("totalConfigureError", $totalConfigureError);
                $xml .= add_XML_value("totalConfigureWarning", $totalConfigureWarning);
                $xml .= add_XML_value("totalError", $totalerrors);
                $xml .= add_XML_value("totalWarning", $totalwarnings);
                $xml .= add_XML_value("totalBuildDuration", $totalBuildDuration);
                $xml .= add_XML_value("totalNotRun", $totalnotrun);
                $xml .= add_XML_value("totalFail", $totalfail);
                $xml .= add_XML_value("totalPass", $totalpass);
                $xml .= add_XML_value("totalTestsDuration", time_difference($totalTestsDuration * 60.0, true));
                $xml .= "</buildgroup>";
            }
            // We assume that the group position are continuous in N
            // So we fill in the gap if we are jumping
            $prevpos = $previousgroupposition + 1;
            if ($prevpos == 0) {
                $prevpos = 1;
            }
            for ($i = $prevpos; $i < $groupposition; $i++) {
                $group = pdo_fetch_array(pdo_query("SELECT g.name,g.id FROM buildgroup AS g,buildgroupposition AS gp WHERE g.id=gp.buildgroupid\n                                                AND gp.position='{$i}' AND g.projectid='{$projectid}'\n                                                AND gp.starttime<'{$end_UTCDate}' AND (gp.endtime>'{$end_UTCDate}'  OR gp.endtime='1980-01-01 00:00:00')\n                                                "));
                $xml .= "<buildgroup>";
                $xml .= add_buildgroup_sortlist($group['name']);
                $xml .= add_XML_value("name", $group["name"]);
                $xml .= add_XML_value("linkname", str_replace(" ", "_", $group["name"]));
                $xml .= add_XML_value("id", $group["id"]);
                if (!$filter_sql) {
                    $xml .= add_expected_builds($group["id"], $currentstarttime, $received_builds);
                }
                $xml .= "</buildgroup>";
            }
            $xml .= "<buildgroup>";
            $totalUpdatedFiles = 0;
            $totalUpdateError = 0;
            $totalUpdateWarning = 0;
            $totalUpdateDuration = 0;
            $totalConfigureError = 0;
            $totalConfigureWarning = 0;
            $totalConfigureDuration = 0;
            $totalerrors = 0;
            $totalwarnings = 0;
            $totalBuildDuration = 0;
            $totalnotrun = 0;
            $totalfail = 0;
            $totalpass = 0;
            $totalTestsDuration = 0;
            $xml .= add_buildgroup_sortlist($groupname);
            $xml .= add_XML_value("name", $groupname);
            $xml .= add_XML_value("linkname", str_replace(" ", "_", $groupname));
            $xml .= add_XML_value("id", $build_array["groupid"]);
            $received_builds = array();
            $previousgroupposition = $groupposition;
        }
        $xml .= "<build>";
        $received_builds[] = $build_array["sitename"] . "_" . $build_array["name"];
        $buildid = $build_array["id"];
        $groupid = $build_array["groupid"];
        $siteid = $build_array["siteid"];
        $countChildrenResult = pdo_single_row_query("SELECT count(id) AS nchildren FROM build WHERE parentid=" . qnum($buildid));
        $countchildren = $countChildrenResult['nchildren'];
        $xml .= add_XML_value("countchildren", $countchildren);
        $child_builds_hyperlink = "";
        if ($countchildren > 0) {
            $child_builds_hyperlink = get_child_builds_hyperlink($build_array["id"], $filterdata);
            $xml .= add_XML_value("multiplebuildshyperlink", $child_builds_hyperlink);
        }
        $xml .= add_XML_value("type", strtolower($build_array["type"]));
        // Attempt to determine the platform based on the OSName and the buildname
        $buildplatform = '';
        if (strtolower(substr($build_array["osname"], 0, 7)) == 'windows') {
            $buildplatform = 'windows';
        } else {
            if (strtolower(substr($build_array["osname"], 0, 8)) == 'mac os x') {
                $buildplatform = 'mac';
            } else {
                if (strtolower(substr($build_array["osname"], 0, 5)) == 'linux' || strtolower(substr($build_array["osname"], 0, 3)) == 'aix') {
                    $buildplatform = 'linux';
                } else {
                    if (strtolower(substr($build_array["osname"], 0, 7)) == 'freebsd') {
                        $buildplatform = 'freebsd';
                    } else {
                        if (strtolower(substr($build_array["osname"], 0, 3)) == 'gnu') {
                            $buildplatform = 'gnu';
                        }
                    }
                }
            }
        }
        if (isset($_GET["parentid"]) && empty($sitexml)) {
            $sitexml .= add_XML_value("site", $build_array["sitename"]);
            $sitexml .= add_XML_value("siteoutoforder", $build_array["siteoutoforder"]);
            $sitexml .= add_XML_value("siteid", $siteid);
            $sitexml .= add_XML_value("buildname", $build_array["name"]);
            $sitexml .= add_XML_value("buildplatform", $buildplatform);
        } else {
            $xml .= add_XML_value("site", $build_array["sitename"]);
            $xml .= add_XML_value("siteoutoforder", $build_array["siteoutoforder"]);
            $xml .= add_XML_value("siteid", $siteid);
            $xml .= add_XML_value("buildname", $build_array["name"]);
            $xml .= add_XML_value("buildplatform", $buildplatform);
        }
        if (isset($build_array["userupdates"])) {
            $xml .= add_XML_value("userupdates", $build_array["userupdates"]);
        }
        $xml .= add_XML_value("buildid", $build_array["id"]);
        $xml .= add_XML_value("generator", $build_array["generator"]);
        $xml .= add_XML_value("upload-file-count", $build_array["builduploadfiles"]);
        if ($build_array['countbuildnotes'] > 0) {
            $xml .= add_XML_value("buildnote", "1");
        }
        if ($build_array['countnotes'] > 0) {
            $xml .= add_XML_value("note", "1");
        }
        // Are there labels for this build?
        //
        $labels_array = $build_array['labels'];
        if (!empty($labels_array)) {
            $xml .= '<labels>';
            foreach ($labels_array as $label) {
                $xml .= add_XML_value("label", $label);
            }
            $xml .= '</labels>';
        }
        $xml .= "<update>";
        $countupdatefiles = $build_array['countupdatefiles'];
        $totalUpdatedFiles += $countupdatefiles;
        $xml .= add_XML_value("files", $countupdatefiles);
        if (!empty($build_array['updatestarttime'])) {
            $xml .= add_XML_value("defined", 1);
            if ($build_array['countupdateerrors'] > 0) {
                $xml .= add_XML_value("errors", 1);
                $totalUpdateError += 1;
            } else {
                $xml .= add_XML_value("errors", 0);
                if ($build_array['countupdatewarnings'] > 0) {
                    $xml .= add_XML_value("warning", 1);
                    $totalUpdateWarning += 1;
                }
            }
            $duration = $build_array['updateduration'];
            $totalUpdateDuration += $duration;
            $xml .= add_XML_value("time", time_difference($duration * 60.0, true));
            $xml .= add_XML_value("timefull", $duration);
        }
        // end if we have an update
        $xml .= "</update>";
        $xml .= "<compilation>";
        if ($build_array['countbuilderrors'] >= 0) {
            $nerrors = $build_array['countbuilderrors'];
            $totalerrors += $nerrors;
            $xml .= add_XML_value("error", $nerrors);
            $nwarnings = $build_array['countbuildwarnings'];
            $totalwarnings += $nwarnings;
            $xml .= add_XML_value("warning", $nwarnings);
            $duration = $build_array['buildduration'];
            $totalBuildDuration += $duration;
            $xml .= add_XML_value("time", time_difference($duration * 60.0, true));
            $xml .= add_XML_value("timefull", $duration);
            $diff = $build_array['countbuilderrordiffp'];
            if ($diff != 0) {
                $xml .= add_XML_value("nerrordiffp", $diff);
            }
            $diff = $build_array['countbuilderrordiffn'];
            if ($diff != 0) {
                $xml .= add_XML_value("nerrordiffn", $diff);
            }
            $diff = $build_array['countbuildwarningdiffp'];
            if ($diff != 0) {
                $xml .= add_XML_value("nwarningdiffp", $diff);
            }
            $diff = $build_array['countbuildwarningdiffn'];
            if ($diff != 0) {
                $xml .= add_XML_value("nwarningdiffn", $diff);
            }
        }
        $xml .= "</compilation>";
        $xml .= "<configure>";
        $xml .= add_XML_value("error", $build_array['countconfigureerrors']);
        $totalConfigureError += $build_array['countconfigureerrors'];
        $nconfigurewarnings = $build_array['countconfigurewarnings'];
        $xml .= add_XML_value("warning", $nconfigurewarnings);
        $totalConfigureWarning += $nconfigurewarnings;
        $diff = $build_array['countconfigurewarningdiff'];
        if ($diff != 0) {
            $xml .= add_XML_value("warningdiff", $diff);
        }
        if ($build_array['hasconfigurestatus'] != 0) {
            $duration = $build_array['configureduration'];
            $totalConfigureDuration += $duration;
            $xml .= add_XML_value("time", time_difference($duration * 60.0, true));
            $xml .= add_XML_value("timefull", $duration);
        }
        $xml .= "</configure>";
        if ($build_array['hastest'] != 0) {
            $xml .= "<test>";
            $nnotrun = $build_array['counttestsnotrun'];
            if ($build_array['counttestsnotrundiffp'] != 0) {
                $xml .= add_XML_value("nnotrundiffp", $build_array['counttestsnotrundiffp']);
            }
            if ($build_array['counttestsnotrundiffn'] != 0) {
                $xml .= add_XML_value("nnotrundiffn", $build_array['counttestsnotrundiffn']);
            }
            $nfail = $build_array['counttestsfailed'];
            if ($build_array['counttestsfaileddiffp'] != 0) {
                $xml .= add_XML_value("nfaildiffp", $build_array['counttestsfaileddiffp']);
            }
            if ($build_array['counttestsfaileddiffn'] != 0) {
                $xml .= add_XML_value("nfaildiffn", $build_array['counttestsfaileddiffn']);
            }
            $npass = $build_array['counttestspassed'];
            if ($build_array['counttestspasseddiffp'] != 0) {
                $xml .= add_XML_value("npassdiffp", $build_array['counttestspasseddiffp']);
            }
            if ($build_array['counttestspasseddiffn'] != 0) {
                $xml .= add_XML_value("npassdiffn", $build_array['counttestspasseddiffn']);
            }
            if ($project_array["showtesttime"] == 1) {
                $xml .= add_XML_value("timestatus", $build_array['countteststimestatusfailed']);
                if ($build_array['countteststimestatusfaileddiffp'] != 0) {
                    $xml .= add_XML_value("ntimediffp", $build_array['countteststimestatusfaileddiffp']);
                }
                if ($build_array['countteststimestatusfaileddiffn'] != 0) {
                    $xml .= add_XML_value("ntimediffn", $build_array['countteststimestatusfaileddiffn']);
                }
            }
            $totalnotrun += $nnotrun;
            $totalfail += $nfail;
            $totalpass += $npass;
            $xml .= add_XML_value("notrun", $nnotrun);
            $xml .= add_XML_value("fail", $nfail);
            $xml .= add_XML_value("pass", $npass);
            $duration = $build_array['testsduration'];
            $totalTestsDuration += $duration;
            $xml .= add_XML_value("time", time_difference($duration * 60.0, true));
            $xml .= add_XML_value("timefull", $duration);
            $xml .= "</test>";
        }
        $starttimestamp = strtotime($build_array["starttime"] . " UTC");
        $submittimestamp = strtotime($build_array["submittime"] . " UTC");
        $xml .= add_XML_value("builddatefull", $starttimestamp);
        // use the default timezone
        // If the data is more than 24h old then we switch from an elapsed to a normal representation
        if (time() - $starttimestamp < 86400) {
            $xml .= add_XML_value("builddate", date(FMT_DATETIMEDISPLAY, $starttimestamp));
            // use the default timezone
            $xml .= add_XML_value("builddateelapsed", time_difference(time() - $starttimestamp, false, 'ago'));
            // use the default timezone
        } else {
            $xml .= add_XML_value("builddateelapsed", date(FMT_DATETIMEDISPLAY, $starttimestamp));
            // use the default timezone
            $xml .= add_XML_value("builddate", time_difference(time() - $starttimestamp, false, 'ago'));
            // use the default timezone
        }
        $xml .= add_XML_value("submitdate", date(FMT_DATETIMEDISPLAY, $submittimestamp));
        // use the default timezone
        $xml .= add_XML_value("nerrorlog", $build_array["nerrorlog"]);
        // use the default timezone
        $xml .= "</build>";
        // Coverage
        //
        // Determine if this is a parent build with no actual coverage of its own.
        $linkToChildCoverage = false;
        if ($countchildren > 0) {
            $countChildrenResult = pdo_single_row_query("SELECT count(fileid) AS nfiles FROM coverage\n         WHERE buildid=" . qnum($buildid));
            if ($countChildrenResult['nfiles'] == 0) {
                $linkToChildCoverage = true;
            }
        }
        $coverages = pdo_query("SELECT * FROM coveragesummary WHERE buildid='{$buildid}'");
        while ($coverage_array = pdo_fetch_array($coverages)) {
            $xml .= "<coverage>";
            $xml .= "  <site>" . $build_array["sitename"] . "</site>";
            $xml .= "  <buildname>" . $build_array["name"] . "</buildname>";
            $xml .= "  <buildid>" . $build_array["id"] . "</buildid>";
            if ($linkToChildCoverage) {
                $xml .= add_XML_value("childlink", "{$child_builds_hyperlink}#Coverage");
            }
            @($percent = round($coverage_array["loctested"] / ($coverage_array["loctested"] + $coverage_array["locuntested"]) * 100, 2));
            $coverageThreshold = $project_array["coveragethreshold"];
            if ($build_array["subprojectgroup"]) {
                $groupId = $build_array["subprojectgroup"];
                $coverageThreshold = $subproject_groups[$groupId]->GetCoverageThreshold();
                $subproject_group_coverage[$groupId]["tested"] += $coverage_array["loctested"];
                $subproject_group_coverage[$groupId]["untested"] += $coverage_array["locuntested"];
                $xml .= "  <group>{$groupId}</group>";
            }
            $xml .= "  <percentage>" . $percent . "</percentage>";
            $xml .= "  <percentagegreen>" . $coverageThreshold . "</percentagegreen>";
            $xml .= "  <fail>" . $coverage_array["locuntested"] . "</fail>";
            $xml .= "  <pass>" . $coverage_array["loctested"] . "</pass>";
            // Compute the diff
            $coveragediff = pdo_query("SELECT * FROM coveragesummarydiff WHERE buildid='{$buildid}'");
            if (pdo_num_rows($coveragediff) > 0) {
                $coveragediff_array = pdo_fetch_array($coveragediff);
                $loctesteddiff = $coveragediff_array['loctested'];
                $locuntesteddiff = $coveragediff_array['locuntested'];
                @($previouspercent = round(($coverage_array["loctested"] - $loctesteddiff) / ($coverage_array["loctested"] - $loctesteddiff + $coverage_array["locuntested"] - $locuntesteddiff) * 100, 2));
                $percentdiff = round($percent - $previouspercent, 2);
                $xml .= "<percentagediff>" . $percentdiff . "</percentagediff>";
                $xml .= "<faildiff>" . $locuntesteddiff . "</faildiff>";
                $xml .= "<passdiff>" . $loctesteddiff . "</passdiff>";
            }
            $starttimestamp = strtotime($build_array["starttime"] . " UTC");
            $xml .= add_XML_value("datefull", $starttimestamp);
            // use the default timezone
            // If the data is more than 24h old then we switch from an elapsed to a normal representation
            if (time() - $starttimestamp < 86400) {
                $xml .= add_XML_value("date", date(FMT_DATETIMEDISPLAY, $starttimestamp));
                // use the default timezone
                $xml .= add_XML_value("dateelapsed", time_difference(time() - $starttimestamp, false, 'ago'));
                // use the default timezone
            } else {
                $xml .= add_XML_value("dateelapsed", date(FMT_DATETIMEDISPLAY, $starttimestamp));
                // use the default timezone
                $xml .= add_XML_value("date", time_difference(time() - $starttimestamp, false, 'ago'));
                // use the default timezone
            }
            // Are there labels for this build?
            //
            if (!empty($labels_array)) {
                $xml .= '<labels>';
                foreach ($labels_array as $label) {
                    $xml .= add_XML_value("label", $label);
                }
                $xml .= '</labels>';
            }
            $xml .= "</coverage>";
        }
        // end coverage
        // Dynamic Analysis
        //
        $dynanalysis = pdo_query("SELECT checker,status FROM dynamicanalysis WHERE buildid='{$buildid}' LIMIT 1");
        while ($dynanalysis_array = pdo_fetch_array($dynanalysis)) {
            $xml .= "<dynamicanalysis>";
            $xml .= "  <site>" . $build_array["sitename"] . "</site>";
            $xml .= "  <buildname>" . $build_array["name"] . "</buildname>";
            $xml .= "  <buildid>" . $build_array["id"] . "</buildid>";
            $xml .= "  <checker>" . $dynanalysis_array["checker"] . "</checker>";
            $xml .= "  <status>" . $dynanalysis_array["status"] . "</status>";
            $defect = pdo_query("SELECT sum(dd.value) FROM dynamicanalysisdefect AS dd,dynamicanalysis as d\n                                              WHERE d.buildid='{$buildid}' AND dd.dynamicanalysisid=d.id");
            $defectcount = pdo_fetch_array($defect);
            if (!isset($defectcount[0])) {
                $defectcounts = 0;
            } else {
                $defectcounts = $defectcount[0];
            }
            $xml .= "  <defectcount>" . $defectcounts . "</defectcount>";
            $starttimestamp = strtotime($build_array["starttime"] . " UTC");
            $xml .= add_XML_value("datefull", $starttimestamp);
            // use the default timezone
            // If the data is more than 24h old then we switch from an elapsed to a normal representation
            if (time() - $starttimestamp < 86400) {
                $xml .= add_XML_value("date", date(FMT_DATETIMEDISPLAY, $starttimestamp));
                // use the default timezone
                $xml .= add_XML_value("dateelapsed", time_difference(time() - $starttimestamp, false, 'ago'));
                // use the default timezone
            } else {
                $xml .= add_XML_value("dateelapsed", date(FMT_DATETIMEDISPLAY, $starttimestamp));
                // use the default timezone
                $xml .= add_XML_value("date", time_difference(time() - $starttimestamp, false, 'ago'));
                // use the default timezone
            }
            // Are there labels for this build?
            //
            if (!empty($labels_array)) {
                $xml .= '<labels>';
                foreach ($labels_array as $label) {
                    $xml .= add_XML_value("label", $label);
                }
                $xml .= '</labels>';
            }
            $xml .= "</dynamicanalysis>";
        }
        // end dynamicanalysis
    }
    // end looping through builds
    if (pdo_num_rows($builds) + count($dynamic_builds) > 0) {
        if (!$filter_sql) {
            $xml .= add_expected_builds($groupid, $currentstarttime, $received_builds);
        }
        $xml .= add_XML_value("totalUpdatedFiles", $totalUpdatedFiles);
        $xml .= add_XML_value("totalUpdateError", $totalUpdateError);
        $xml .= add_XML_value("totalUpdateWarning", $totalUpdateWarning);
        $xml .= add_XML_value("totalUpdateDuration", $totalUpdateDuration);
        $xml .= add_XML_value("totalConfigureDuration", $totalConfigureDuration);
        $xml .= add_XML_value("totalConfigureError", $totalConfigureError);
        $xml .= add_XML_value("totalConfigureWarning", $totalConfigureWarning);
        $xml .= add_XML_value("totalError", $totalerrors);
        $xml .= add_XML_value("totalWarning", $totalwarnings);
        $xml .= add_XML_value("totalBuildDuration", $totalBuildDuration);
        $xml .= add_XML_value("totalNotRun", $totalnotrun);
        $xml .= add_XML_value("totalFail", $totalfail);
        $xml .= add_XML_value("totalPass", $totalpass);
        $xml .= add_XML_value("totalTestsDuration", time_difference($totalTestsDuration * 60.0, true));
        $xml .= "</buildgroup>";
    }
    // generate subproject coverage by group here.
    if (!empty($subproject_groups)) {
        foreach ($subproject_groups as $groupid => $group) {
            $group_cov = $subproject_group_coverage[$groupid];
            $tested = $group_cov['tested'];
            $untested = $group_cov['untested'];
            if ($tested == 0 && $untested == 0) {
                continue;
            }
            $coverage = round($tested / ($tested + $untested) * 100, 2);
            $xml .= "<subprojectgroup>";
            $xml .= add_XML_value("name", $group->GetName());
            $xml .= add_XML_value("id", $group->GetId());
            $xml .= add_XML_value("threshold", $group->GetCoverageThreshold());
            $xml .= add_XML_value("coverage", $coverage);
            $xml .= add_XML_value("tested", $tested);
            $xml .= add_XML_value("untested", $untested);
            $xml .= "</subprojectgroup>";
        }
    }
    // Fill in the rest of the info
    $prevpos = $previousgroupposition + 1;
    if ($prevpos == 0) {
        $prevpos = 1;
    }
    for ($i = $prevpos; $i <= $lastGroupPosition; $i++) {
        $group = pdo_fetch_array(pdo_query("SELECT g.name,g.id FROM buildgroup AS g,buildgroupposition AS gp WHERE g.id=gp.buildgroupid\n                                                                                     AND gp.position='{$i}' AND g.projectid='{$projectid}'\n                                                                                     AND gp.starttime<'{$end_UTCDate}' AND (gp.endtime>'{$end_UTCDate}'  OR gp.endtime='1980-01-01 00:00:00')"));
        $xml .= "<buildgroup>";
        $xml .= add_buildgroup_sortlist($group['name']);
        $xml .= add_XML_value("id", $group["id"]);
        $xml .= add_XML_value("name", $group["name"]);
        $xml .= add_XML_value("linkname", str_replace(" ", "_", $group["name"]));
        if (!$filter_sql) {
            $xml .= add_expected_builds($group["id"], $currentstarttime, $received_builds);
        }
        $xml .= "</buildgroup>";
    }
    $xml .= add_XML_value("enableTestTiming", $project_array["showtesttime"]);
    $end = microtime_float();
    $xml .= "<generationtime>" . round($end - $start, 3) . "</generationtime>";
    if (!empty($sitexml)) {
        $xml .= $sitexml;
    }
    $xml .= "</cdash>";
    return $xml;
}