[Fusionforge-commits] FusionForge branch Branch_5_3 updated. 99d7a6415c3ebbd86c8f9d94a1c5acd9ee8e9b41

Franck VILLAUME nerville at fusionforge.org
Mon Feb 3 13:55:21 CET 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "FusionForge".

The branch, Branch_5_3 has been updated
       via  99d7a6415c3ebbd86c8f9d94a1c5acd9ee8e9b41 (commit)
       via  8b0255b3be29700918d0ac657994ec1618d7c5b1 (commit)
       via  9b05f43f21162ab8042728344991c6f3a5437757 (commit)
       via  97a45eaf51d70a54d411734eccb3cbc64ef5c616 (commit)
      from  6f9d38eeb8e1903eb45941567817d7f593d1d27d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 99d7a6415c3ebbd86c8f9d94a1c5acd9ee8e9b41
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Tue Jan 28 17:59:36 2014 +0100

    [#464] Tracker Item Votes: add sorting capability, fix typo

diff --git a/src/common/tracker/ArtifactFactory.class.php b/src/common/tracker/ArtifactFactory.class.php
index ad5b4b9..448993a 100644
--- a/src/common/tracker/ArtifactFactory.class.php
+++ b/src/common/tracker/ArtifactFactory.class.php
@@ -457,7 +457,7 @@ class ArtifactFactory extends Error {
 				$this->artifacts[] = new Artifact($this->ArtifactType, $arr);
 			}
 		}
-		if ($sortcol == 'extra' || $sortcol != '_votes' || $sortcol != '_voters' || $sortcol != '_votage') {
+		if ($sortcol == 'extra' || $sortcol == '_votes' || $sortcol == '_voters' || $sortcol == '_votage') {
 			sortArtifactList ($this->artifacts, $this->order_col, $this->sort) ;
 		}
 		return $this->artifacts;

commit 8b0255b3be29700918d0ac657994ec1618d7c5b1
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Tue Jan 28 17:45:29 2014 +0100

    [#464] Tracker Item Votes: add sorting capability

diff --git a/src/common/tracker/Artifact.class.php b/src/common/tracker/Artifact.class.php
index 7fc55e3..3a93d23 100644
--- a/src/common/tracker/Artifact.class.php
+++ b/src/common/tracker/Artifact.class.php
@@ -7,6 +7,7 @@
  * Copyright 2009, Roland Mas
  * Copyright (C) 2009-2013 Alain Peyrat, Alcatel-Lucent
  * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
+ * Copyright 2014, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -1921,6 +1922,27 @@ class ArtifactComparator {
 			$b_priority = $b->getPriority() ;
 			return ($a_priority < $b_priority) ? -1 : 1;
 			break;
+		case '_votes':
+			$a->getVotes();
+			$a_votes = $a->votes[0];
+			$b->getVotes();
+			$b_votes = $b->votes[0];
+			return ($a_votes < $b_votes) ? -1 : 1;
+			break;
+		case '_voters':
+			$a->getVotes();
+			$a_votes = $a->votes[1];
+			$b->getVotes();
+			$b_votes = $b->votes[1];
+			return ($a_votes < $b_votes) ? -1 : 1;
+			break;
+		case '_votage':
+			$a->getVotes();
+			$a_votes = $a->votes[2];
+			$b->getVotes();
+			$b_votes = $b->votes[2];
+			return ($a_votes < $b_votes) ? -1 : 1;
+			break;
 		default:
 			$aa=$a->getExtraFieldDataText();
 			$ba=$b->getExtraFieldDataText();
diff --git a/src/common/tracker/ArtifactFactory.class.php b/src/common/tracker/ArtifactFactory.class.php
index 4929466..ad5b4b9 100644
--- a/src/common/tracker/ArtifactFactory.class.php
+++ b/src/common/tracker/ArtifactFactory.class.php
@@ -4,6 +4,7 @@
  *
  * Copyright 2002, GForge, LLC
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2014, Franck Villaume - TrivialDev
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -203,7 +204,10 @@ class ArtifactFactory extends Error {
 					   'assigned_to',
 					   'submitted_by',
 					   'priority',
-					   'last_modified_date') ;
+					   'last_modified_date',
+					   '_votes',
+					   '_voters',
+					   '_votage') ;
 		$efarr = $this->ArtifactType->getExtraFields();
 		$keys=array_keys($efarr);
 		for ($k=0; $k<count($keys); $k++) {
@@ -430,9 +434,12 @@ class ArtifactFactory extends Error {
 							    'close_date',
 							    'assigned_to',
 							    'submitted_by',
-							    'priority'));
+							    'priority',
+							    '_votage',
+							    '_voters',
+							    '_votes'));
 
