? modules/project/voting
Index: modules/project/project.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/project.inc,v
retrieving revision 1.68
diff -u -r1.68 project.inc
--- modules/project/project.inc	27 Jan 2006 05:51:11 -0000	1.68
+++ modules/project/project.inc	21 Feb 2006 20:47:26 -0000
@@ -160,6 +160,25 @@
     '#rows' => 5,
   );
 
+  if (module_exist('votingapi')) {
+    /* Voting properties */
+    $form['voting'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Voting information'),
+    );
+    $form['voting']['vote'] = array(
+      '#type' => 'item',
+      '#title' => t('Project voting'),
+    );
+    $form['voting']['voting'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enable community voting'),
+      '#return_value' => 1,
+      '#default_value' => $node->voting,
+      '#description' => t('Let users rate this project. If the issue tracker is enabled, multiple criteria can be used to rate the project'),
+    );
+  }
+
   /* E-mail options */
   $form['email'] = array(
     '#type' => 'fieldset',
@@ -354,6 +373,15 @@
       $output .= theme('item_list', $links, t('Releases'));
     }
 
+    if ($node->voting && module_exist('votingapi')) {
+      // this is where voting related stuff should go. We want to draw the voting widget, and the voting results separately.
+      $voutput .= theme('project_voting_widget', $node);
+      $voutput .= theme('project_voting_results', $node);
+      if ($voutput) {
+        $output .= theme('box', t('Project rating'), $voutput);
+      }
+    }
+
     // Misc section
     $links = array();
 
@@ -530,4 +558,175 @@
   }
 }
 
+function theme_project_voting_widget($node) {
+  return project_vote_widget($node);
+}
+
+function project_vote_widget($node) {
+  global $user;
+  $uid = $user->uid;
+
+  if (!user_access('vote on projects') || $node->uid == $uid) {
+    return;
+  }
+
+  $form = array();
+  $form['#tree'] = TRUE;
+  
+  $form['content_type'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->type,
+  );
+
+  $form['content_id'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->nid,
+  );
+
+  $tmp = votingapi_get_user_votes($node->type, $node->nid, $user->uid);
+  foreach($tmp as $vote) {
+    $existing_votes[$vote->tag] = $vote->value;
+  }
+
+  if (is_array($node->components)) {
+    $form['calculate_average'] = array(
+      '#type' => 'hidden',
+      '#value' => TRUE,
+    );
+    foreach ($node->components as $c) {
+      $criterion[$c] = $c;
+    }
+  }
+  else {
+    $form['calculate_average'] = array(
+      '#type' => 'hidden',
+      '#value' => FALSE,
+    );
+    $criterion = array(VOTINGAPI_DEFAULT_VALUE_TAG => t('Project rating'));
+  }
+  foreach($criterion as $value=>$name) {
+    $form['criterion'][$value] = array(
+      '#type' => 'select',
+      '#title' => $name,
+      '#default_value' => $existing_votes[$value],
+      '#options' => array(0=>"", 20=>"*", 40=>"* *", 60=>"* * *", 80=>"* * * *", 100=>"* * * * *"),
+    );
+  }
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+  );
+
+  $output = drupal_get_form('project_rating_form', $form);
+  return $output;
+}
+
+function theme_project_rating_form($form) {
+  foreach (element_children($form['criterion']) as $tag) {
+    $row = array();
+    $row[] = '<strong>'.$form['criterion'][$tag]['#title'].'</strong>';
+    unset($form['criterion'][$tag]['#title']);
+    $row[] = form_render($form['criterion'][$tag]);
+    $rows[] = $row;
+  }
+  $row = array();
+  $row[] = form_render($form['submit']);
+  $row[] = '';
+  $rows[] = $row;
+
+  $output = theme('table', NULL, $rows, array('class' => 'project_voting_widget'));
+  $output .= form_render($form);
+  return $output;
+}
+
+function project_rating_form_submit($form_id, $form_values) {
+  foreach (element_children($form_values['criterion']) as $tag) {
+    $value = $form_values['criterion'][$tag];
+    if ($value > 100) {
+      $value = 100;
+    }
+    if ($value < 0) {
+      $value = 0;
+    }
+    $total += $value;
+    $count++;
+
+    $vote_object->tag = $tag;
+    $vote_object->value_type = VOTINGAPI_VALUE_TYPE_PERCENT;
+    $vote_object->value = $form_values['criterion'][$tag];
+    $vote_objects[] = $vote_object;
+    unset($vote_object);
+  }
+  
+  // If necessary, calculate an ovreall vote value for all criteria
+  if ($form_values['calculate_average']) {
+    $vote_object->tag = VOTINGAPI_VALUE_DEFAULT_TAG;
+    $vote_object->value_type = VOTINGAPI_VALUE_TYPE_PERCENT;
+    $vote_object->value = $total / $count;
+    $vote_objects[] = $vote_object;
+  }
+  votingapi_set_vote($form_values['content_type'], $form_values['content_id'], $vote_objects);
+}
+
+function theme_project_voting_results($node) {
+  $votes = votingapi_get_voting_results($node->type, $node->nid);
+
+  $rating = array();
+  $overall = t('No votes yet');
+
+  foreach ($votes as $vobj) {
+    if ($vobj->function == 'average') {
+      if ($vobj->tag == VOTINGAPI_VALUE_DEFAULT_TAG) {
+        $overall = theme('project_project_rating_value', $vobj->value);
+      }
+      else {
+        $rating[$vobj->tag] = theme('project_project_rating_value', $vobj->value);
+      }
+    }
+
+    else if ($vobj->function == 'count' && $vobj->tag == VOTINGAPI_DEFAULT_VALUE_TAG) {
+      $num_votes = $vobj->value;
+    }
+  }
+
+  $row = array();
+  $row[] = '<strong>'.t('Project rating').'</strong>';
+  $row[] = $overall;
+  $rows[] = $row;
+
+  foreach ($rating as $criteria=>$vote) {
+    $row = array();
+    $row[] = $criteria;
+    $row[] = $vote;
+    $rows[] = $row;
+  }
+  
+  $output = theme('table', NULL, $rows, array('class' => 'project_voting_results'));
+  return $output;
+
+}
+
+function theme_project_project_rating_value($pct) {
+  $score = round($pct / 20, 1);
+  $stars = round($score);
+  
+  $path = '/' . drupal_get_path('module', 'project') . '/voting/';
+  for ($i = 1; $i < 6; $i++) {
+    if ($i <= $score) {
+      $output .= "<img src='" . $path . "star_on.png' />";
+    }
+    else {
+      if ($i <= $stars) {
+        $output .= "<img src='" . $path . "star_half.png' />";
+      }
+      else {
+        $output .= "<img src='" . $path . "star_off.png' />";
+      }
+    }
+  }
+  $output .= " ($score)";
+  
+  return $output;
+}
 ?>
