| <?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; | |
| } | |
| ?> |