blob: 04934ef4f23f486b3e95ef1b47aa8f709cc7fb98 [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
* 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=\"Proposal\" 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\">";
}
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);
}
// FIXME Refactor redundant code
if ($forge = json_decode(@file_get_contents('http://projects.eclipse.org/json/proposals/all'), true)) {
foreach($forge as $row) {
$id = $row['Id'];
if (isset($proposals[$id])) {
$proposal = $proposals[$id];
} else {
$proposal = new Proposal($row);
$proposals[$id] = $proposal;
}
$proposal->statuses[] = new ProposalStatus($row);
}
}
if ($forge = json_decode(@file_get_contents('http://www.locationtech.org/json/proposals/all'), true)) {
foreach($forge as $row) {
$id = $row['Id'];
if (isset($proposals[$id])) {
$proposal = $proposals[$id];
} else {
$proposal = new Proposal($row);
$proposals[$id] = $proposal;
}
$proposal->statuses[] = new ProposalStatus($row);
}
}
if ($forge = json_decode(@file_get_contents('http://www.polarsys.org/json/proposals/all'), true)) {
foreach($forge as $row) {
$id = $row['Id'];
$proposal = new Proposal($row);
$proposal->statuses[] = new ProposalStatus($row);
$proposals[$id] = $proposal;
}
}
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;
}
function getProposals() {
$proposals = array();
foreach(getForges() as $forge) {
$url = "$forge/json/proposals";
$json = getUrlContents($url);
if ($list = json_decode($json, true)) {
foreach($list as $row) {
$proposals[] = new Proposal($row);
}
}
}
usort($proposals, 'proposals_sortByDate');
return $proposals;
}
function proposals_sortByDate($a, $b) {
$aDate = $a->getDate();
$bDate = $b->getDate();
if ($aDate < $bDate) return 1;
if ($aDate > $bDate) return -1;
return 0;
}
?>