| <?php | |
| /******************************************************************************* | |
| * Copyright (c) 2010, 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: | |
| * Wayne Beaton (Eclipse Foundation) - initial API and implementation | |
| * Wayne Beaton (Eclipse Foundation) - Added getProjectId() function | |
| *******************************************************************************/ | |
| /* | |
| * This script assumes that it is being included by another script. We | |
| * assume that the $App variable has already been defined. | |
| */ | |
| require_once(dirname(__FILE__) . "/common.php"); | |
| require_once(dirname(__FILE__) . "/debug.php"); | |
| trace_file_info(__FILE__); | |
| class Proposal { | |
| var $info; | |
| var $date; | |
| var $statuses = array(); | |
| function __construct($info) { | |
| $this->info = $info; | |
| } | |
| function getName() { | |
| return $this->info['ProposalName']; | |
| } | |
| /** | |
| * Once the project is created, the ProjectId field should be filled in. | |
| */ | |
| function getProjectId() { | |
| return $this->info['ProjectId']; | |
| } | |
| function getProjectUrl() { | |
| return normalizeHttpUrl($this->info['ProjectURL']); | |
| } | |
| function asHtml() { | |
| $name = $this->getName(); | |
| $proposalUrl = $this->getProposalUrl(); | |
| $projectUrl = $this->getProjectUrl(); | |
| $text = htmlentities($name); | |
| if ($projectUrl) $text = "<a href=\"$projectUrl\">$text</a>"; | |
| if ($proposalUrl) | |
| $text .= " <a href=\"$proposalUrl\"><img style=\"vertical-align:top\" title=\"Review Documentation\" src=\"http://dev.eclipse.org/small_icons/mimetypes/text-x-generic.png\"/></a>"; | |
| if ($this->isSuccessful()) { | |
| $text .= "<img style=\"vertical-align:top\" title=\"This project has been created.\" src=\"/projects/images/ok.gif\">"; | |
| } else if ($this->isActive()) { | |
| $text .= "<img style=\"vertical-align:top\" title=\"This proposal is active.\" src=\"http://dev.eclipse.org/small_icons/status/weather-clear.png\">"; | |
| } else { | |
| $text .= "<img style=\"vertical-align:top\" title=\"This proposal is inactive.\" src=\"http://dev.eclipse.org/small_icons/status/weather-showers-scattered.png\">"; | |
| } | |
| if ($this->isWithdrawn()) $text = "<strike>$text</strike><img style=\"vertical-align:top\" title=\"Review Withdrawn\" src=\"http://dev.eclipse.org/small_icons/actions/process-stop.png\">"; | |
| return $text; | |
| } | |
| /** | |
| * This function gets the scope for the receiver from the | |
| * proposal document. This is a relatively expensive operation, and | |
| * no caching is provided. We use some very crude parsing to extract | |
| * the contents from the <h2>Scope</h2> section of the document. | |
| */ | |
| function getScope() { | |
| $id = $this->getProjectId(); | |
| $trace = trace("Finding scope for $id"); | |
| $url = $this->getProposalUrl(); | |
| if (!$url) { | |
| $trace->trace("Proposal URL is not specified."); | |
| return null; | |
| } | |
| $trace->trace("URL is specified as $url"); | |
| $path = $this->getProposalDocumentFilePath($url); | |
| $trace->trace("Proposal URL $path"); | |
| $contents = @file_get_contents($path); | |
| return $this->extractScope($trace, $contents); | |
| } | |
| /** | |
| * Find the real path of the proposal document. | |
| * @internal | |
| * @return NULL|string | |
| */ | |
| function getProposalDocumentFilePath($url) { | |
| $path = realpath(normalizeFilePathUrl($url)); | |
| if (is_file($path)) return $path; | |
| $file = "$path/proposal.html"; | |
| if (is_file($file)) return $file; | |
| $file = "$path/index.php"; | |
| if (is_file($file)) return $file; | |
| trace("Cannot find Proposal document at $url."); | |
| return null; | |
| } | |
| /** | |
| * @internal | |
| * @param unknown_type $url | |
| * @param unknown_type $contents | |
| * @return NULL|string | |
| */ | |
| function extractScope($trace, $contents) { | |
| if (!$contents) { | |
| $trace->trace("Proposal document is empty."); | |
| return null; | |
| } | |
| if (preg_match('/<h2[^>]*>.*?Scope.*?<\/h2>(.*?)<h\d[^>]*>/is', $contents, $matches)) { | |
| $scope = $matches[1]; | |
| } else { | |
| $trace->trace("Cannot find scope tag."); | |
| return null; | |
| } | |
| $scope = preg_replace('/<!--.*?-->/s','', $scope); | |
| $scope = preg_replace('/\s+/', ' ', $scope); | |
| $scope = trim($scope); | |
| $trace->trace("Scope: $scope"); | |
| return $scope; | |
| } | |
| function isWithdrawn() { | |
| return $this->getProposalWithdrawn() != null; | |
| } | |
| function isSuccessful() { | |
| return $this->getReviewSuccessful() != null; | |
| } | |
| function isActive() { | |
| if ($this->isSuccessful()) return false; | |
| if ($this->isWithdrawn()) return false; | |
| return $this->getActiveDate() > strtotime('-3 month'); | |
| } | |
| function getReviewSuccessful() { | |
| return $this->getStatus('Review Successful'); | |
| } | |
| function getProposalWithdrawn() { | |
| return $this->getStatus('Proposal Withdrawn'); | |
| } | |
| function getProposalPosted() { | |
| return $this->getStatus('Proposal Posted'); | |
| } | |
| function getProposalUrl() { | |
| return normalizeHttpUrl($this->info['ProposalURL']); | |
| } | |
| /** | |
| * This function returns the date of the proposal. We consider this to | |
| * be the date of the earliest status. | |
| */ | |
| function getDate() { | |
| if (!$this->date) $this->date = $this->compute_date(); | |
| return $this->date; | |
| } | |
| function getActiveDate() { | |
| $date = 0; | |
| foreach($this->statuses as $status) { | |
| $status_date = $status->getDate(); | |
| if ($status_date > $date) $date = $status_date; | |
| } | |
| return $date; | |
| } | |
| /** | |
| * It would be easier to just determine | |
| * this value from the 'Proposal Posted' date, but we have found some | |
| * entries that do not have this status... | |
| * | |
| * THIS IS NOT API | |
| */ | |
| /* private */ function compute_date() { | |
| $date = strtotime('now'); | |
| foreach($this->statuses as $status) { | |
| $status_date = $status->getDate(); | |
| if ($status_date < $date) $date = $status_date; | |
| } | |
| return $date; | |
| } | |
| /** | |
| * THIS IS NOT API | |
| */ | |
| /* private */ function getStatus($text) { | |
| foreach($this->statuses as $status) { | |
| if ($status->getText() == $text) return $status; | |
| } | |
| return null; | |
| } | |
| } | |
| class ProposalStatus { | |
| var $info; | |
| function __construct($info) { | |
| $this->info = $info; | |
| } | |
| function getText() { | |
| return $this->info['Status']; | |
| } | |
| function getDate() { | |
| return strtotime($this->info['Date']); | |
| } | |
| } | |
| function get_proposals($App) { | |
| $sql = " | |
| SELECT | |
| r.id as Id, | |
| r.ProjectName, r.ProjectId, | |
| ProjectURL, ProposalURL, SlidesURL, IPLogURL, BugNumber, ReviewDate, | |
| ReviewName, ProposalName, | |
| 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 | |
| length(trim(ProposalName)) > 0 | |
| ORDER BY Date desc"; | |
| $result = $App->foundation_sql($sql); | |
| $proposals = array(); | |
| while($row = mysql_fetch_assoc($result)) { | |
| $id = $row['Id']; | |
| if (isset($proposals[$id])) { | |
| $proposal = $proposals[$id]; | |
| } else { | |
| $proposal = new Proposal($row); | |
| $proposals[$id] = $proposal; | |
| } | |
| $proposal->statuses[] = new ProposalStatus($row); | |
| } | |
| return $proposals; | |
| } | |
| /** | |
| * This function returns the proposal corresponding to the project | |
| * with the provided id. | |
| * | |
| * Requires that the $App variable be defined. | |
| * | |
| * @param string $id A project id. | |
| */ | |
| function getProposalForProject($id) { | |
| if (!isValidProjectId($id)) return; | |
| global $App; | |
| $sql = " | |
| SELECT | |
| r.id as Id, | |
| r.ProjectName, r.ProjectId, | |
| ProjectURL, ProposalURL, SlidesURL, IPLogURL, BugNumber, ReviewDate, | |
| ReviewName, ProposalName, | |
| 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 | |
| trim(r.ProposalURL) != '' | |
| AND r.ProjectId = '$id' | |
| ORDER BY Date desc"; | |
| $result = $App->foundation_sql($sql); | |
| $proposal = null; | |
| while($row = mysql_fetch_assoc($result)) { | |
| if (!$proposal) $proposal = new Proposal($row); | |
| $proposal->statuses[] = new ProposalStatus($row); | |
| } | |
| return $proposal; | |
| } | |
| ?> |