blob: 34fdb1da4e4330ca7bde24f52e1d118454f82918 [file] [log] [blame]
<?php
/*******************************************************************************
* Copyright (c) 2010, 2015 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:
* Wayne Beaton (Eclipse Foundation)- initial API and implementation
*******************************************************************************/
require_once($_SERVER['DOCUMENT_ROOT'] . "/projects/classes/common.php");
require_once($_SERVER['DOCUMENT_ROOT'] . "/projects/classes/debug.php");
class Review {
var $info;
function __construct($info) {
$this->info = $info;
}
function getId() {
return $this->info['Id'];
}
function getProjectName() {
$name = @$this->info['ProjectName'];
if ($name) return $name;
/*
* If the name hasn't been specified, use the proposal name instead.
* That is, assume that we're looking at a Creation Review that's
* following a proposal.
*/
return @$this->info['ProposalName'];
}
function getProjectId() {
return $this->info['ProjectID'];
}
function getReviewName() {
$name = $this->info['ReviewName'];
if ($name) return $name;
/*
* If the review name has not been provided, but a proposal
* name has been provided, assume that this is a creation review.
*/
if ($this->info['ProposalName']) return 'Creation';
return "Unknown";
}
function getTitle() {
$projectName = $this->getProjectName();
$reviewName = $this->getReviewName();
$status = $this->getStatus();
return "$projectName $reviewName $status";
}
function isCreation() {
return preg_match('/Creation/i', $this->getReviewName()) ? true : false;
}
/**
* If the name includes the word "release", or if the name is
* just a number, then it's a release.
*
* @return boolean
*/
function isRelease() {
if (preg_match('/release/i', $this->getReviewName())) return true;
if (preg_match('/^\d*(\.\d+){0,}$/', trim($this->getReviewName()))) return true;
return false;
}
function isGraduation() {
return preg_match('/Graduation/i', $this->getReviewName()) ? true : false;
}
function isRestructure() {
if (preg_match('/Restruct/i', $this->getReviewName())) return true;
if (preg_match('/Move/i', $this->getReviewName())) return true;
return false;
}
function isTermination() {
if (preg_match('/Termination/i', $this->getReviewName())) return true;
if (preg_match('/Archiv/i', $this->getReviewName())) return true;
return false;
}
function getVersion() {
if (preg_match('/(\d+)(\.\d+)?(\.\d+)?/', $this->getReviewName(), $matches)) {
$name = $matches[1];
$name .= isset($matches[2]) && $matches[2] ? $matches[2] : '.0';
$name .= isset($matches[3]) && $matches[3] ? $matches[3] : '.0';
return $name;
} else if (preg_match('/(\d+(\.\d+){1,2})/', $this->getReviewName())) {
return $match[1];
} else {
return null;
}
}
function getReviewDate() {
$date = $this->info['ReviewDate'];
if (!$date) return null;
return strtotime($date);
}
function getDate() {
return $this->getReviewDate();
}
function getProjectUrl() {
return $this->info['ProjectURL'];
}
function getBugNumber() {
return $this->info['BugNumber'];
}
function getIplogUrl() {
return $this->info['IPLogURL'];
}
function getLink() {
return $this->getSlidesUrl();
}
function getSlidesUrl() {
return $this->info['SlidesURL'];
}
function isWithdrawn() {
return $this->getReviewWithdrawn() != null;
}
function isSuccessful() {
return $this->getReviewSuccessful() != null;
}
function isUnsuccessful() {
return $this->getReviewUnsuccessful() != null;
}
function getReviewSuccessful() {
return $this->getStatus('Review Successful');
}
function getReviewWithdrawn() {
return $this->getStatus('Review Withdrawn');
}
function getReviewUnsuccessful() {
return $this->getStatus('Review Unsuccessful');
}
function getWaitingProvisioning() {
return $this->getStatus('Waiting Provisioning');
}
/**
* This function provides a line of HTML that describes the receiver; it
* provides links to the various bits of interesting information about
* the review. Yes, this probably doesn't belong here (it's more of
* UI thing).
*
* @return string
*/
function asHtml($ignore = null) {
global $App;
$projectName = $this->getProjectName();
$reviewName = $this->getReviewName();
$projectUrl = $this->getProjectUrl();
$reviewUrl = $this->getSlidesUrl();
$iplogUrl = $this->getIplogUrl();
$reviewDate = $this->getReviewDate();
$projectName = htmlentities($projectName);
$reviewName = htmlentities($reviewName);
$suffix = 'Review';
if ($projectUrl) $projectName = "<a href=\"$projectUrl\">$projectName</a>";
if ($reviewDate) {
$reviewDate = $App->getFormattedDate($reviewDate, 'short');
$reviewDate = str_replace(' ', '&nbsp;', $reviewDate);
} else {
$reviewDate= 'unscheduled';
}
if ($reviewUrl)
$suffix = "<a href=\"$reviewUrl\">$suffix</a>";
$icons = '';
if ($iplogUrl) {
$icons .= "<a href=\"$iplogUrl\"><img style=\"vertical-align:top\" title=\"IP Log\" src=\"http://dev.eclipse.org/small_icons/status/dialog-information.png\"/></a>";
}
if ($this->isSuccessful()) {
$icons .= "<img style=\"vertical-align:top\" title=\"Review Successful\" src=\"/projects/images/ok.gif\">";
}
if ($this->isUnsuccessful()) {
$icons .= "<img style=\"vertical-align:top\" title=\"Review Unsuccessful\" src=\"http://dev.eclipse.org/small_icons/actions/process-stop.png\">";
}
if ($this->isWithdrawn()) {
$reviewDate = "<strike>$reviewDate</strike>";
$projectName = "<strike>$projectName</strike>";
$reviewName = "<strike>$reviewName</strike>";
$icons .= "<img style=\"vertical-align:top\" title=\"Review Withdrawn\" src=\"http://dev.eclipse.org/small_icons/actions/process-stop.png\">";
}
return "$reviewDate ${icons}${projectName} $reviewName $suffix";
}
/**
* THIS IS NOT API
*/
/* private */ function getStatus($text) {
foreach($this->statuses as $status) {
if ($status->getText() == $text) return $status;
}
return null;
}
}
class ReviewStatus {
var $info;
function __construct($info) {
$this->info = $info;
}
function getText() {
return $this->info['Status'];
}
function getDate() {
return strtotime($this->info['Date']);
}
}
/**
* This function provides the list of all reviews. Note that the
* results are cached.
*
* @deprecated
* @return Review[]
*/
function get_reviews() {
_loadReviews();
global $_Reviews;
return $_Reviews;
}
function _loadReviews() {
global $_Reviews, $_ProjectIdToReviewMap, $App;
if (isset($_Reviews)) return;
$sql = "
SELECT
r.id as Id,
r.ProjectName, r.ProposalName, r.ProjectID,
ProjectURL, SlidesURL, IPLogURL, BugNumber, ReviewDate,
ReviewName,
s.status as Status, s.value as Date
FROM
ProjectReviews as r
join ProjectReviewStatus as s on (r.id = s.id and s.value != 0)
WHERE
ReviewDate is not null and ReviewDate != '0000-00-00'
ORDER BY ReviewDate desc, Date desc";
$result = $App->foundation_sql($sql);
$reviews = array();
$projectIdToReviewMap = array();
while($row = mysql_fetch_assoc($result)) {
$id = $row['Id'];
if (isset($reviews[$id])) {
$review = $reviews[$id];
} else {
$review = new Review($row);
$reviews[$id] = $review;
if ($review->getProjectId())
$projectIdToReviewMap[$review->getProjectId()][] = $review;
}
$review->statuses[] = new ReviewStatus($row);
}
$forges = array(
'http://projects.eclipse.org/json/reviews/complete',
'http://polarsys.org/json/reviews/complete',
'http://locationtech.org/json/reviews/complete'
);
foreach($forges as $forge) {
if ($upcoming = json_decode(@file_get_contents($forge), true)) {
foreach($upcoming as $row) {
$review = new Review($row);
$review->statuses[] = new ReviewStatus($row);
$reviews[$review->getId()] = $review;
}
}
}
usort($reviews, 'sortByReviewDate');
/* Cache the result for next time... */
$_Reviews = $reviews;
$_ProjectIdToReviewMap = $projectIdToReviewMap;
return $reviews;
}
/**
* @deprecated
* @param unknown $projectId
*/
function getReviewsForProject($projectId) {
_loadReviews();
global $_ProjectIdToReviewMap;
if (isset($_ProjectIdToReviewMap[$projectId]))
return $_ProjectIdToReviewMap[$projectId];
return array();
}
/**
* State should be one of 'complete' or 'upcoming'
*
* @param unknown $state
* @param unknown $limit
*/
function getReviews($state = 'upcoming', $limit=null) {
$reviews = array();
foreach(getForges() as $forge) {
$url = "$forge/json/reviews/$state";
if ($list = json_decode(getUrlContents($url), true)) {
foreach($list as $row) {
$review = new Review($row);
$review->statuses[] = new ReviewStatus($row);
$reviews[$review->getId()] = $review;
}
}
}
usort($reviews, 'sortByReviewDate');
if ($limit)
return array_slice($reviews, 0, $limit);
return $reviews;
}
function sortByReviewDate($a, $b) {
$dateA = $a->getReviewDate();
$dateB = $b->getReviewDate();
if ($dateA == $dateB) return 0;
return $dateA > $dateB ? -1 : 1;
}
/**
* Compare two Reviews for sorting. The most recently completed
* reviews are sorted first, followed by everything else. Within
* the groups, everything is sorted by date and then by project id.
*
* @internal
* @param Review $a
* @param Review $b
* @return -1, 0, 1 if <,==,>
*/
function sortUpcomingReviews($a, $b) {
$now = strtotime('now');
$lastWeek = strtotime('-1 week');
$aDate = $a->getDate();
$bDate = $b->getDate();
$aRecent = ($aDate < $now) && ($aDate > $lastWeek);
$bRecent = ($bDate < $now) && ($bDate > $lastWeek);
if ($aRecent == $bRecent) {
if ($aDate < $bDate) return -1;
if ($aDate > $bDate) return 1;
return strcasecmp($a->getProjectId(),$b->getProjectId());
}
if ($aRecent == 1) return -1;
return 1;
}
?>