Experimental new PMC tool.
Change-Id: I689244bae9c8fe2a91af588a116b534ecae9f454
diff --git a/classes/Release.class.inc b/classes/Release.class.inc
new file mode 100755
index 0000000..5aef9ff
--- /dev/null
+++ b/classes/Release.class.inc
@@ -0,0 +1,144 @@
+<?php
+/**
+ * *****************************************************************************
+ * Copyright (c) 2017 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 dirname ( __FILE__ ) . '/../classes/Project.class.php';
+require_once dirname ( __FILE__ ) . '/../classes/debug.php';
+require_once dirname ( __FILE__ ) . '/../classes/database.inc';
+
+class Release {
+ var $project;
+ var $name;
+ var $date;
+
+ /**
+ * This method answers an array containing all of
+ * @param unknown $root
+ * @param unknown $date
+ * @return Release
+ */
+ public static function releasesSince($root = null, $date = null) {
+ $releases = array ();
+ $sql = "
+ select
+ project as id, name, date
+ from ProjectReleases
+ where id regexp :pattern
+ and date > date(:date)
+ order by date";
+ $args = array(
+ ':pattern' => $root ? "^${root}(?:\..*)?$" : '',
+ ':date' => date('Y-m-d', $date ? $date : time())
+ );
+
+ return new DatabaseQuery('dashboard', $sql, $args, function ($row) {
+ $project = Project::getProject ( $row ['id'] );
+ $name = $row ['name'];
+ $date = strtotime ( $row ['date'] );
+ $reviewDate = self::getProbableReviewDate ( $date );
+
+ return new Release ( $project, $name, $date );
+ } );
+ }
+
+ private function __construct($project, $name, $date) {
+ $this->project = $project;
+ $this->name = $name;
+ $this->date = $date;
+ }
+
+ function getId() {
+ return $this->project->getId ();
+ }
+
+ function getUrl() {
+ return $this->project->getUrl ();
+ }
+
+ function getName() {
+ return $this->project->getName () . ' ' . $this->name;
+ }
+
+ function getDate() {
+ return $this->date;
+ }
+
+ private static function getProbableReviewDate($date) {
+ $diff = date ( 'w', $date ) - 3; // '3' means Wednesday
+ if ($diff < 0)
+ $diff += 7;
+
+ $date = strtotime ( "-$diff days", $date );
+ $now = strtotime ( 'now' );
+ $dates = array ();
+ while ( $date > $now ) {
+ // There's probably a better way to do this, but
+ // the month boundaries are icky, this works, and is simple.
+ if (self::isFirstOrThirdWeek ( $date )) {
+ return $date;
+ }
+ $date = strtotime ( "-1 week", $date );
+ }
+ return 0;
+ }
+
+ /**
+ * Answers whether the provided date represents either the
+ * first or the third week of the month.
+ *
+ * @see Release::getProbableReviewDate()
+ * @param int $date
+ */
+ private static function isFirstOrThirdWeek($date) {
+ $day = date ( 'j', $date ) - 1; // 0-based day of the month
+ if (floor ( $day / 7 ) == 0)
+ return true; // first week
+ if (floor ( $day / 7 ) == 2)
+ return true; // third week
+ return false;
+ }
+}
+
+
+
+function dumpFutureReleases() {
+ foreach(getFutureReleases() as $date => $releases) {
+ echo "<h3>" . ($date == 0 ? "It's already too late" : ("For review on " . date('Y-m-d', $date))) . "</h3>";
+ echo "<ul>";
+ foreach($releases as $release) {
+ echo "<li><a href=\"{$release->getUrl()}\">{$release->getName()}</a> ";
+ echo date('Y-m-d', $release->getDate());
+ dumpOpenCQs($release);
+ echo "</li>";
+ }
+ echo "</ul>";
+ }
+}
+
+function dumpOpenCQs(Release $release) {
+ echo "<ul>";
+ $sql = '
+ select
+ b.bug_id as id, b.short_desc as title
+ from bugs as b
+ join components as c on b.component_id=c.id
+ where c.name=\'$id\'
+ and bug_status in (\'NEW\', \'REOPENED\')';
+
+ query ('ipzilla', $sql, array('$id' => $release->getId()), function ($row) {
+ $id = $row ['id'];
+ $title = $row ['title'];
+ echo "<li><a target=_blank href=\"https://dev.eclipse.org/ipzilla/show_bug.cgi?id=$id\">$id</a> $title</li>";
+ });
+ echo "</ul>";
+}
+
+
diff --git a/classes/common.php b/classes/common.php
index ffa51cf..8f2c060 100644
--- a/classes/common.php
+++ b/classes/common.php
@@ -325,8 +325,6 @@
return;
}
- require_once ($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/classes/friends/friend.class.php");
-
$Session = $App->useSession("required");
$friend = $Session->getFriend();
diff --git a/classes/database.inc b/classes/database.inc
index b58991b..bc39976 100644
--- a/classes/database.inc
+++ b/classes/database.inc
@@ -88,4 +88,21 @@
$mysqli->close();
}
+
+class DatabaseQuery {
+ var $database, $query, $args, $callable;
+
+ function __construct($database, $query, $args, $callable) {
+ $this->database = $database;
+ $this->query = $query;
+ $this->args = $args;
+ $this->callable = $callable;
+ }
+
+ public function withEach($callback) {
+ query($this->database, $this->query, $this->args, function($row) use (&$callback) {
+ call_user_func($callback, call_user_func($this->callable, $row));
+ });
+ }
+}
?>
\ No newline at end of file
diff --git a/tools/pmc.php b/tools/pmc.php
new file mode 100644
index 0000000..d1ae379
--- /dev/null
+++ b/tools/pmc.php
@@ -0,0 +1,96 @@
+<?php
+/*******************************************************************************
+ * Copyright (c) 2018 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
+ *******************************************************************************/
+
+/**
+
+ */
+require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/app.class.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/nav.class.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/eclipse.org-common/system/menu.class.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/projects/classes/Project.class.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/projects/classes/common.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/projects/classes/database.inc");
+
+$App = new App();
+$Nav = new Nav();
+$Menu = new Menu();
+include($App->getProjectCommon());
+
+$pageTitle = "Eclipse Foundation PMC Tasks";
+$pageKeywords = "";
+$pageAuthor = "Wayne Beaton";
+
+$root = Project::getProject($_GET['id']);
+if ($root->isTopLevel()) {
+
+}
+
+function withCqsAwaitingPMC($id, $callable) {
+ $sql = "
+ select
+ b.bug_id as id,
+ c.name as project,
+ b.short_desc as description,
+ b.cf_type as type,
+ date(b.creation_ts) as created,
+ b.bug_status as status,
+ b.resolution as resolution,
+ b.bug_severity as state
+ from bugs as b
+ join components as c on b.component_id = c.id
+ join products as p on b.product_id = p.id
+ where p.name='{$id}'
+ and bug_status='NEW'
+ and bug_severity='awaiting_pmc'
+ order by c.name
+ ";
+ query('ipzilla', $sql, array(), $callable);
+}
+
+
+ob_start();
+?>
+<div id="maincontent">
+<div id="midcolumn">
+<h1><?= $pageTitle ?></h1>
+
+<p><strong>Experimental</strong> Provide a list of links to tasks that require the PMC's attention.</p>
+
+<h3>Intellectual Property</h3>
+
+<?php
+$cqs = array();
+withCqsAwaitingPMC($root->getId(), function($cq) use (&$cqs) {
+ $cqs[$cq['project']][] = $cq;
+});
+
+if ($cqs) {
+ print "<p>The following CQs require some attention from the PMC.</p>";
+
+ foreach ($cqs as $id => $list) {
+ $project = Project::getProject($id);
+ $name = $project ? $project->getFormalName() : $id;
+ print "<h4>{$name}</h4>";
+ print "<ul>";
+ foreach($list as $cq) {
+ print "<li><a href=\"https://dev.eclipse.org/ipzilla/show_bug.cgi?id={$cq['id']}\">{$cq['id']}</a> {$cq['description']}</li>";
+ }
+ print "</ul>";
+ }
+}
+?>
+
+</div>
+</div>
+
+<?php
+$html = ob_get_contents();
+ob_end_clean();
+$App->generatePage($theme, $Menu, $Nav, $pageAuthor, $pageKeywords, $pageTitle, $html);
+?>