| <?php |
| /******************************************************************************* |
| * Copyright (c) 2010 Eclipse Foundation and others. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| *******************************************************************************/ |
| require_once($_SERVER['DOCUMENT_ROOT'] . "/projects/classes/common.php"); |
| require_once($_SERVER['DOCUMENT_ROOT'] . "/projects/classes/debug.php"); |
| |
| require_once(dirname(__FILE__) . "/Forge.class.inc"); |
| require_once(dirname(__FILE__) . "/database.inc"); |
| |
| define('REVIEW_TYPE_CREATION', 'creation'); |
| define('REVIEW_TYPE_GRADUATION', 'graduation'); |
| define('REVIEW_TYPE_RELEASE', 'release'); |
| define('REVIEW_TYPE_RESTRUCTURE', 'restructure'); |
| define('REVIEW_TYPE_TERMINATION', 'termination'); |
| |
| class Review { |
| var $info; |
| |
| function __construct($info) { |
| $this->info = $info; |
| } |
| |
| /** |
| * State should be one of 'complete' or 'upcoming' |
| * |
| * @param string $state |
| * @param int $cutoff Only return reviews that have occurred since this date |
| * @return Review[] |
| */ |
| public static function getReviews($state = 'upcoming', $cutoff = null) { |
| $reviews = array(); |
| |
| foreach(Forge::getForges() as $forge) { |
| $url = "{$forge->getUrl()}/json/reviews/$state"; |
| if ($list = json_decode(getUrlContents($url), true)) { |
| foreach($list as $row) { |
| $review = new Review($row); |
| if ($cutoff && ($review->getDate() < $cutoff)) continue; |
| $review->statuses[] = new ReviewStatus($row); |
| $reviews[$review->getId()] = $review; |
| } |
| } |
| } |
| usort($reviews, 'sortReviewsByDate'); |
| return $reviews; |
| } |
| |
| /** |
| * Fetch completed reviews from all forges. The results are sorted by date. |
| * @return Review[] |
| */ |
| public static function getCompletedReviews() { |
| return self::getReviews('complete'); |
| } |
| |
| 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(); |
| |
| return "$projectName $reviewName"; |
| } |
| |
| function getType() { |
| if ($this->isCreation()) return REVIEW_TYPE_CREATION; |
| if ($this->isGraduation()) return REVIEW_TYPE_GRADUATION; |
| if ($this->isRelease()) return REVIEW_TYPE_RELEASE; |
| if ($this->isRestructure()) return REVIEW_TYPE_RESTRUCTURE; |
| if ($this->isTermination()) return REVIEW_TYPE_TERMINATION; |
| return null; |
| } |
| |
| 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(' ', ' ', $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 "${projectName} $reviewName <nobr>${suffix}${icons}</nobr>"; |
| } |
| |
| /** |
| * 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 use Review::getCompletedReviews() |
| * @return Review[] |
| */ |
| function get_reviews() { |
| return Review::getCompletedReviews(); |
| } |
| |
| |
| /** |
| * @deprecated |
| * @param string $projectId |
| */ |
| function getReviewsForProject($projectId) { |
| $reviews = array(); |
| foreach(Review::getCompletedReviews() as $review) { |
| if ($review->getProjectId() == $projectId) |
| $reviews[] = $review; |
| } |
| return $reviews; |
| } |
| |
| /** |
| * State should be one of 'complete' or 'upcoming' |
| * |
| * @deprecated use Review::getReviews() |
| * @param string $state |
| * @param int $cutoff Only return reviews that have occurred since this date |
| */ |
| function getReviews($state = 'upcoming', $cutoff = null) { |
| return Review::getReviews($state, $cutoff); |
| } |
| |
| function sortReviewsByDate($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 sortReviewsByUpcoming($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; |
| } |
| ?> |