| <?php | |
| /******************************************************************************* | |
| * Copyright (c) 2008, 2011 Eclipse Foundation and others. | |
| * All rights reserved. This program and the accompanying materials | |
| * are made available under the terms of the Eclipse Public License v1.0 | |
| * which accompanies this distribution, and is available at | |
| * http://www.eclipse.org/legal/epl-v10.html | |
| * | |
| * Contributors: | |
| * Bjorn Feeman-Benson (Eclipse Foundation) - initial API and implementation | |
| * Wayne Beaton (Eclipse Foundation) - Bug 344065 | |
| *******************************************************************************/ | |
| require_once("common/shared_functions.php"); | |
| /*------------------------------------------------------------------------------ | |
| Inputs: | |
| $projectids = array of projectid | |
| Outputs: | |
| $errors = array of error messages | |
| $activecqs = array of rows from bugs from ipzilla database | |
| row includes extra columns for keywords keyword_*, e.g., keyword_modified: | |
| modified, unmodified, binary, source, sourceandbinary | |
| $unusedcqs = array of .ditto. | |
| $pendingcqs = array of .ditto. | |
| $prereqcqs = array of .ditto. | |
| $committers_at_least_once = array of PID, FName, LName, Name1, Name2, Comment | |
| $committers_never = array of .ditto. | |
| $committers_excluded = array of .ditto. | |
| $contributors = array of [login name] => | |
| array of | |
| realname => | |
| login_name => | |
| bugs => array of | |
| bug_id => | |
| type => 'A' (attachment) | 'C' (comment) | |
| attach_id => (also comment_id if type = 'C') | |
| size => | |
| bug_desc => | |
| attach_desc => | |
| $contributors_excluded = array of [login name] => | |
| array of | |
| realname => | |
| login_name => | |
| bugs => array of | |
| bug_id => | |
| type => 'A' (attachment) | 'C' (comment) | |
| attach_id => (also comment_id if type = 'C') | |
| size => | |
| bug_desc => | |
| attach_desc => | |
| Functions: | |
| pretty_size( $v ) | |
| *------------------------------------------------------------------------------ | |
| */ | |
| function get_ip_log_data_structures( $projectids ) { | |
| global $App; | |
| $errors = array(); | |
| /*================================================= | |
| * C Q S | |
| */ | |
| /* | |
| * Step 1: | |
| * Translate the projectids into ipzilla component ids. | |
| * Error if a component name does not match. | |
| */ | |
| $componentids = array(); | |
| foreach( $projectids as $projectid ) { | |
| $sql = "SELECT id FROM components WHERE name = '" . $projectid . "'"; | |
| $result = $App->ipzilla_sql( $sql ); | |
| if( ($row = mysql_fetch_array($result)) ) { | |
| $componentids[] = $row[0]; | |
| } else { | |
| $errors[] = "Error: $projectid does not exist in ipzilla; contact the EMO."; | |
| } | |
| } | |
| /* | |
| * If the conpentids is empty then we found no projects so return, else we get an SQL error | |
| */ | |
| if(empty($componentids)){ | |
| return array( | |
| $errors, | |
| $activecqs, | |
| $unusedcqs, | |
| $pendingcqs, | |
| $prereqcqs, | |
| $committers_at_least_once, | |
| $committers_never, | |
| $committers_excluded, | |
| // $contributors, | |
| // $contributors_excluded | |
| ); | |
| } | |
| /* | |
| * Step 2: | |
| * Get all the CQs for the projects | |
| */ | |
| $sql = "SELECT * FROM bugs | |
| WHERE component_id IN ( " . implode( ',', $componentids ) . ") | |
| "; | |
| $result = $App->ipzilla_sql( $sql ); | |
| $activecqs = array(); | |
| $unusedcqs = array(); | |
| $pendingcqs = array(); | |
| $prereqcqs = array(); | |
| $bugids = array(); | |
| $keywords = array( 'modified', 'unmodified', 'source', 'binary', 'sourceandbinary', | |
| 'obsolete', 'unused', 'withdrawn', 'nonepl' , 'epl'); | |
| while( $row = mysql_fetch_assoc($result) ) { | |
| foreach( $keywords as $key ) { | |
| $row["keyword_$key"] = 0; | |
| } | |
| $bugids[] = $row['bug_id']; | |
| switch( $row['bug_severity'] ) { | |
| case 'approved_all_projects': | |
| case 'approved_one_project': | |
| case 'approved': | |
| case 'reuse': | |
| $activecqs[$row['bug_id']] = $row; | |
| break; | |
| case 'exempt_prereq': | |
| case 'workswith': | |
| case 'prereq': | |
| $prereqcqs[$row['bug_id']] = $row; | |
| break; | |
| case 'awaiting_analysis': | |
| case 'awaiting_committer': | |
| case 'awaiting_emo': | |
| case 'awaiting_pmc': | |
| case 'awaiting_project': | |
| case 'awaiting_triage': | |
| case 'new': | |
| case 'under_review': | |
| if( ($row['bug_status'] == 'RESOLVED' | |
| || $row['bug_status'] == 'CLOSED') | |
| && $row['resolution'] == 'FIXED' ) { | |
| $activecqs[$row['bug_id']] = $row; | |
| } else if( $row['bug_status'] == 'RESOLVED' | |
| || $row['bug_status'] == 'CLOSED') { | |
| /* ignore */ | |
| } else { | |
| $pendingcqs[$row['bug_id']] = $row; | |
| } | |
| break; | |
| case 'closed': | |
| case 'rejected': | |
| case 'withdrawn': | |
| /* ignore */ | |
| break; | |
| default: | |
| $pendingcqs[$row['bug_id']] = $row; | |
| break; | |
| } | |
| } | |
| /* | |
| * Step 3: | |
| * Collect the usage and used keywords for the cqs | |
| */ | |
| if(!empty($bugids)){ | |
| $sql = " | |
| SELECT bug_id, name FROM keywords | |
| LEFT JOIN keyworddefs ON keywordid = id | |
| WHERE name in ( 'modified', 'unmodified', 'source', 'binary', 'sourceandbinary', | |
| 'obsolete', 'unused', 'withdrawn', 'nonepl', 'epl' ) | |
| AND bug_id IN ( " . implode( ",", $bugids ) . " ) | |
| "; | |
| $result = $App->ipzilla_sql( $sql ); | |
| while( $row = mysql_fetch_assoc($result) ) { | |
| if( isset($activecqs[$row['bug_id']]) ) | |
| $activecqs[$row['bug_id']]["keyword_" . $row['name']] = 1; | |
| if( isset($pendingcqs[$row['bug_id']]) ) | |
| $pendingcqs[$row['bug_id']]["keyword_" . $row['name']] = 1; | |
| if( isset($prereqcqs[$row['bug_id']]) ) | |
| $prereqcqs[$row['bug_id']]["keyword_" . $row['name']] = 1; | |
| } | |
| } | |
| /* | |
| * Setp 3.5: | |
| * drop any CQs that are under the EPL and without keyword nonepl | |
| * drop any CQs with the keyword EPL | |
| */ | |
| $activecqs = remove_EPL_CQs($activecqs); | |
| $pendingcqs = remove_EPL_CQs($pendingcqs); | |
| $prereqcqs = remove_EPL_CQs($prereqcqs); | |
| /* | |
| * Step 4: | |
| * Move the unused CQs from active, pending, and prereq to unused | |
| */ | |
| $xa = array(); | |
| $xp = array(); | |
| $xr = array(); | |
| foreach( $activecqs as $key => $value ) { | |
| if( $value['keyword_obsolete'] || $value['keyword_unused'] || $value['keyword_withdrawn'] | |
| /* || $value['keyword_nonepl'] -- removed by Bjorn 24-Oct because it was excluding obviously active CQs */ ) | |
| $unusedcqs[$key] = $value; | |
| else | |
| $xa[$key] = $value; | |
| } | |
| foreach( $pendingcqs as $key => $value ) { | |
| if( $value['keyword_obsolete'] || $value['keyword_unused'] || $value['keyword_withdrawn'] ) | |
| $unusedcqs[$key] = $value; | |
| else | |
| $xp[$key] = $value; | |
| } | |
| foreach( $prereqcqs as $key => $value ) { | |
| if( $value['keyword_obsolete'] || $value['keyword_unused'] || $value['keyword_withdrawn'] ) | |
| $unusedcqs[$key] = $value; | |
| else | |
| $xr[$key] = $value; | |
| } | |
| $activecqs = $xa; | |
| $pendingcqs = $xp; | |
| $prereqcqs = $xr; | |
| /*================================================= | |
| * C O M M I T T E R S | |
| */ | |
| /* | |
| * Step 1: | |
| * Find ALL the past and present committers on this project | |
| * complete with their current employer's name | |
| */ | |
| $all_committers_in_db = array(); | |
| // $sql = " | |
| // SELECT DISTINCT(People.PersonID) as PID, FName, LName, Name1, Name2 | |
| // FROM PeopleProjects, Projects, People | |
| // LEFT JOIN OrganizationContacts | |
| // ON OrganizationContacts.PersonID = People.PersonID | |
| // LEFT JOIN Organizations | |
| // ON OrganizationContacts.OrganizationID = Organizations.OrganizationID | |
| // LEFT JOIN IPLogCorrections ON (IPLogCorrections.ProjectID=Projects.ProjectID and IPLogCorrections.ItemID=People.PersonID) | |
| // WHERE PeopleProjects.Relation in ('CM') | |
| // AND People.PersonID = PeopleProjects.PersonID | |
| // AND Projects.ProjectID = PeopleProjects.ProjectID | |
| // AND ( | |
| // Projects.ProjectID IN ( '" . implode( "','", $projectids ) . "' ) | |
| // OR ( | |
| // ParentProjectID IN ( '" . implode( "','", $projectids ) . "' ) | |
| // AND IsComponent = 1) | |
| // ) | |
| // AND (IPLogCorrections.Action<>'REMOVE') | |
| // "; | |
| /* | |
| * WTB: Modified to exclude committers only from the projects that they are actually | |
| * excluded from. Original code excluded a committer from the rollup ip log (i.e. | |
| * a log for multiple projects) if they are excluded from any project in the rollup. | |
| * By making the exclusion part of the query, we can make sure that those committeres | |
| * who should be there actually appear. To make this work, I had to turn off the | |
| * tracking of excluded entries which may have the effect of making it impossible to | |
| * "unexclude" somebody. | |
| */ | |
| // SELECT DISTINCT(People.PersonID) as PID, FName, LName, Name1, Name2 | |
| //FROM People | |
| //JOIN PeopleProjects ON (People.PersonID = PeopleProjects.PersonID) | |
| //JOIN Projects ON (Projects.ProjectID = PeopleProjects.ProjectID) | |
| //LEFT JOIN OrganizationContacts ON OrganizationContacts.PersonID = People.PersonID | |
| //LEFT JOIN Organizations ON OrganizationContacts.OrganizationID = Organizations.OrganizationID | |
| //LEFT JOIN IPLogCorrections ON (IPLogCorrections.ProjectID=Projects.ProjectID and IPLogCorrections.ItemID=People.PersonID and IPLogCorrections.Action = 'REMOVE') | |
| //WHERE PeopleProjects.Relation in ('CM') | |
| // | |
| //AND Projects.ProjectID IN ( 'webtools.jsf', 'webtools.common') | |
| //or (ParentProjectID IN ( 'webtools.jsf', 'webtools.common') and IsComponent=1) | |
| //AND (IPLogCorrections.Action is NULL) | |
| $sql = " | |
| SELECT DISTINCT(People.PersonID) as PID, FName, LName, Name1, Name2 | |
| FROM People | |
| JOIN PeopleProjects ON (People.PersonID = PeopleProjects.PersonID) | |
| JOIN Projects ON (Projects.ProjectID = PeopleProjects.ProjectID) | |
| LEFT JOIN OrganizationContacts ON OrganizationContacts.PersonID = People.PersonID | |
| LEFT JOIN Organizations ON OrganizationContacts.OrganizationID = Organizations.OrganizationID | |
| LEFT JOIN IPLogCorrections ON (IPLogCorrections.ProjectID=Projects.ProjectID and IPLogCorrections.ItemID=People.PersonID and IPLogCorrections.Action = 'REMOVE') | |
| WHERE PeopleProjects.Relation in ('CM') | |
| AND (Projects.ProjectID IN ( '" . implode( "','", $projectids ) . "' ) | |
| OR (ParentProjectID IN ( '" . implode( "','", $projectids ) . "' ) AND IsComponent = 1)) | |
| AND (IPLogCorrections.Action is NULL)"; | |
| if (isset($_GET['debug'])) echo $sql; | |
| $result = $App->foundation_sql( $sql ); | |
| mysql_error_check(); | |
| while( $row = mysql_fetch_assoc($result) ) { | |
| $row['Comment'] = ''; | |
| $all_committers_in_db[ $row['PID'] ] = $row; | |
| } | |
| /* | |
| * Step 2: | |
| * Get the commits activity to figure out everyone who | |
| * ever committed code to the project. | |
| */ | |
| $blob = file("http://dash.eclipse.org/dash/commits/web-api/commits-index.php?projectid=" . implode(',', $projectids) ); | |
| $cm_counts = array(); | |
| foreach( $blob as $line ) { | |
| $words = split( "\t", $line ); | |
| if( substr($words[0],0,1) == '#' ) // skip comments | |
| continue; | |
| if( $words[2] == 999999 ) // only use the 'inf' records | |
| // WTB Only add if the person is actually a committer on the project. | |
| if (isset($all_committers_in_db[$words[0]])) | |
| $cm_counts[$words[0]] = $words[1]; | |
| } | |
| /* | |
| * Step 3: | |
| * Get the corrections ItemType = COMMITTR, Action = ? | |
| * COMENT: Just comments | |
| * REMOVE: Committer is not a committer (move to excluded list) | |
| * ACTIVE: Committer was active (move to at least once list) | |
| * ADD: Add a committer (move to at least once list) | |
| */ | |
| $sql = " | |
| SELECT * FROM IPLogCorrections | |
| WHERE ProjectID IN ( '" . implode( "','", $projectids ) . "' ) | |
| AND ItemType = 'COMMITTR' | |
| "; | |
| $result = $App->foundation_sql( $sql ); | |
| $committer_corrections = array(); | |
| while( $row = mysql_fetch_assoc( $result ) ) { | |
| $committer_corrections[$row['Action']][$row['ItemID']] = $row; | |
| } | |
| /* | |
| * Step 4: | |
| * Compute three lists: committers who once committed code | |
| * and committers who appear never to have committed any code | |
| * and committers who have been excluded | |
| */ | |
| $committers_at_least_once = array(); | |
| $committers_never = array(); | |
| $committers_excluded = array(); | |
| foreach( $all_committers_in_db as $key => $row ) { | |
| if( isset($committer_corrections['COMENT'][$key]) ) { | |
| $row['Comment'] = $committer_corrections['COMENT'][$key]['Comment']; | |
| } | |
| // if( isset($committer_corrections['REMOVE'][$key]) ) { | |
| // //$committers_excluded[$key] = $row; | |
| // } else { | |
| if( isset($committer_corrections['ACTIVE'][$key]) ) { | |
| if (isset($_GET['debug'])) echo "<p>Committers forced active: $key</p>"; | |
| $committers_at_least_once[$key] = $row; | |
| } else { | |
| if( isset($cm_counts[$key]) ) { | |
| if (isset($_GET['debug'])) echo "<p>Committers at least once: $key</p>"; | |
| $committers_at_least_once[$key] = $row; | |
| } else { | |
| if (isset($_GET['debug'])) echo "<p>Committers never: $key</p>"; | |
| $committers_never[$key] = $row; | |
| } | |
| } | |
| // } | |
| } | |
| foreach( $cm_counts as $key => $row ) { | |
| if( !isset($all_committers_in_db[$key] ) ) { | |
| if( isset($committer_corrections['REMOVE'][$key]) ) { | |
| $committers_excluded[$key] = | |
| array( 'PID' => $key, | |
| 'FName' => $key, | |
| 'LName' => '', | |
| 'Name1' => '(not a current committer)', | |
| 'Name2' => '', | |
| 'Comment' => | |
| (isset($committer_corrections['COMENT'][$key]['Comment']) ? | |
| $committer_corrections['COMENT'][$key]['Comment'] : '' ) | |
| ); | |
| } else { | |
| $committers_at_least_once[$key] = | |
| array( 'PID' => $key, | |
| 'FName' => $key, | |
| 'LName' => '', | |
| 'Name1' => '(not a current committer)', | |
| 'Name2' => '', | |
| 'Comment' => | |
| (isset($committer_corrections['COMENT'][$key]['Comment']) ? | |
| $committer_corrections['COMENT'][$key]['Comment'] : '' ) | |
| ); | |
| } | |
| } | |
| } | |
| if( isset($committer_corrections['ADD']) ) { | |
| foreach( $committer_corrections['ADD'] as $key => $rec ) { | |
| $x = explode( '|', $rec['Value'] ); | |
| $committers_at_least_once[$key] = | |
| array( 'PID' => $key, | |
| 'FName' => $x[0], | |
| 'LName' => '', | |
| 'Name1' => $x[1], | |
| 'Name2' => '', | |
| 'Comment' => $rec['Comment'] ); | |
| } | |
| } | |
| /* | |
| * Step 5: | |
| * Sort the lists | |
| */ | |
| uasort( $committers_at_least_once, 'sortcms' ); | |
| uasort( $committers_never, 'sortcms' ); | |
| uasort( $committers_excluded, 'sortcms' ); | |
| // WTB Moved to IPLog.class.php | |
| // /*================================================= | |
| // * C O N T R I B U T O R S | |
| // */ | |
| // /* | |
| // * Step 1: | |
| // * Get the bugzilla project info records for each project. | |
| // * Error if a project does not have a bugzilla record. | |
| // */ | |
| // $bugzillakeys = array(); // list of productname, '' or productname, component | |
| // foreach( $projectids as $projectid ) { | |
| // $project = new ProjectInfoData($projectid); | |
| // if( $project->bugzilla ) { | |
| // foreach( $project->bugzillas as $bugzilla ) { | |
| // if( $bugzilla->productname ) { | |
| // if( $bugzilla->components ) { | |
| // $x = explode(',', $bugzilla->components); | |
| // foreach( $x as $component ) { | |
| // $bugzillakeys[] = array( trim($bugzilla->productname), trim($component) ); | |
| // } | |
| // } else { | |
| // $bugzillakeys[] = array( trim($bugzilla->productname), '' ); | |
| // } | |
| // } else { | |
| // $errors[] = " | |
| // Error: the project meta-data key 'bugzilla/productname' \"" . $bugzillakeys[$i][0] . "\" | |
| // is blank; | |
| // use <a href='http://portal.eclipse.org/'>the portal</a> | |
| // \"[maintain] project info meta-data\" to enter the correct | |
| // <a href='http://bugs.eclipse.org/'>bugzilla</a> Product name for $projectid"; | |
| // } | |
| // } | |
| // } else { | |
| // $errors[] = " | |
| // Error: there is no project meta-data key 'bugzilla' for $projectid; | |
| // use <a href='http://portal.eclipse.org/'>the portal</a> | |
| // \"[maintain] project info meta-data\" to enter the correct | |
| // <a href='http://bugs.eclipse.org/'>bugzilla</a> Product name for $projectid"; | |
| // } | |
| // } | |
| // /* | |
| // * Step 2: | |
| // * Translate the productnames and components into ids. | |
| // * Error if a productname or component name does not match. | |
| // */ | |
| // $lastname = ''; | |
| // $lastid = 0; | |
| // for( $i = 0; $i < count($bugzillakeys); $i += 1 ) { | |
| // if( $lastname == $bugzillakeys[$i][0] ) { | |
| // $bugzillakeys[$i][2] = $lastid; | |
| // } else { | |
| // $sql = "SELECT id FROM products WHERE name = '" . $bugzillakeys[$i][0] . "' LIMIT 1"; | |
| // $result = $App->bugzilla_sql( $sql ); | |
| // if( ($row = mysql_fetch_array($result)) ) { | |
| // $bugzillakeys[$i][2] = $row[0]; | |
| // $lastname = $bugzillakeys[$i][0]; | |
| // $lastid = $row[0]; | |
| // } else { | |
| // $errors[] = " | |
| // Error: the project meta-data key 'bugzilla/productname' \"" . $bugzillakeys[$i][0] . "\" | |
| // is not a valid Product name in <a href='http://bugs.eclipse.org/'>bugzilla</a>; | |
| // use <a href='http://portal.eclipse.org/'>the portal</a> | |
| // \"[maintain] project info meta-data\" to enter the correct | |
| // bugzilla Product name for $projectid"; | |
| // } | |
| // } | |
| // if( $bugzillakeys[$i][1] ) { | |
| // $sql = "SELECT id FROM components WHERE name = '" . $bugzillakeys[$i][1] . "' | |
| // AND product_id = " . $lastid . " LIMIT 1"; | |
| // $result = $App->bugzilla_sql( $sql ); | |
| // if( ($row = mysql_fetch_array($result)) ) { | |
| // $bugzillakeys[$i][3] = $row[0]; | |
| // } else { | |
| // $errors[] = " | |
| // Error: the project meta-data key 'bugzilla/components' \"" . $bugzillakeys[$i][1] . "\" | |
| // is not a valid Component name in the \"" . $bugzillakeys[$i][0] . "\" Product name | |
| // in <a href='http://bugs.eclipse.org/'>bugzilla</a>; | |
| // use <a href='http://portal.eclipse.org/'>the portal</a> | |
| // \"[maintain] project info meta-data\" to enter the correct | |
| // bugzilla Component name(s) for $projectid"; | |
| // } | |
| // } | |
| // } | |
| // /* | |
| // * Step 3: | |
| // * Query bugzilla to find all the iplog flagged attachments to closed bugs | |
| // */ | |
| // $ors = array(); | |
| // foreach( $bugzillakeys as $each ) { | |
| // $ands = array(); | |
| // if($each[2] != ""){ | |
| // $ands[] = "product_id = " . $each[2]; | |
| // if( isset($each[3]) ){ | |
| // $ands[] = "component_id = " . $each[3]; | |
| // } | |
| // $ors[] = "(" . implode( " AND ", $ands ) . ")"; | |
| // } | |
| // } | |
| // if( count($ors) == 0 ){ | |
| // $ors[] = "FALSE"; | |
| // } | |
| // $sql = " | |
| // SELECT profiles.login_name, | |
| // profiles.realname, | |
| // bugs.bug_id, | |
| // attachments.attach_id, | |
| // attachments.description, | |
| // UNIX_TIMESTAMP(attachments.creation_ts) AS created, | |
| // LENGTH(attach_data.thedata) AS size, | |
| // bugs.short_desc | |
| // FROM attachments, attach_data, bugs, profiles, flags, flagtypes | |
| // WHERE flagtypes.name = 'iplog' | |
| // AND flags.status = '+' | |
| // AND bug_status IN ( 'RESOLVED', 'VERIFIED', 'CLOSED' ) | |
| // AND resolution IN ( 'FIXED' ) | |
| // AND flagtypes.target_type = 'a' | |
| // AND flags.bug_id = bugs.bug_id | |
| // AND flags.attach_id = attachments.attach_id | |
| // AND flagtypes.id = flags.type_id | |
| // AND attachments.bug_id = bugs.bug_id | |
| // AND attachments.attach_id = attach_data.id | |
| // AND profiles.userid = attachments.submitter_id | |
| // AND (" . implode( " OR ", $ors ) . ") | |
| // ORDER BY bugs.bug_id | |
| // "; | |
| // if (isset($_GET['test'])) echo $sql; | |
| // $result = $App->bugzilla_sql( $sql ); | |
| // $contributors = array(); | |
| // $contributors_excluded = array(); | |
| // while( $row = mysql_fetch_assoc($result) ) { | |
| // $contributors[$row['login_name']]['realname'] = $row['realname']; | |
| // $contributors[$row['login_name']]['login_name'] = $row['login_name']; | |
| // $contributors[$row['login_name']]['bugs'][] = array( | |
| // 'bug_id' => $row['bug_id'], | |
| // 'type' => 'A', | |
| // 'attach_id' => $row['attach_id'], | |
| // 'size' => $row['size'], | |
| // 'created' => $row['created'], | |
| // 'bug_desc' => $row['short_desc'], | |
| // 'attach_desc' => $row['description'] ); | |
| // } | |
| // /* | |
| // * Step 4: | |
| // * Query bugzilla to find all the comments to iplog flagged closed bugs | |
| // */ | |
| // $sql = " | |
| // SELECT profiles.login_name, | |
| // profiles.realname, | |
| // bugs.bug_id, | |
| // longdescs.comment_id, | |
| // UNIX_TIMESTAMP(longdescs.bug_when) AS created, | |
| // LENGTH(longdescs.thetext) AS size, | |
| // bugs.short_desc | |
| // FROM longdescs, bugs, profiles, flags, flagtypes | |
| // WHERE flagtypes.name = 'iplog' | |
| // AND flags.status = '+' | |
| // AND bug_status IN ( 'RESOLVED', 'VERIFIED', 'CLOSED' ) | |
| // AND resolution IN ( 'FIXED' ) | |
| // AND flagtypes.target_type = 'b' | |
| // AND flags.bug_id = bugs.bug_id | |
| // AND flagtypes.id = flags.type_id | |
| // AND longdescs.bug_id = bugs.bug_id | |
| // AND profiles.userid = longdescs.who | |
| // AND (" . implode( " OR ", $ors ) . ") | |
| // ORDER BY bugs.bug_id, longdescs.comment_id | |
| // "; | |
| // $result = $App->bugzilla_sql( $sql ); | |
| // $lastbug = 0; | |
| // $commentnumber = 0; | |
| // while( $row = mysql_fetch_assoc($result) ) { | |
| // if( $row['bug_id'] == $lastbug ) { | |
| // $commentnumber += 1; | |
| // } else { | |
| // $commentnumber = 0; | |
| // $lastbug = $row['bug_id']; | |
| // } | |
| // $contributors[$row['login_name']]['realname'] = $row['realname']; | |
| // $contributors[$row['login_name']]['login_name'] = $row['login_name']; | |
| // $contributors[$row['login_name']]['bugs'][] = array( | |
| // 'bug_id' => $row['bug_id'], | |
| // 'type' => 'C', | |
| // 'attach_id' => $row['comment_id'], | |
| // 'size' => $row['size'], | |
| // 'created' => $row['created'], | |
| // 'bug_desc' => $row['short_desc'], | |
| // 'attach_desc' => 'comment #' . $commentnumber ); | |
| // } | |
| // /* | |
| // * Step 5: | |
| // * Find Foundation database ids for contributors (if they have ids) | |
| // */ | |
| // // WTB Bug 343596 - Need to escape email addresses before using them in query. | |
| // $emails = array(); | |
| // foreach (array_keys( $contributors ) as $email) { | |
| // $emails[] = mysql_real_escape_string($email); | |
| // } | |
| // $personids = array(); | |
| // $sql = "SELECT PersonID, Email FROM People | |
| // WHERE Email IN ( '" . implode( "','", $emails ) . "' ) | |
| // "; | |
| // $result = $App->foundation_sql( $sql ); | |
| // while( $row = mysql_fetch_array($result) ) { | |
| // $contributors[$row[1]]['personid'] = $row[0]; | |
| // $personids[$row[0]] = 1; | |
| // } | |
| // $sql = "SELECT PersonID, Email FROM PeopleEmails | |
| // WHERE Email IN ( '" . implode( "','", $emails ) . "' ) | |
| // "; | |
| // $result = $App->foundation_sql( $sql ); | |
| // while( $row = mysql_fetch_array($result) ) { | |
| // $contributors[$row[1]]['personid'] = $row[0]; | |
| // $personids[$row[0]] = 1; | |
| // } | |
| // /* | |
| // * Step 6: | |
| // * Find out when each of the PersonIDs is/was a committer (if they ever were) | |
| // */ | |
| // $sql = " | |
| // SELECT PersonID, UNIX_TIMESTAMP(ActiveDate) AS start, UNIX_TIMESTAMP(InactiveDate) AS end FROM PeopleProjects | |
| // WHERE Relation = 'CM' | |
| // AND ProjectID IN ( '" . implode( "','", $projectids ) . "' ) | |
| // AND PersonID IN ( '" . implode( "','", array_keys($personids) ) . "' ) | |
| // "; | |
| // $result = $App->foundation_sql( $sql ); | |
| // $activedates = array(); | |
| // while( $row = mysql_fetch_assoc($result) ) { | |
| // $activedates[$row['PersonID']][] = $row; | |
| // } | |
| // /* | |
| // * Step 7: | |
| // * Filter out the attachments that were contributed by a committer | |
| // */ | |
| // foreach( $contributors as $key => $rec ) { | |
| // if( isset($rec['personid']) ) { | |
| // $filtered = array(); | |
| // foreach( $rec['bugs'] as $bug ) { | |
| // $found = false; | |
| // foreach( $activedates[$rec['personid']] as $each ) { | |
| // if( $bug['created'] >= $each['start'] | |
| // && ($each['end'] == null | |
| // || $bug['created'] <= $each['end']) ) { | |
| // $found = true; | |
| // break; | |
| // } | |
| // } | |
| // if( !$found ) { | |
| // $filtered[] = $bug; | |
| // } | |
| // } | |
| // $contributors[$key]['bugs'] = $filtered; | |
| // } | |
| // } | |
| // /* | |
| // * Step 8: | |
| // * Get the corrections ItemType = CONTRIB, Action = ? | |
| // */ | |
| // $sql = " | |
| // SELECT * FROM IPLogCorrections | |
| // WHERE ProjectID IN ( '" . implode( "','", $projectids ) . "' ) | |
| // AND ItemType = 'CONTRIB' | |
| // "; | |
| // $result = $App->foundation_sql( $sql ); | |
| // $contributor_corrections = array(); | |
| // while( $row = mysql_fetch_assoc( $result ) ) { | |
| // $contributor_corrections[$row['Action']][$row['ItemID']] = $row; | |
| // } | |
| // /* | |
| // * Step 9: | |
| // * Move the corrected/removed contributions to the excluded array | |
| // */ | |
| // $contributors2 = array(); | |
| // foreach( $contributors as $loginname => $rec ) { | |
| // $rec2 = array(); | |
| // $rec2['realname'] = $rec['realname']; | |
| // $rec2['login_name'] = $rec['login_name']; | |
| // $rec2['bugs'] = array(); | |
| // $rec2x = array(); | |
| // $rec2x['realname'] = $rec['realname']; | |
| // $rec2x['login_name'] = $rec['login_name']; | |
| // $rec2x['bugs'] = array(); | |
| // foreach( $rec['bugs'] as $bug ) { | |
| // $bug2 = array(); | |
| // $bug2['bug_id'] = $bug['bug_id']; | |
| // $bug2['attach_id'] = $bug['attach_id']; | |
| // $bug2['size'] = $bug['size']; | |
| // $bug2['bug_desc'] = $bug['bug_desc']; | |
| // $bug2['attach_desc'] = $bug['attach_desc']; | |
| // $bug2['type'] = $bug['type']; | |
| // if( isset($contributor_corrections['RM' . $bug['type']][$bug['attach_id']]) ) { | |
| // $rec2x['bugs'][] = $bug2; | |
| // } else { | |
| // $rec2['bugs'][] = $bug2; | |
| // } | |
| // } | |
| // if( count($rec2x['bugs']) > 0 ) { | |
| // $contributors_excluded[$rec2x['login_name']] = $rec2x; | |
| // } | |
| // $contributors2[$rec2['login_name']] = $rec2; | |
| // } | |
| // $contributors = $contributors2; | |
| // /* | |
| // * Step 9: | |
| // * Clean out the empty records | |
| // */ | |
| // $x = array(); | |
| // foreach( $contributors as $key => $value ) { | |
| // if( count($value['bugs']) > 0 ) | |
| // $x[$key] = $value; | |
| // } | |
| // $contributors = $x; | |
| // /* | |
| // * Step 8: | |
| // * Sort the results | |
| // */ | |
| // uasort( $contributors, 'cmpcontributors' ); | |
| // uasort( $contributors_excluded, 'cmpcontributors' ); | |
| return array( | |
| $errors, | |
| $activecqs, | |
| $unusedcqs, | |
| $pendingcqs, | |
| $prereqcqs, | |
| $committers_at_least_once, | |
| $committers_never, | |
| $committers_excluded, | |
| // $contributors, | |
| // $contributors_excluded | |
| ); | |
| } | |
| function cmpcontributors( $a, $b ) { | |
| $ar = $a['realname']; | |
| $br = $b['realname']; | |
| if( $ar && $br ) { | |
| preg_match( "/(\w+)\s*$/", $ar, $ma ); | |
| preg_match( "/(\w+)\s*$/", $br, $mb ); | |
| if( $ma[1] < $mb[1] ) return -1; | |
| if( $ma[1] > $mb[1] ) return 1; | |
| } | |
| if( $a['login_name'] < $b['login_name'] ) return -1; | |
| if( $a['login_name'] > $b['login_name'] ) return 1; | |
| return 0; | |
| } | |
| function sortcms( $a, $b ) { | |
| if( $a['LName'] > $b['LName'] ) return 1; | |
| if( $a['LName'] < $b['LName'] ) return -1; | |
| if( $a['FName'] > $b['FName'] ) return 1; | |
| if( $a['FName'] < $b['FName'] ) return -1; | |
| return 0; | |
| } | |
| function pretty_size($bytes) | |
| { | |
| $sufs= array ( | |
| "B", | |
| "K", | |
| "M", | |
| "G", | |
| "T", | |
| "P" | |
| ); //we shouldn't be larger than 999.9 petabytes any time soon, hopefully | |
| $suf= 0; | |
| while ($bytes >= 1000) | |
| { | |
| $bytes /= 1024; | |
| $suf++; | |
| } | |
| $rtrn = sprintf("%3.1f%s", $bytes, $sufs[$suf]); | |
| if( substr( $rtrn, -3 ) == ".0B" ) $rtrn = substr( $rtrn, 0, -3 ); | |
| return $rtrn; | |
| } | |
| function check_if_show_edit_form( $projectids, $Session, $Friend, $only_one_project, &$show_edit_form, &$reason_no_edit_form, &$logged_in_email_address ) { | |
| global $App; | |
| $reason_no_edit_form = ''; | |
| $show_edit_form = 0; | |
| if( count($projectids) > 1 && $only_one_project ) { | |
| $reason_no_edit_form = 'To modify an ip log you must <a href="ip_log_selector.php?projectid=' | |
| . implode( ',', $projectids ) . '">select a single project</a>.'; | |
| if( $Session->getBugzillaID() == 0 ) { | |
| $reason_no_edit_form .= ' and be <a href="http://dev.eclipse.org/site_login/">logged in</a> as a committer on that project.'; | |
| } | |
| } else { | |
| if( $Session->getBugzillaID() == 0 ) { | |
| $reason_no_edit_form = 'To modify an ip log you must be <a href="http://dev.eclipse.org/site_login/">logged in</a> as a committer.'; | |
| } else { | |
| $bugzilla_userid = $Session->getBugzillaID(); | |
| $sql = "select login_name from profiles where userid = " . $bugzilla_userid; | |
| $result = $App->bugzilla_sql( $sql ); | |
| $row = mysql_fetch_array( $result ); | |
| if( $row ) { | |
| $logged_in_email_address = $row[0]; | |
| $sql = "select People.PersonID from People, PeopleProjects | |
| where People.PersonID = PeopleProjects.PersonID | |
| and EMail = '" . $row[0] . "' | |
| and ProjectID IN ('" . implode('\',\'',$projectids) . "') | |
| and Relation IN ( 'CM', 'PL', 'PM', 'PD' ) | |
| "; | |
| if (isset($_GET['test'])) echo $sql; | |
| $result = $App->foundation_sql( $sql ); | |
| $row = mysql_fetch_array( $result ); | |
| if( $row ) { | |
| $show_edit_form = $row[0]; | |
| } else { | |
| $reason_no_edit_form = 'To modify an ip log you must be <a href="http://dev.eclipse.org/site_login/">logged in</a> as a committer on the project.'; | |
| } | |
| } else { | |
| $reason_no_edit_form = 'Internal error 1: no login_name for userid (' . $bugzilla_userid . ')'; | |
| } | |
| } | |
| } | |
| } | |
| /* | |
| * drop any CQs that are under the EPL and without keyword nonepl | |
| * drop any CQs with the keyword EPL | |
| */ | |
| function remove_EPL_CQs($cqs){ | |
| foreach($cqs as $bug_id => $bug){ | |
| if( (preg_match('/Eclipse Public License|EPL/i',$bug['cf_license']) and $bug["keyword_nonepl"] == 0) or $bug["keyword_epl"] == 1 ){ | |
| unset($cqs[$bug_id]); | |
| } | |
| } | |
| return $cqs; | |
| } | |
| /** | |
| * This function returns a simple array containing the descriptive text | |
| * for all of the licenses included in the projects ("Eclipse Public License, 1.0", | |
| * for example). This information is harvested from the Foundation database. | |
| * | |
| * @param $projectids an array of string values: the ids of the projects of interest. | |
| * @return an array containing the descriptive text of the licenses. | |
| */ | |
| function gather_project_licenses(&$projectids) { | |
| global $App; | |
| $sql = "SELECT distinct l.Description as License FROM ProjectLicenses as p join (SYS_Licenses as l) on (p.LicenseId = l.LicenseId) where p.ProjectId IN ( '" . implode( "','", $projectids ) . "')"; | |
| $result = $App->foundation_sql( $sql ); | |
| mysql_error_check(); | |
| $licenses = array(); | |
| while( $row = mysql_fetch_assoc($result) ) { | |
| $license = $row['License']; | |
| if (in_array($license, $licenses)) continue; | |
| $licenses[] = $license; | |
| } | |
| return $licenses; | |
| } | |
| ?> | |