Index: modules/project/project.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/project.module,v
retrieving revision 1.230
diff -u -r1.230 project.module
--- modules/project/project.module	6 Feb 2006 18:17:57 -0000	1.230
+++ modules/project/project.module	21 Feb 2006 20:33:46 -0000
@@ -112,7 +112,8 @@
     'access own projects',
     'create project issues',
     'access project issues',
-    'access own project issues'
+    'access own project issues',
+    'vote on projects'
   );
   $states = project_issue_state();
   foreach($states as $key => $value) {
@@ -985,4 +986,5 @@
   }
   return $output;
 }
-?>
+
+?>
\ No newline at end of file
Index: modules/project/project.mysql
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/project.mysql,v
retrieving revision 1.23
diff -u -r1.23 project.mysql
--- modules/project/project.mysql	31 Jan 2006 00:48:09 -0000	1.23
+++ modules/project/project.mysql	21 Feb 2006 20:33:47 -0000
@@ -13,6 +13,7 @@
   demo varchar(255) NOT NULL default '',
   release_directory varchar(255) NOT NULL default '',
   issues tinyint(4) NOT NULL default '0',
+  voting tinyint(4) NOT NULL default '0',
   components text,
   version int(10) unsigned NOT NULL default '0',
   mail varchar(255) not null default '',
Index: modules/project/project.update
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/project.update,v
retrieving revision 1.1
diff -u -r1.1 project.update
--- modules/project/project.update	27 Jan 2006 17:45:12 -0000	1.1
+++ modules/project/project.update	21 Feb 2006 20:33:47 -0000
@@ -2,4 +2,15 @@
 function project_update_1() {
   return _system_update_utf8(array('project_projects', 'project_releases', 'project_issues', 'project_comments', 'project_subscriptions', 'project_issue_state'));
 }
-?> 
\ No newline at end of file
+
+function project_update_2() {
+  switch ($GLOBALS['db_type']) {
+  case 'mysql':
+  case 'mysqli':
+    $ret[] = update_sql("ALTER TABLE {project_projects} ADD voting tinyint(4) NOT NULL default '1' AFTER issues");
+    break;
+  }
+
+  return $ret;
+}
+?>
\ No newline at end of file