-		if ($sortcol != 'extra') {
+		if ($sortcol != 'extra' && $sortcol != '_votes' && $sortcol != '_voters' && $sortcol != '_votage' ) {
 			$ordersql = " ORDER BY Artifacts.group_artifact_id $sortorder, Artifacts.$sortcol $sortorder" ;
 		} else {
 			$ordersql = ''  ;
@@ -450,7 +457,7 @@ class ArtifactFactory extends Error {
 				$this->artifacts[] = new Artifact($this->ArtifactType, $arr);
 			}
 		}
-		if ($sortcol == 'extra') {
+		if ($sortcol == 'extra' || $sortcol != '_votes' || $sortcol != '_voters' || $sortcol != '_votage') {
 			sortArtifactList ($this->artifacts, $this->order_col, $this->sort) ;
 		}
 		return $this->artifacts;
diff --git a/src/common/tracker/actions/browse.php b/src/common/tracker/actions/browse.php
index 25f9e37..7d8e331 100644
--- a/src/common/tracker/actions/browse.php
+++ b/src/common/tracker/actions/browse.php
@@ -5,7 +5,7 @@
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright 2010 Roland Mas
  * Copyright (C) 2011-2012 Alain Peyrat - Alcatel-Lucent
- * Copyright 2012-2013, Franck Villaume - TrivialDev
+ * Copyright 2012-2014, Franck Villaume - TrivialDev
  * Copyright 2011, Iñigo Martinez
  * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
@@ -201,6 +201,9 @@ $order_name_arr[]=_('Last Modified Date');
 $order_name_arr[]=_('Close Date');
 $order_name_arr[]=_('Submitter');
 $order_name_arr[]=_('Assignee');
+$order_name_arr[]=_('# Votes');
+$order_name_arr[]=_('# Voters');
+$order_name_arr[]=_('% Votes');
 
 $order_arr=array();
 $order_arr[]='artifact_id';
@@ -211,6 +214,9 @@ $order_arr[]='last_modified_date';
 $order_arr[]='close_date';
 $order_arr[]='submitted_by';
 $order_arr[]='assigned_to';
+$order_arr[]='_votes';
+$order_arr[]='_voters';
+$order_arr[]='_votage';
 
 //
 //	custom sort arrays to build pop-up box

commit 9b05f43f21162ab8042728344991c6f3a5437757
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Tue Jan 28 16:46:20 2014 +0100

    [#464] Tracker Item Votes: integration code from Evolvis

diff --git a/src/db/20140128-tracker-vote-table.sql b/src/db/20140128-tracker-vote-table.sql
new file mode 100644
index 0000000..7362d32
--- /dev/null
+++ b/src/db/20140128-tracker-vote-table.sql
@@ -0,0 +1,12 @@
+-- Add a table to count tracker votes.
+
+CREATE TABLE artifact_votes (
+	artifact_id	integer		NOT NULL,
+	user_id		integer		NOT NULL,
+	CONSTRAINT artifact_votes_fk_aid
+		FOREIGN KEY (artifact_id) REFERENCES artifact (artifact_id),
+	CONSTRAINT artifact_votes_fk_uid
+		FOREIGN KEY (user_id) REFERENCES users (user_id),
+	CONSTRAINT artifact_votes_pk
+		PRIMARY KEY (artifact_id, user_id)
+);

commit 97a45eaf51d70a54d411734eccb3cbc64ef5c616
Author: Franck Villaume <franck.villaume at trivialdev.com>
Date:   Tue Jan 28 16:41:32 2014 +0100

    backport from master: [#464] Tracker Item Votes: integration code from Evolvis

diff --git a/src/common/include/RBAC.php b/src/common/include/RBAC.php
index e97e13a..3989985 100644
--- a/src/common/include/RBAC.php
+++ b/src/common/include/RBAC.php
@@ -4,7 +4,8 @@
  *
  * Copyright 2004, GForge, LLC
  * Copyright 2009-2010, Roland Mas
- * Copyright 2012-2013, Franck Villaume - TrivialDev
+ * Copyright 2012-2014, Franck Villaume - TrivialDev
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  * Copyright 2013, French Ministry of National Education
  * http://fusionforge.org
  *
@@ -68,11 +69,11 @@ abstract class BaseRole extends Error {
 			'pm_admin' => array(0, 1),
 			'forum_admin' => array(0, 1),
 
-			'tracker' => array(0, 1, 9, 11, 13, 15),
+			'tracker' => array(0, 1, 9, 11, 13, 15, 17, 19, 21, 23),
 			'pm' => array(0, 1, 3, 5, 7),
 			'forum' => array(0, 1, 2, 3, 4),
 
-			'new_tracker' => array(0, 1, 9, 11, 13, 15),
+			'new_tracker' => array(0, 1, 9, 11, 13, 15, 17, 19, 21, 23),
 			'new_pm' => array(0, 1, 3, 5, 7),
 			'new_forum' => array(0, 1, 2, 3, 4),
 
@@ -707,10 +708,9 @@ abstract class BaseRole extends Error {
 			case 'submit':
 				return (($value & 8) != 0) ;
 				break ;
-			/*
-			 * bit4 (value & 16) is reserved
-			 * for tracker item vote from Evolvis
-			 */
+			case 'vote':
+				return (($value & 16) != 0);
+				break;
 			}
 			break ;
 
@@ -1093,6 +1093,19 @@ class RoleAnonymous extends BaseRole implements PFO_RoleAnonymous {
 		$c = __CLASS__ ;
 		self::$_instance = new $c ;
 
+		 /* drop vote rights from RoleAnonymous */
+		 // why ?????
+		foreach (array('tracker', 'new_tracker') as $x) {
+			$y = array();
+			foreach (self::$_instance->role_values[$x] as $z) {
+				if (($z & 16) != 0) {
+					continue;
+				}
+				$y[] = $z;
+			}
+			self::$_instance->role_values[$x] = $y;
+		}
+
 		$res = db_query_params ('SELECT r.role_id FROM pfo_role r, pfo_role_class c WHERE r.role_class = c.class_id AND c.class_name = $1',
 					array ('PFO_RoleAnonymous')) ;
 		if (!$res || !db_numrows($res)) {
diff --git a/src/common/include/RBACEngine.class.php b/src/common/include/RBACEngine.class.php
index a529162..c46a295 100644
--- a/src/common/include/RBACEngine.class.php
+++ b/src/common/include/RBACEngine.class.php
@@ -3,6 +3,7 @@
  * FusionForge RBAC engine
  *
  * Copyright 2010, Roland Mas
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -364,6 +365,9 @@ class RBACEngine extends Error implements PFO_RBACEngine {
 			case 'submit':
 				$qpa = db_construct_qpa ($qpa, 'AND (perm_val & 8) = 8');
 				break;
+			case 'vote':
+				$qpa = db_construct_qpa ($qpa, 'AND (perm_val & 16) = 16');
+				break;
 			}
 			break;
 		case 'pm':
@@ -423,7 +427,7 @@ class RBACEngine extends Error implements PFO_RBACEngine {
 			$result = array_merge ($result, $this->_getRolesIdByAllowedAction ('project_admin', $reference));
 			break;
 		case 'tracker':
-			if ($action != 'tech') {
+			if ($action != 'tech' && $action != 'vote') {
 				$t = artifactType_get_object ($reference);
 				$result = array_merge ($result, $this->_getRolesIdByAllowedAction ('tracker_admin', $t->Group->getID()));
 			}
@@ -439,7 +443,7 @@ class RBACEngine extends Error implements PFO_RBACEngine {
 			$result = array_merge ($result, $this->_getRolesIdByAllowedAction ('forum_admin', $t->Group->getID()));
 			break;
 		case 'new_tracker':
-			if ($action != 'tech') {
+			if ($action != 'tech' && $action != 'vote') {
 				$result = array_merge ($result, $this->_getRolesIdByAllowedAction ('tracker_admin', $reference));
 			}
 			break;
diff --git a/src/common/include/rbac_texts.php b/src/common/include/rbac_texts.php
index 736368b..9fc0cde 100644
--- a/src/common/include/rbac_texts.php
+++ b/src/common/include/rbac_texts.php
@@ -3,6 +3,7 @@
  * FusionForge localisation
  *
  * Copyright 2007-2010, Roland Mas
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -80,6 +81,14 @@ function setup_rbac_strings () {
 								  'tracker13' => _('Manager'),
 								  'tracker14' => _('Tech & manager (no read access)'),
 								  'tracker15' => _('Tech & manager'),
+								  'tracker16' => _('No access + Vote'),
+								  'tracker17' => _('Read only + Vote'),
+								  'tracker18' => _('Technician (no read access) + Vote'),
+								  'tracker19' => _('Technician + Vote'),
+								  'tracker20' => _('Manager (no read access) + Vote'),
+								  'tracker21' => _('Manager + Vote'),
+								  'tracker22' => _('Tech & manager (no read access) + Vote'),
+								  'tracker23' => _('Tech & manager + Vote'),
 								  'pm0' => _('No Access'),
 								  'pm1' => _('Read only'),
 								  'pm2' => _('Technician (no read access)'),
@@ -110,6 +119,14 @@ function setup_rbac_strings () {
 								  'new_tracker13' => _('Manager'),
 								  'new_tracker14' => _('Tech & manager (no read access)'),
 								  'new_tracker15' => _('Tech & manager'),
+								  'new_tracker16' => _('No access + Vote'),
+								  'new_tracker17' => _('Read only + Vote'),
+								  'new_tracker18' => _('Technician (no read access) + Vote'),
+								  'new_tracker19' => _('Technician + Vote'),
+								  'new_tracker20' => _('Manager (no read access) + Vote'),
+								  'new_tracker21' => _('Manager + Vote'),
+								  'new_tracker22' => _('Tech & manager (no read access) + Vote'),
+								  'new_tracker23' => _('Tech & manager + Vote'),
 								  'new_pm0' => _('No Access'),
 								  'new_pm1' => _('Read only'),
 								  'new_pm2' => _('Technician (no read access)'),
diff --git a/src/common/include/utils.php b/src/common/include/utils.php
index d40453f..f5c4259 100644
--- a/src/common/include/utils.php
+++ b/src/common/include/utils.php
@@ -1791,6 +1791,18 @@ function util_sudo_effective_user($username, $function, $params=array()) {
 	return true;
 }
 
+function getselfhref($p = array(), $return_encoded = true) {
+	global $group_id, $atid, $aid, $is_add;
+	$p['group_id'] = $group_id;
+	$p['atid'] = $atid;
+	if (!$is_add) {
+		/* grml… */
+		$p['aid'] = $aid;
+		$p['artifact_id'] = $aid;
+	}
+	return util_gethref(false, $p, $return_encoded);
+}
+
 // Local Variables:
 // mode: php
 // c-file-style: "bsd"
diff --git a/src/common/tracker/Artifact.class.php b/src/common/tracker/Artifact.class.php
index a078bdd..7fc55e3 100644
--- a/src/common/tracker/Artifact.class.php
+++ b/src/common/tracker/Artifact.class.php
@@ -6,6 +6,7 @@
  * Copyright 2002-2004, GForge, LLC
  * Copyright 2009, Roland Mas
  * Copyright (C) 2009-2013 Alain Peyrat, Alcatel-Lucent
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -126,6 +127,12 @@ class Artifact extends Error {
 	var $relatedtasks;
 
 	/**
+	 * cached return value of getVotes
+	 * @var	int|bool	$votes
+	 */
+	var $votes = false;
+
+	/**
 	 * Artifact - constructor.
 	 *
 	 * @param	ArtifactType	$ArtifactType	The ArtifactType object.
@@ -293,6 +300,7 @@ class Artifact extends Error {
 	 * @return	boolean	success.
 	 */
 	function fetchData($artifact_id) {
+		$this->votes = false;
 		$res = db_query_params ('SELECT * FROM artifact_vw WHERE artifact_id=$1 AND group_artifact_id=$2',
 					array ($artifact_id,
 					       $this->ArtifactType->getID())) ;
@@ -1777,6 +1785,90 @@ class Artifact extends Error {
 
 		return $return;
 	}
+
+	/**
+	 * castVote - Vote on this tracker item or retract the vote
+	 * @param	bool	$value	true to cast, false to retract
+	 * @return	bool	success (false sets error message)
+	 */
+	function castVote($value = true) {
+		if (!($uid = user_getid()) || $uid == 100) {
+			$this->setMissingParamsError(_('User ID not passed'));
+			return false;
+		}
+		if (!$this->ArtifactType->canVote()) {
+			$this->setPermissionDeniedError();
+			return false;
+		}
+		$has_vote = $this->hasVote($uid);
+		if ($has_vote == $value) {
+			/* nothing changed */
+			return true;
+		}
+		if ($value) {
+			$res = db_query_params('INSERT INTO artifact_votes (artifact_id, user_id) VALUES ($1, $2)',
+						array($this->getID(), $uid));
+		} else {
+			$res = db_query_params('DELETE FROM artifact_votes WHERE artifact_id=$1 AND user_id=$2',
+						array($this->getID(), $uid));
+		}
+		if (!$res) {
+			$this->setError(db_error());
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * hasVote - Check if a user has voted on this tracker item
+	 *
+	 * @param	int	$uid	user ID (default: current user)
+	 * @return	bool	true if a vote exists
+	 */
+	function hasVote($uid=false) {
+		if (!$uid) {
+			$uid = user_getid();
+		}
+		if (!$uid || $uid == 100) {
+			return false;
+		}
+		$res = db_query_params('SELECT * FROM artifact_votes WHERE artifact_id=$1 AND user_id=$2',
+					array($this->getID(), $uid));
+		return (db_numrows($res) == 1);
+	}
+
+       /**
+        * getVotes - get number of valid cast and potential votes
+        *
+        * @return	array	(votes, voters, percent)
+        */
+	function getVotes() {
+		if ($this->votes !== false) {
+			return $this->votes;
+		}
+
+		$voters = $this->ArtifactType->getVoters();
+		unset($voters[0]);	/* just in case */
+		unset($voters[100]);	/* need users */
+		if (($numvoters = count($voters)) < 1) {
+			$this->votes = array(0, 0, 0);
+			return $this->votes;
+		}
+
+		$res = db_query_params('SELECT COUNT(*) AS count FROM artifact_votes WHERE artifact_id=$1 AND user_id=ANY($2)',
+					array($this->getID(), db_int_array_to_any_clause($voters)));
+		$db_count = db_fetch_array($res);
+		$numvotes = $db_count['count'];
+
+		/* check for invalid values */
+		if ($numvotes < 0 || $numvoters < $numvotes) {
+			$this->votes = array(-1, -1, 0);
+		} else {
+			$this->votes = array($numvotes, $numvoters,
+				(int)($numvotes * 100 / $numvoters + 0.5));
+		}
+		return $this->votes;
+	}
 }
 
 class ArtifactComparator {
diff --git a/src/common/tracker/ArtifactType.class.php b/src/common/tracker/ArtifactType.class.php
index 3fa9d15..45d3dbe 100644
--- a/src/common/tracker/ArtifactType.class.php
+++ b/src/common/tracker/ArtifactType.class.php
@@ -6,6 +6,7 @@
  * Copyright 2002-2004, GForge, LLC
  * Copyright 2009, Roland Mas
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -142,6 +143,12 @@ class ArtifactType extends Error {
 	var $element_status;
 
 	/**
+	 * cached return value of getVoters
+	 * @var	int|bool	$voters
+	 */
+	var $voters = false;
+
+	/**
 	 * ArtifactType - constructor.
 	 *
 	 * @param	Group		$Group			The Group object.
@@ -273,6 +280,7 @@ class ArtifactType extends Error {
 	 * @return	boolean	success.
 	 */
 	function fetchData($artifact_type_id) {
+		$this->voters = false;
 		$res = db_query_params('SELECT * FROM artifact_group_list_vw
 			WHERE group_artifact_id=$1
 			AND group_id=$2',
@@ -1059,6 +1067,38 @@ class ArtifactType extends Error {
 		return $res;
 	}
 
+	/**
+	 * canVote - check whether the current user can vote on
+	 *		items in this tracker
+	 *
+	 * @return	bool	true if they can
+	 */
+	function canVote() {
+		return forge_check_perm('tracker', $this->getID(), 'vote');
+	}
+
+	/**
+	 * getVoters - get IDs of users that may vote on
+	 *		items in this tracker
+	 *
+	 * @return	array	list of user IDs
+	 */
+	function getVoters() {
+		if ($this->voters !== false) {
+			return $this->voters;
+		}
+
+		$this->voters = array();
+		if (($engine = RBACEngine::getInstance())
+			&& ($voters = $engine->getUsersByAllowedAction('tracker', $this->getID(), 'vote'))
+			&& (count($voters) > 0)) {
+			foreach ($voters as $voter) {
+				$voter_id = $voter->getID();
+				$this->voters[$voter_id] = $voter_id;
+			}
+		}
+		return $this->voters;
+	}
 }
 
 // Local Variables:
diff --git a/src/common/tracker/actions/browse.php b/src/common/tracker/actions/browse.php
index 3fcf111..25f9e37 100644
--- a/src/common/tracker/actions/browse.php
+++ b/src/common/tracker/actions/browse.php
@@ -7,6 +7,7 @@
  * Copyright (C) 2011-2012 Alain Peyrat - Alcatel-Lucent
  * Copyright 2012-2013, Franck Villaume - TrivialDev
  * Copyright 2011, Iñigo Martinez
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -571,6 +572,12 @@ if ($art_arr && $art_cnt > 0) {
 				$title=_('Related Tasks');
 			if ($f == 'last_modified_date')
 				$title=_('Last Modified Date');
+			if ($f == '_votes')
+				$title = _('# Votes');
+			if ($f == '_voters')
+				$title = _('# Voters');
+			if ($f == '_votage')
+				$title = _('% Voted');
 		}
 		$title_arr[] = $title;
 	}
@@ -580,6 +587,7 @@ if ($art_arr && $art_cnt > 0) {
 	}
 
 	$then=(time()-$ath->getDuePeriod());
+	$voters = count($ath->getVoters());
 
 	for ($i=$start; $i<$max; $i++) {
 		$extra_data = $art_arr[$i]->getExtraFieldDataText();
@@ -648,6 +656,14 @@ if ($art_arr && $art_cnt > 0) {
 
 				}
 				echo '<td>' . $value .'</td>';
+			} else if ($f == '_votes') {
+				$v = $art_arr[$i]->getVotes();
+				echo html_e('td', array(), $v[0], false);
+			} else if ($f == '_voters') {
+				echo html_e('td', array(), $voters, false);
+			} else if ($f == '_votage') {
+				$v = $art_arr[$i]->getVotes();
+				echo html_e('td', array(), $v[2], false);
 			} else {
 				// Display ? for unknown values.
 				echo '<td>?</td>';
diff --git a/src/common/tracker/actions/detail.php b/src/common/tracker/actions/detail.php
index 63458f2..d0e5e95 100644
--- a/src/common/tracker/actions/detail.php
+++ b/src/common/tracker/actions/detail.php
@@ -4,7 +4,8 @@
  *
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
- * Copyright 2012, Franck Villaume - TrivialDev
+ * Copyright 2012-2014, Franck Villaume - TrivialDev
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -57,6 +58,22 @@ echo notepad_func();
 						html_image('ic/'.$img.'','20','20').' '.$text.'</strong></a>';
 					?>
 			</td>
+			<td><?php
+					$votes = $ah->getVotes();
+					echo '<span id="tracker-votes" title="'.html_get_tooltip_description('votes').'" >'.html_e('strong', array(), _('Votes') . _(': ')).sprintf('%1$d/%2$d (%3$d%%)', $votes[0], $votes[1], $votes[2]).'</span>';
+					if ($ath->canVote()) {
+						if ($ah->hasVote()) {
+							$key = 'pointer_down';
+							$txt = _('Retract Vote');
+						} else {
+							$key = 'pointer_up';
+							$txt = _('Cast Vote');
+						}
+						echo '<a id="tracker-vote" alt="'.$txt.'" title="'.html_get_tooltip_description('vote').'" href="'.getselfhref(array('func' => $key)) . '">' .
+							html_image('ic/' . $key . '.png', '16', '16', array('border' => '0')) . '</a>';
+					}
+					?>
+			</td>
 			<td>
 				<input type="submit" name="submit" value="<?php echo _('Save Changes') ?>" />
 			</td>
diff --git a/src/common/tracker/actions/downloadcsv.php b/src/common/tracker/actions/downloadcsv.php
index 95a48e0..280d92c 100644
--- a/src/common/tracker/actions/downloadcsv.php
+++ b/src/common/tracker/actions/downloadcsv.php
@@ -66,7 +66,10 @@ if ($headers) {
 		'close_date'.$sep.
 		'last_modified_date'.$sep.
 		'summary'.$sep.
-		'details';
+		'details'.$sep.
+		'_votes'.$sep.
+		'_voters'.$sep.
+		'_votage';
 
 	//
 	//	Show the extra fields
@@ -85,6 +88,7 @@ for ($i=0; $i<count($at_arr); $i++) {
 	$update_date = $at_arr[$i]->getLastModifiedDate() ? date(_('Y-m-d H:i'),$at_arr[$i]->getLastModifiedDate()) : '';
 	$close_date  = $at_arr[$i]->getCloseDate()? date(_('Y-m-d H:i'),$at_arr[$i]->getCloseDate()): '';
 
+	$at_arr[$i]->getVotes();
 	echo $at_arr[$i]->getID().$sep.
 		$at_arr[$i]->getStatusID().$sep.
 		'"'.$at_arr[$i]->getStatusName().'"'.$sep.
@@ -97,7 +101,10 @@ for ($i=0; $i<count($at_arr); $i++) {
 		'"'.$close_date.'"'.$sep.
 		'"'.$update_date.'"'.$sep.
 		'"'.fix4csv($at_arr[$i]->getSummary()).'"'.$sep.
-		'"'.fix4csv($at_arr[$i]->getDetails()).'"';
+		'"'.fix4csv($at_arr[$i]->getDetails()).'"'.$sep.
+		$votes[0].$sep.
+		$votes[1].$sep.
+		$votes[2];
 
 	//
 	//	Show the extra fields
diff --git a/src/common/tracker/actions/mod-limited.php b/src/common/tracker/actions/mod-limited.php
index 1e169a5..a20b47b 100644
--- a/src/common/tracker/actions/mod-limited.php
+++ b/src/common/tracker/actions/mod-limited.php
@@ -4,7 +4,8 @@
  *
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
- * Copyright 2012, Franck Villaume - TrivialDev
+ * Copyright 2012-2014, Franck Villaume - TrivialDev
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -67,6 +68,22 @@ if (session_loggedin()) {
 				?>
 			</td>
 			<td><?php
+					$votes = $ah->getVotes();
+					echo '<span id="tracker-votes" title="'.html_get_tooltip_description('votes').'" >'.html_e('strong', array(), _('Votes') . _(': ')).sprintf('%1$d/%2$d (%3$d%%)', $votes[0], $votes[1], $votes[2]).'</span>';
+					if ($ath->canVote()) {
+						if ($ah->hasVote()) {
+							$key = 'pointer_down';
+							$txt = _('Retract Vote');
+						} else {
+							$key = 'pointer_up';
+							$txt = _('Cast Vote');
+						}
+						echo '<a id="tracker-vote" alt="'.$txt.'" title="'.html_get_tooltip_description('vote').'" href="'.getselfhref(array('func' => $key)) . '">' .
+							html_image('ic/' . $key . '.png', '16', '16', array('border' => '0')) . '</a>';
+					}
+					?>
+			</td>
+			<td><?php
 				if ($group->usesPM()) {
 					echo '
 				<a href="'.getStringFromServer('PHP_SELF').'?func=taskmgr&group_id='.$group_id.'&atid='.$atid.'&aid='.$aid.'">'.
diff --git a/src/common/tracker/actions/mod.php b/src/common/tracker/actions/mod.php
index a378480..8fc51c0 100644
--- a/src/common/tracker/actions/mod.php
+++ b/src/common/tracker/actions/mod.php
@@ -5,7 +5,8 @@
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright 2010 (c) Franck Villaume - Capgemini
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
- * Copyright 2012, Franck Villaume - TrivialDev
+ * Copyright 2012-2014, Franck Villaume - TrivialDev
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -33,6 +34,13 @@ global $group;
 global $aid;
 global $atid;
 
+function gettipspan($idpart, $content) {
+	$id = 'tracker-' . str_replace(' ', '_', $idpart);
+	return '<span id="' . $id . '" title="' .
+	html_get_tooltip_description($idpart) . '">' .
+	$content . '</span>';
+}
+
 html_use_coolfieldset();
 $ath->header(array ('title'=> $ah->getStringID().' '. $ah->getSummary(), 'atid'=>$ath->getID()));
 
@@ -65,6 +73,23 @@ if (session_loggedin()) {
 				?>
 			</td>
 			<td><?php
+					$votes = $ah->getVotes();
+					echo '<span id="tracker-votes" title="'.html_get_tooltip_description('votes').'" >'.html_e('strong', array(), _('Votes') . _(': ')).sprintf('%1$d/%2$d (%3$d%%)', $votes[0], $votes[1], $votes[2]).'</span>';
+
+					if ($ath->canVote()) {
+						if ($ah->hasVote()) {
+							$key = 'pointer_down';
+							$txt = _('Retract Vote');
+						} else {
+							$key = 'pointer_up';
+							$txt = _('Cast Vote');
+						}
+						echo '<a id="tracker-vote" alt="'.$txt.'" title="'.html_get_tooltip_description('vote').'" href="'.getselfhref(array('func' => $key)) . '">' .
+							html_image('ic/' . $key . '.png', '16', '16', array('border' => '0')) . '</a>';
+					}
+				?>
+			</td>
+			<td><?php
 				if ($group->usesPM()) {
 					echo '
 				<a href="'.getStringFromServer('PHP_SELF').'?func=taskmgr&group_id='.$group_id.'&atid='.$atid.'&aid='.$aid.'">'.
@@ -131,11 +156,14 @@ echo html_build_select_box ($res,'new_artifact_type_id',$ath->getID(),false);
 		<td>
 		</td>
 	</tr>
-
+	<tr>
+		<td>
 	<?php
 		$ath->renderExtraFields($ah->getExtraFieldData(),true,'none',false,'Any',array(),false,'UPDATE');
 	?>
-
+		</td>
+		<td></td>
+	</tr>
 	<tr>
 		<td><strong><?php echo _('Assigned to')._(': ') ?></strong><br />
 		<?php
diff --git a/src/common/tracker/actions/tracker.php b/src/common/tracker/actions/tracker.php
index 80d03e9..e87d2f3 100644
--- a/src/common/tracker/actions/tracker.php
+++ b/src/common/tracker/actions/tracker.php
@@ -5,6 +5,7 @@
  * Copyright 1999-2001 (c) VA Linux Systems
  * Copyright 2002-2004 (c) GForge Team
  * Copyright 2012-2014, Franck Villaume - TrivialDev
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  * http://fusionforge.org/
  *
  * This file is part of FusionForge. FusionForge is free software;
@@ -560,6 +561,45 @@ switch (getStringFromRequest('func')) {
 			}
 			break;
 		}
+		//
+		//     Tracker Item Voting
+		//
+		case 'pointer_down': {
+			$artifact_id = $aid = getIntFromRequest('aid');
+			if ($aid) {
+				$ah = new ArtifactHtml($ath, $aid);
+				if (!$ah || !is_object($ah)) {
+					exit_error(_('Artifact Could Not Be Created'), 'tracker');
+				} else if ($ah->isError()) {
+					exit_error($ah->getErrorMessage(), 'tracker');
+				}
+				if ($ah->castVote(false)) {
+					$feedback = _('Retracted Vote successfully');
+				} else {
+					$error_msg = $ah->getErrorMessage();
+				}
+			}
+			include $gfcommon.'tracker/actions/browse.php';
+			break;
+		}
+		case 'pointer_up': {
+			$artifact_id = $aid = getIntFromRequest('aid');
+			if ($aid) {
+				$ah = new ArtifactHtml($ath, $aid);
+				if (!$ah || !is_object($ah)) {
+					exit_error(_('Artifact Could Not Be Created'), 'tracker');
+				} else if ($ah->isError()) {
+					exit_error($ah->getErrorMessage(), 'tracker');
+				}
+				if ($ah->castVote()) {
+					$feedback = _('Cast Vote successfully');
+				} else {
+					$error_msg = $ah->getErrorMessage();
+				}
+			}
+			include $gfcommon.'tracker/actions/browse.php';
+			break;
+		}
 		default : {
 			include $gfcommon.'tracker/actions/browse.php';
 			break;
diff --git a/src/common/tracker/views/form-customizelist.php b/src/common/tracker/views/form-customizelist.php
index 0797cd7..3bdc8f1 100644
--- a/src/common/tracker/views/form-customizelist.php
+++ b/src/common/tracker/views/form-customizelist.php
@@ -4,6 +4,7 @@
  *
  * Copyright 2010, FusionForge Team
  * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
  * This file is part of FusionForge. FusionForge is free software;
  * you can redistribute it and/or modify it under the terms of the
@@ -43,7 +44,10 @@ $fields = array (
 	'close_date' => _('Close Date'),
 	'details' => _('Detailed description'),
 	'related_tasks' => _('Related Tasks'),
-	'last_modified_date' => _('Last Modified Date')
+	'last_modified_date' => _('Last Modified Date'),
+	'_votes' => _('# Votes'),
+	'_voters' => _('# Voters'),
+	'_votage' => _('% Votes')
 );
 
 if(count($ath->getExtraFields(array(ARTIFACT_EXTRAFIELDTYPE_STATUS))) > 0) {
diff --git a/src/www/include/html.php b/src/www/include/html.php
index 00dabdf..5c6ef5e 100644
--- a/src/www/include/html.php
+++ b/src/www/include/html.php
@@ -6,7 +6,7 @@
  * Copyright 2010 (c) FusionForge Team
  * Copyright (C) 2010-2012 Alain Peyrat - Alcatel-Lucent
  * Copyright 2011, Franck Villaume - Capgemini
- * Copyright 2011-2013, Franck Villaume - TrivialDev
+ * Copyright 2011-2014, Franck Villaume - TrivialDev
  * Copyright © 2011, 2012
  *	Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
  *
@@ -423,6 +423,10 @@ function html_get_tooltip_description($element_name) {
 			return _('You can monitor or un-monitor this item by clicking the “Monitor” button.')
 				.' <br /><br />'
 				._('<strong>Note!</strong> this will send you additional email. If you add comments to this item, or submitted, or are assigned this item, you will also get emails for those reasons as well!');
+		case 'vote':
+			return _('You can cast your vote for a Tracker Item to aid Project Management to decide which features to prioritise, and retract votes at any time. Please use this functionality sparingly, as it loses its meaning if you vote on *every* item.');
+		case 'votes':
+			return _('This metric displays the number of people who can *currently* vote for features in this tracker, and how many of them did so. (This means historic votes of people no longer allowed to vote, while not lost, do not play into the numbers displayed.)');
 		default:
 			return '';
 	}
diff --git a/src/www/js/jquery-common.js b/src/www/js/jquery-common.js
index 042ab64..5f69c42 100644
--- a/src/www/js/jquery-common.js
+++ b/src/www/js/jquery-common.js
@@ -3,6 +3,8 @@
  *
  * Copyright 2010, Alain Peyrat
  * Copyright 2011, Franck Villaume - Capgemini
+ * Copyright 2012, Thorsten “mirabilos” Glaser <t.glaser at tarent.de>
+ * Copyright 2014, Franck Villaume - TrivialDev
  * http://fusionforge.org
  *
  * This file is part of FusionForge.
@@ -34,7 +36,8 @@ jQuery(function() {
 		jQuery('#tracker-comment').tipsy({gravity: 'w', delayIn: 1000, delayOut: 500, fade: true});
 		jQuery('#tracker-new_artifact_type_id').tipsy({gravity: 'w', html:true, delayIn: 1000, delayOut: 500, fade: true});
 		jQuery('#tracker-manage-roles').tipsy({gravity: 'w', delayIn: 1000, delayOut: 500, fade: true});
-
+		jQuery('#tracker-vote').tipsy({gravity: 'w', delayIn: 1000, delayOut: 500, fade: true});
+		jQuery('#tracker-votes').tipsy({gravity: 'n', delayIn: 1000, delayOut: 500, fade: true});
 		jQuery('.forum_monitor').tipsy({gravity: 'n', html:true, delayIn: 1000, delayOut: 500, fade: true});
 		jQuery('.forum_save_place').tipsy({gravity: 'n', html:true, delayIn: 1000, delayOut: 500, fade: true});
 		jQuery('.forum_start_thread').tipsy({gravity: 'n', html:true, delayIn: 1000, delayOut: 500, fade: true});
diff --git a/src/www/themes/funky-wOw/images/ic/pointer_down.png b/src/www/themes/funky-wOw/images/ic/pointer_down.png
new file mode 100644
index 0000000..78ac9e7
Binary files /dev/null and b/src/www/themes/funky-wOw/images/ic/pointer_down.png differ
diff --git a/src/www/themes/funky-wOw/images/ic/pointer_up.png b/src/www/themes/funky-wOw/images/ic/pointer_up.png
new file mode 100644
index 0000000..91392e8
Binary files /dev/null and b/src/www/themes/funky-wOw/images/ic/pointer_up.png differ
diff --git a/src/www/themes/funky/images/ic/pointer_down.png b/src/www/themes/funky/images/ic/pointer_down.png
new file mode 100644
index 0000000..78ac9e7
Binary files /dev/null and b/src/www/themes/funky/images/ic/pointer_down.png differ
diff --git a/src/www/themes/funky/images/ic/pointer_up.png b/src/www/themes/funky/images/ic/pointer_up.png
new file mode 100644
index 0000000..91392e8
Binary files /dev/null and b/src/www/themes/funky/images/ic/pointer_up.png differ

-----------------------------------------------------------------------

Summary of changes:
 src/common/include/RBAC.php                        |   27 +++--
 src/common/include/RBACEngine.class.php            |    8 +-
 src/common/include/rbac_texts.php                  |   17 +++
 src/common/include/utils.php                       |   12 +++
 src/common/tracker/Artifact.class.php              |  114 ++++++++++++++++++++
 src/common/tracker/ArtifactFactory.class.php       |   15 ++-
 src/common/tracker/ArtifactType.class.php          |   40 +++++++
 src/common/tracker/actions/browse.php              |   24 ++++-
 src/common/tracker/actions/detail.php              |   19 +++-
 src/common/tracker/actions/downloadcsv.php         |   11 +-
 src/common/tracker/actions/mod-limited.php         |   19 +++-
 src/common/tracker/actions/mod.php                 |   34 +++++-
 src/common/tracker/actions/tracker.php             |   40 +++++++
 src/common/tracker/views/form-customizelist.php    |    6 +-
 src/db/20140128-tracker-vote-table.sql             |   12 +++
 src/www/include/html.php                           |    6 +-
 src/www/js/jquery-common.js                        |    5 +-
 .../funky-wOw/images/ic}/pointer_down.png          |  Bin 188 -> 188 bytes
 src/www/themes/funky-wOw/images/ic/pointer_up.png  |  Bin 0 -> 176 bytes
 .../funky/images/ic}/pointer_down.png              |  Bin 188 -> 188 bytes
 src/www/themes/funky/images/ic/pointer_up.png      |  Bin 0 -> 176 bytes
 21 files changed, 385 insertions(+), 24 deletions(-)
 create mode 100644 src/db/20140128-tracker-vote-table.sql
 copy src/www/{images => themes/funky-wOw/images/ic}/pointer_down.png (100%)
 create mode 100644 src/www/themes/funky-wOw/images/ic/pointer_up.png
 copy src/www/{images => themes/funky/images/ic}/pointer_down.png (100%)
 create mode 100644 src/www/themes/funky/images/ic/pointer_up.png


hooks/post-receive
-- 
FusionForge



More information about the Fusionforge-commits mailing list