diff -urp nodereview/nodereview.admin.inc nodereview_new/nodereview.admin.inc
--- nodereview/nodereview.admin.inc	2009-05-16 20:19:34.000000000 +0300
+++ nodereview_new/nodereview.admin.inc	2010-02-02 09:14:10.000000000 +0300
@@ -16,24 +16,30 @@
  *
  */
 
-function nodereview_configure_axes(&$form_state, $type, $name) {
-
-  drupal_set_title(t('Reviews for %type nodes', array('%type' => check_plain($name))));
-
+function nodereview_type_configure_axes(&$form_state, $nrtid ) {
+//drupal_set_message('gevefr');
+  $nr_type_name = db_result(db_query("SELECT name FROM {nodereview_type} WHERE nrtid = %d", $nrtid));
+  drupal_set_title(t('Review for %nr_type_name', array('%nr_type_name' => check_plain($nr_type_name))));
+  
   $form['use'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('reviews'),
-      '#collapsible' => TRUE,
-      '#collapsed' => FALSE,
+    '#type' => 'fieldset',
+    '#title' => t('review'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
   );
 
-  $form['use']['node_type'] = array('#type' => 'hidden', '#value' => $type);
+  $form['use']['nrtid'] = array(
+    '#type' => 'hidden',
+    '#value' => $nrtid
+  );
+
+  $guide = db_result(db_query("SELECT guide FROM {nodereview_type} WHERE nrtid = %d", $nrtid));
   $form['use']['guide'] = array(
     '#type' => 'textarea',
-    '#title' => t('Usage Guide to the User'),
+    '#title' => t('Usage Guide'),
     '#return_value' => 1,
-    '#default_value' => variable_get('nodereview_guide_'. $type, ''),
-    '#description' => t('Instructions to users for how to use this review.  These will be shown on the "Add Review" page. Note that if you have help text defined on admin/settings/content-types/nodereview, this value will override it.'),
+    '#default_value' => $guide,
+    '#description' => t('Instructions to users on how to use this review.'),
   );
 
   $form['axes'] = array(
@@ -45,47 +51,58 @@ function nodereview_configure_axes(&$for
   );
 
   // We'll store field information in its own table
-  $result = db_query("SELECT aid, tag, description, weight FROM {nodereview_axes} WHERE node_type='%s' ORDER BY weight", $type);
+  $result = db_query("SELECT aid, tag, hide_description, description, tid, multiplier, weight FROM {nodereview_axes} WHERE nrtid=%d ORDER BY weight", $nrtid);
 
   $axes = array();
 
   while ($record = db_fetch_object($result)) {
-    $axes[] = _nodereview_configure_axis($record);
+    $axes[] = _nodereview_type_configure_axis($record);
   }
 
   $record = new stdClass();
   $record->aid = 0;
-  $record->node_type = $type;
+  $record->nrtid = $nrtid;
+  $record->hide_description = variable_get('nodereview_hide_descr', 0);
 
-  $axes[] = _nodereview_configure_axis($record);
+  $axes[] = _nodereview_type_configure_axis($record);
 
   $form['axes'] += $axes;
 
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
-
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save')
+  );
+  $form['list'] = array(
+    '#type' => 'markup',
+    '#prefix' => '',
+    '#value' => t("<a href='". base_path() . "admin/settings/nodereview/nodereview_type/list'>List types"),
+    '#suffix' => '',
+  );
+  
   return $form;
 
 }
 
 
 /**
- * Handle submission of the nodereview node type axes
- * form and saving of the data to the database.
+ * Handle submission of the nodereview type node type
+ * axes form and saving of the data to the database.
  *
  */
+function nodereview_type_configure_axes_submit($form, $form_state) {
 
-function nodereview_configure_axes_submit($form, $form_state) {
   $form_values = $form_state['values'];
   // Save whether or not we're reviewing this node type
   // variable_set('nodereview_use_' . $form_values['node_type'], $form_values['use']);
-  variable_set('nodereview_guide_'. $form_values['node_type'], $form_values['guide']);
+  //variable_set('nodereview_guide_'. $form_values['node_type'], $form_values['guide']);
+  db_query("UPDATE {nodereview_type} SET guide='%s' WHERE nrtid=%d", $form_values['guide'], $form_values['nrtid']);
 
   // Regardless, save the user's data, just in case they may want it later
   foreach ($form_values['axes'] as $axis) {
     if ($axis['aid'] && $axis['use']) {
       // Update an existing axis
       $axis['description'] = check_plain($axis['description']);
-      db_query("UPDATE {nodereview_axes} SET tag='%s', description='%s', weight=%d WHERE aid=%d", $axis['tag'], $axis['description'], $axis['weight'], $axis['aid']);
+      db_query("UPDATE {nodereview_axes} SET tag='%s', nrtid=%d, hide_description=%d, description='%s', tid=%d, multiplier=%f, weight=%d WHERE aid=%d", $axis['tag'], $form_values['nrtid'] ,$axis['hide_description'], $axis['description'], $axis['tid'], $axis['multiplier'], $axis['weight'], $axis['aid']);
     }
     elseif ($axis['aid'] && ! $axis['use']) {
       // Delete an existing axis
@@ -94,12 +111,13 @@ function nodereview_configure_axes_submi
     elseif ($axis['use'] && ! $axis['aid']) {
       // Create a new axis
       $axis['description'] = check_plain($axis['description']);
-      db_query("INSERT INTO {nodereview_axes} (node_type, tag, description, weight) VALUES ('%s', '%s', '%s', %d)", $form_values['node_type'], $axis['tag'], $axis['description'], $axis['weight']);
+      db_query("INSERT INTO {nodereview_axes} (tag, nrtid, hide_description, description, tid, multiplier, weight) VALUES ('%s', %d, %d, '%s', %d, %f, %d)", $axis['tag'], $form_values['nrtid'], $axis['hide_description'], $axis['description'], $axis['tid'], $axis['multiplier'], $axis['weight']);
     }
     else {
       // Doesn't exist and don't use, so just ignore
     }
   }
+
 }
 
 
@@ -109,7 +127,7 @@ function nodereview_configure_axes_submi
  * @ingroup forms
  *
  */
-function _nodereview_configure_axis($record) {
+function _nodereview_type_configure_axis($record) {
   $form['aid'] = array(
     '#type' => 'hidden',
     '#value' => $record->aid,
@@ -126,7 +144,15 @@ function _nodereview_configure_axis($rec
     '#title' => t('name'),
     '#return_value' => 1,
     '#default_value' => $record->tag,
-    '#size' => 30,
+    '#size' => 20,
+  );
+
+  $form['hide_description'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Hide description'),
+    '#return_value' => 1,
+    '#default_value' => (boolean)($record->hide_description),
+    '#description' => t(''),
   );
   $form['description'] = array(
     '#type' => 'textarea',
@@ -135,19 +161,86 @@ function _nodereview_configure_axis($rec
     '#default_value' => $record->description,
     '#rows' => 2,
   );
+  $vid = variable_get('nodereview_vocabulary', 0);
+  $sql = "SELECT tid, name FROM {term_data} WHERE vid = %d ORDER BY weight";
+  $terms = db_query($sql, $vid);
+  $options = array();
+  while ($term = db_fetch_object($terms)) {
+    $options[$term->tid] = $term->name;
+  }
+  $form['tid'] = array(
+    '#title' => t('Term'),
+    '#type' => 'select',
+    '#description' => t(''),
+    '#default_value' => array($record->tid),
+    '#options' => $options,
+    '#multiple' => FALSE,
+  );
+  $form['multiplier'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Multiplier'),
+    '#description' => t(''),
+    '#default_value' => $record->multiplier,
+    '#size' => 10,
+  );
   $form['weight'] = array(
     '#type' => 'weight',
     '#title' => t('weight'),
-    '#delta' => 10,
+    '#delta' => 100,
     '#default_value' => $record->weight,
     '#description' => t(''),
   );
-
+  
   return $form;
 }
 
 
 /**
+ * Implementation of hook_settings().
+ */
+function nodereview_settings() {
+
+  $form = array();
+
+  $form['nodereview_textual_grade'] = array(
+    '#title' => t('Hide textual grade field.'),
+    '#type' => 'checkbox',
+    '#description' => t('Hide textual grade field for node review axes by default.'),
+    '#default_value' => variable_get('nodereview_textual_grade', 0),
+  );
+  $form['nodereview_hide_descr'] = array(
+    '#title' => t('Hide axis description field by default.'),
+    '#type' => 'checkbox',
+    '#description' => t('Hide axis description field by default.'),
+    '#default_value' => variable_get('nodereview_hide_descr', 0),
+  );
+  $form['nodereview_userreviews'] = array(
+    '#title' => t('Allow multiple reviews.'),
+    '#type' => 'checkbox',
+    '#description' => t('Are users allowed to review a node multiple times using different nodereview types.'),
+    '#default_value' => variable_get('nodereview_userreviews', 0),
+  );
+  
+  $vocabulary_options = array();
+  $vocabularies = taxonomy_get_vocabularies();
+  foreach ($vocabularies as $vocabulary) {
+  	$vocabulary_options[$vocabulary->vid] = $vocabulary->name;
+  }
+  $form['nodereview_vocabulary'] = array(
+    '#title' => t('Vocabulary.'),
+    '#type' => 'select',
+    '#description' => t('Vocabulary to use for grouping results for calculations.'),
+    '#default_value' => variable_get('nodereview_vocabulary', NULL),
+    '#options' => $vocabulary_options,
+    '#multiple' => FALSE,
+  );
+
+  return system_settings_form($form);
+
+}
+
+
+/**
  * We use this function in place of hook_settings(), because hook_settings()
  * isn't fancy enough to support what we need to do.
  *
@@ -209,17 +302,301 @@ function nodereview_configure() {
 
 
 function nodereview_configure_submit($form, $form_state) {
+
   $form_values = $form_state['values'];
   foreach ($form_values['types'] as $type => $checked) {
     variable_set('nodereview_use_'. $type, (bool)$checked);
   }
+
   if($form_values['fivestar']) {
     foreach ($form_values['fivestar'] as $option => $value) {
       variable_set('nodereview_fivestar_'. $option, $value);
     }
   }
+
   cache_clear_all();
   menu_rebuild();
 
 }
 
+
+function nodereview_type_list() {
+
+  $types = db_query('SELECT * FROM {nodereview_type}');
+  $header = array(t('Name'), t('Description'), array('data' => t('Operations'), 'colspan' => '3'));
+  $rows = array();
+
+  while ($type = db_fetch_object($types)) {
+    $row = array(
+      l($type->name, 'admin/settings/nodereview/nodereview_type/'. $type->nrtid .'/edit'),
+      filter_xss_admin($type->description),
+    );
+    // Set the edit column.
+    $row[] = array('data' => l(t('edit'), 'admin/settings/nodereview/nodereview_type/'. $type->nrtid .'/edit'));
+
+   // Set the reviewcolumn.
+    $row[] = array('data' => l(t('review'), 'admin/settings/nodereview/nodereview_type/'. $type->nrtid .'/review'));
+    
+    // Set the delete column.
+    $row[] = array('data' => l(t('delete'), 'admin/settings/nodereview/nodereview_type/'. $type->nrtid .'/delete'));
+
+    $rows[] = $row;
+  }
+
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No content types available.'), 'colspan' => '4', 'class' => 'message'));
+  }
+
+  return theme('table', $header, $rows);
+
+}
+
+
+function nodereview_type_add() {
+
+  $form = array();
+
+  $form['name'] = array(
+    '#type' => 'textfield',
+    '#length' => 255,
+    '#title' => t('Name'),
+    '#default_value' => '',
+    '#description' => t('The name of the new nodereview type.'),
+  );
+
+  $form['description'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Description'),
+    '#default_value' => '',
+    '#description' => t('A short description of the (use of) the new nodereview type.'),
+  );
+
+  $options = array();
+  foreach (node_get_types() as $type => $info) {
+    $options[$type] = $info->name;
+  }
+  
+  $form['node_types'] = array(
+    '#title' => t('Reviewable node types'),
+    '#type' => 'select',
+    '#description' => t('The node types that the nodereview type applies to.'),
+    //'#default_value' => $default,
+    '#options' => $options,
+    '#multiple' => TRUE,
+  );
+
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+
+  return $form;
+
+}
+
+
+function nodereview_type_add_submit($form, $form_state) {
+
+  $form_values = $form_state['values'];
+
+  db_query("INSERT INTO {nodereview_type} (name, description) VALUES ('%s', '%s')", $form_values['name'], $form_values['description']);
+  $nrtid = db_last_insert_id('nodereview_type', 'nrtid');
+
+  $node_types = $form_values['node_types'];
+  foreach ($node_types as $key => $value) {
+    db_query("INSERT INTO {nodereview_type_nodetype} (nrtid, node_type) VALUES (%d, '%s')", $nrtid, $value);
+  }
+
+}
+
+
+/**
+ * Import nodereview types from cut & paste
+ */
+function nodereview_type_import() {
+  $form['nodereview_types'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Paste nodereview types code here'),
+    '#description' => t('Paste code from inside the _nodereview_types_defaults function in the defaults.inc file generated by the features module. Copy the $nodereview_types definition.'),
+    '#required' => TRUE,
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Import'),
+    '#submit' => array('nodereview_type_import_submit'),
+    '#validate' => array('nodereview_type_import_validate'),
+  );
+  return $form;
+}
+
+
+/**
+ * Validate handler to import nodereview types
+ */
+function nodereview_type_import_validate($form, &$form_state) {
+  $nodereview_types = '';
+  //views_include('view');
+  ob_start();
+  eval($form_state['values']['nodereview_types']);
+  ob_end_clean();
+  if (!is_array($nodereview_types)) {
+    return form_error($form['nodereview_types'], t('Unable to interpret nodereview types code.'));
+  }
+  $form_state['nodereview_types'] = &$nodereview_types;
+}
+
+
+/**
+ * Submit handler for nodereview types import
+ */
+function nodereview_type_import_submit($form, &$form_state) {
+  $nodereview_types = $form_state['nodereview_types'];
+  while ($nodereview_type = each($nodereview_types)) {
+    $result = db_fetch_array(db_query("SELECT nrtid, name FROM {nodereview_type} WHERE name = '%s'", $nodereview_type['value']['name']));
+    if ($result) {
+      $nrtid = $result['nrtid'];
+      db_query("UPDATE {nodereview_type} SET description = '%s', guide = '%s' WHERE nrtid = %d", $nodereview_type['value']['description'], $nodereview_type['value']['guide'], $nrtid);
+      $nodetypes = $nodereview_type['value']['nodetypes'];
+      while ($nodetype = each($nodetypes)) {
+        $result = db_fetch_array(db_query("SELECT * FROM {nodereview_type_nodetype} WHERE nrtid = %d AND node_type = '%s'", $nrtid, $nodetype['value']['node_type']));
+        if (! $result) {
+          db_query("INSERT INTO {nodereview_type_nodetype} (nrtid, node_type) VALUES (%d, '%s')", $nrtid, $nodetype['value']['node_type']);
+        }
+      }
+      $axes = $nodereview_type['value']['axes'];
+      while ($axe = each($axes)) {
+        $result = db_fetch_array(db_query("SELECT aid FROM {nodereview_axes} WHERE tag = '%s' AND nrtid = %d", $axe['value']['tag'], $nrtid));
+        if (! $result) {
+          db_query("INSERT INTO {nodereview_axes} (tag, weight, description, nrtid, tid, hide_description, multiplier) VALUES ('%s', %d, '%s', %d, %d, %d, %f)", $axe['value']['tag'], $axe['value']['weight'], $axe['value']['description'], $nrtid, $map['tids'][$axe['value']['tid']], $axe['value']['hide_description'], $axe['value']['multiplier']);
+        }
+        else {
+          db_query("UPDATE {nodereview_axes} SET weight = %d, description = '%s', tid = %d, hide_description = %d, multiplier = %f WHERE aid = %d", $axe['value']['weight'], $axe['value']['description'], $map['tids'][$axe['value']['tid']], $axe['value']['hide_description'], $axe['value']['multiplier'], $result['aid']);
+        }
+      }
+      drupal_set_message(t("Nodereview type '". $nodereview_type['value']['name'] ."' already existed; your import has been merged with it."), 'warning');
+    }
+    else {
+      db_query("INSERT INTO {nodereview_type} (name, description, guide) VALUES ('%s', '%s', '%s')", $nodereview_type['value']['name'], $nodereview_type['value']['description'], $nodereview_type['value']['guide']);
+      $nrtid = db_last_insert_id('nodereview_type', 'nrtid');
+      $nodetypes = $nodereview_type['value']['nodetypes'];
+      while ($nodetype = each($nodetypes)) {
+        db_query("INSERT INTO {nodereview_type_nodetype} (nrtid, node_type) VALUES (%d, '%s')", $nrtid, $nodetype['value']['node_type']);
+      }
+      $axes = $nodereview_type['value']['axes'];
+      while ($axe = each($axes)) {
+        db_query("INSERT INTO {nodereview_axes} (tag, weight, description, nrtid, tid, hide_description, multiplier) VALUES ('%s', %d, '%s', %d, %d, %d, %f)", $axe['value']['tag'], $axe['value']['weight'], $axe['value']['description'], $nrtid, $map['tids'][$axe['value']['tid']], $axe['value']['hide_description'], $axe['value']['multiplier']);
+      }
+    }
+  }
+  drupal_set_message(t("Nodereview types have been imported successfully"));
+}
+
+
+function nodereview_type_edit($dummy, $nrtid) {
+	
+  $nodereview_type = db_fetch_object(db_query('SELECT * FROM {nodereview_type} WHERE nrtid = %d', $nrtid));
+  
+  $form = array();
+
+  $form['nrtid'] = array(
+    '#type' => 'value',
+    '#value' => $nrtid,
+  );
+
+  $form['name'] = array(
+    '#type' => 'textfield',
+    '#length' => 255,
+    '#title' => t('Name'),
+    '#default_value' => $nodereview_type->name,
+    '#description' => t('The name of the nodereview type.'),
+  );
+
+  $form['description'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Description'),
+    '#default_value' => $nodereview_type->description,
+    '#description' => t('A short description of the (use of) the nodereview type.'),
+  );
+
+  $options = array();
+  $default = array();
+  foreach(node_get_types() as $type => $info) {
+  	$options[$type] = $info->name;
+    $node_type = db_result(db_query("SELECT node_type FROM {nodereview_type_nodetype} WHERE nrtid = %d AND node_type = '%s'", $nrtid, $type));
+    if ($node_type == $type) {
+      $default[] = $type;
+    }
+  }
+  
+  $form['node_types'] = array(
+    '#title' => t('Reviewable node types'),
+    '#type' => 'select',
+    '#description' => t('The node types that the nodereview type applies to.'),
+    '#default_value' => $default,
+    '#options' => $options,
+    '#multiple' => TRUE,
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+  );
+
+  return $form;
+
+}
+
+
+function nodereview_type_edit_submit($form, $form_state) {
+
+  $form_values = $form_state['values'];
+  $nrtid = $form_values['nrtid'];
+
+  db_query("UPDATE {nodereview_type} SET name = '%s', description = '%s' WHERE nrtid = %d", $form_values['name'], $form_values['description'], $nrtid);
+  
+  $sql = "DELETE FROM {nodereview_type_nodetype} WHERE nrtid = %d";
+  db_query($sql, $nrtid);
+
+  $node_types = $form_values['node_types'];
+  foreach ($node_types as $key => $value) {
+    db_query("INSERT INTO {nodereview_type_nodetype} (nrtid, node_type) VALUES (%d, '%s')", $nrtid, $value);
+  }
+
+  drupal_goto('admin/settings/nodereview/nodereview_type/list');
+  
+}
+
+
+function nodereview_type_delete($dummy, $nrtid) {
+
+  $form = array();
+
+  $form['nrtid'] = array(
+    '#type' => 'value',
+    '#value' => $nrtid,
+  );
+
+  $nodereview_type = db_fetch_object(db_query("SELECT * FROM {nodereview_type} WHERE nrtid = %d", $nrtid));
+
+  return confirm_form($form,
+    t('Are you sure you want to delete %name?', array('%name' => $nodereview_type->name)),
+    isset($_GET['destination']) ? $_GET['destination'] : 'admin/settings/nodereview/nodereview_type/list',
+    t('This action cannot be undone.'),
+    t('Delete'),
+    t('Cancel')
+  );
+
+}
+
+
+function nodereview_type_delete_submit($form, $form_state) {
+
+  $form_values = $form_state['values'];
+  $nrtid = $form_values['nrtid'];
+  
+  $sql = "DELETE FROM {nodereview_type} WHERE nrtid = %d";
+  db_query($sql, $nrtid);
+
+  $sql = "DELETE FROM {nodereview_type_nodetype} WHERE nrtid = %d";
+  db_query($sql, $nrtid);
+
+  drupal_goto('admin/settings/nodereview/nodereview_type/list');
+  
+}
diff -urp nodereview/nodereview.install nodereview_new/nodereview.install
--- nodereview/nodereview.install	2009-05-16 19:29:51.000000000 +0300
+++ nodereview_new/nodereview.install	2010-02-02 09:16:48.000000000 +0300
@@ -26,6 +26,7 @@ function nodereview_uninstall() {
 
   //Delete all the node type entry from nodetype table
   db_query("DELETE FROM {node_type} WHERE type='nodereview'");
+  db_query("DELETE FROM {node_type} WHERE type='nodereview_type'");
 
   //Delete nodereview fivestar variables
   variable_del('nodereview_fivestar_enable');
@@ -36,11 +37,16 @@ function nodereview_uninstall() {
     variable_del('nodereview_use_' . $type);
     variable_del('nodereview_guide_' . $info->name);
   }
+  variable_del('nodereview_textual_grade');
+  variable_del('nodereview_hide_descr');
+  variable_del('nodereview_userreviews');
+  variable_del('nodereview_vocabulary');
 }
 
 
 /**
  * Implementation of hook_schema().
+ * We use the original schema for update purposes.
  */
 function nodereview_schema() {
 
@@ -113,7 +119,6 @@ function nodereview_schema() {
   );
 
 
-
   $schema['nodereview_reviews'] = array(
     'description' => t('Stores reviews.'),
     'fields' => array(
@@ -146,3 +151,218 @@ function nodereview_schema() {
 }
 
 
+/**
+ * Update database schema: Add tables nodereview_type and nodereview_type_nodetype.
+ */
+function nodereview_update_6100() {
+
+  $ret = array();
+
+  //Delete old nodereview node types & its help info
+  foreach(node_get_types() as $type => $info) {
+    variable_del('nodereview_use_' . $type);
+    variable_del('nodereview_guide_' . $info->name);
+  }
+
+  $schema = array();
+  $schema['nodereview_type'] = array(
+    'description' => t('Stores review types.'),
+    'fields' => array(
+      'nrtid' => array(
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'size' => normal,
+        'not null' => TRUE,
+        'description' => t('The {nodereview_type}.nrtid of the review type.'),
+      ),
+      'name' => array(
+        'type' => 'varchar',
+        'length'   => 255,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => t('The name of the review type.'),
+      ),
+      'description' => array(
+        'type' => 'text',
+        'not null' => TRUE,
+        'default' => '',
+        'description' => t('The description of the review type.'),
+      ),
+      'guide' => array(
+        'type' => 'text',
+        'not null' => TRUE,
+        'default' => '',
+        'description' => t('Instructions to reviewers on how to use this review type.'),
+      ),
+    ),
+    'primary key' => array('nrtid'),
+  );
+  $schema['nodereview_type_nodetype'] = array(
+    'description' => t('Stores node types for particular nodereview types.'),
+    'fields' => array(
+      'nrtid' => array(
+        'type' => 'int',
+        'length'   => 11,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => t('The {nodereview_type}.nrtid of the review type.'),
+      ),
+      'node_type' => array(
+        'type' => 'varchar',
+        'length'   => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => t('The node type associated with the review type.'),
+      ),
+    ),
+  );
+  foreach ($schema as $name => $table) {
+    db_create_table($ret, $name, $table);
+  }
+
+  return $ret;
+
+}
+
+
+/**
+ * Update database schema: Add nrtid field to nodereview table.
+ */
+function nodereview_update_6101() {
+
+  $ret = array();
+
+  $nrtid = array(
+    'type' => 'int',
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+    'default' => 0,
+    'description' => t('The {nodereview_type}.nrtid of the review type.'),
+  );
+  db_add_field($ret, 'nodereview', 'nrtid', $nrtid);
+
+  return $ret;
+
+}
+
+
+/**
+ * Update database schema: Reconfigure nodereview_axes table.
+ */
+function nodereview_update_6102() {
+
+  $ret = array();
+
+  $nrtid = array(
+    'type' => 'int',
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+    'default' => 0,
+    'description' => t('The {nodereview_type}.nrtid to which the axis belongs.'),
+  );
+  db_add_field($ret, 'nodereview_axes', 'nrtid', $nrtid);
+
+  $tid = array(
+    'type' => 'int',
+    'not null' => TRUE,
+    'default' => 0,
+    'description' => t('The term id associated with the review type.'),
+  );
+  db_add_field($ret, 'nodereview_axes', 'tid', $tid);
+
+  $hide_description = array(
+    'type' => 'int',
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+    'default' => 0,
+    'description' => t('Whether or not to hide the description of the axes.'),
+  );
+  db_add_field($ret, 'nodereview_axes', 'hide_description', $hide_description);
+
+  $multiplier = array(
+    'type' => 'numeric',
+    'precision' => 8,
+    'scale' => 2,
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+    'default' => 1.00,
+    'description' => t('The weight of the axes to determine its contribution to the total.'),
+  );
+  db_add_field($ret, 'nodereview_axes', 'multiplier', $multiplier);
+
+  return $ret;
+
+}
+
+
+/**
+ * Update database: Populate the nodereview_type and nodereview_type_nodetype tables
+ *                  and update the nodereview_axes and nodereview tables.
+ */
+function nodereview_update_6103() {
+
+  $axes = db_query("SELECT DISTINCT node_type FROM {nodereview_axes}");
+  while ($axis = db_fetch_object($axes)) {
+    $node_type = $axis->node_type;
+
+    // Populate nodereview_type table.
+    db_query("INSERT INTO {nodereview_type} (name) VALUES ('%s')", $node_type);
+    $nrtid = db_last_insert_id('nodereview_type', 'nrtid');
+
+    // Populate nodereview_type_nodetype table.
+    db_query("INSERT INTO {nodereview_type_nodetype} (nrtid, node_type) VALUES (%d, '%s')",$nrtid, $node_type);
+
+    // Populate nrtid field in updated nodereview_axes table.
+    $sql = "UPDATE {nodereview_axes} SET nrtid = %d WHERE node_type = '%s'";
+    db_query($sql, $nrtid, $node_type);
+  }
+
+  // Populate nrtid field in updated nodereview table.
+  $nodereviews = db_query("SELECT * FROM {nodereview}");
+  while ($nodereview = db_fetch_object($nodereviews)) {
+    $node = node_load($nodereview->reviewed_nid);
+    $nrtid = db_result(db_query("SELECT nrtid FROM {nodereview_type} WHERE name = '%s'", $node->type));
+    $sql = "UPDATE {nodereview} SET nrtid = %d WHERE nid = %d";
+    db_query($sql, $nrtid, $nodereview->nid);
+  }
+
+}
+
+
+/**
+ * Update database schema: Drop node_type field from nodereview_axes table.
+ */
+function nodereview_update_6104() {
+
+  $ret = array();
+
+  db_drop_field($ret, 'nodereview_axes', 'node_type');
+
+  return $ret;
+
+}
+
+
+/**
+ * Update database :Since we changed the tag field to hold the actual aid,
+ *                  we have to update the votingapi_vote and votingapi_cache tables.
+ */
+function nodereview_update_6105() {
+  // The tag field is not enforced to be unique in the database schema.
+  // This update only works when the tags are unique.
+
+  // Perform update only if tags are unique.
+  $numberofaxes = db_result(db_query("SELECT COUNT(aid) FROM {nodereview_axes}"));
+  $numberoftags = db_result(db_query("SELECT COUNT(DISTINCT tag) FROM {nodereview_axes}"));
+  if ($numberofaxes == $numberoftags) { // Tags are unique.
+    $axes = db_query("SELECT aid, tag FROM {nodereview_axes}");
+    while ($axis = db_fetch_object($axes)) {
+      db_query("UPDATE {votingapi_vote} SET tag = '%s' WHERE tag = '%s'", $axis->aid, $axis->tag);
+      db_query("UPDATE {votingapi_cache} SET tag = '%s' WHERE tag = '%s'", $axis->aid, $axis->tag);
+    }
+  }
+  else { //Tags are not unique.
+    drupal_set_message('Tags are not unique, update 6105 not performed.', 'error');
+  }
+
+}
diff -urp nodereview/nodereview.module nodereview_new/nodereview.module
--- nodereview/nodereview.module	2009-05-16 19:29:51.000000000 +0300
+++ nodereview_new/nodereview.module	2010-02-02 09:24:39.000000000 +0300
@@ -62,7 +62,7 @@ function nodereview_node_info() {
       'has_title' => TRUE,
       'title_label' => t('Short comment'),
       'has_body' => FALSE,
-    )
+    ),
   );
 }
 
@@ -91,12 +91,13 @@ function nodereview_link($type, $node = 
   if ($type == 'node' && $node->type == 'nodereview') {
 
     // Add a link back to the node being reviewed by this node
-    $reviewed_type = node_get_types('type', db_result(db_query("SELECT type FROM {node} WHERE nid=%d", $node->reviewed_nid)));
+    $reviewed_nid = db_result(db_query("SELECT reviewed_nid FROM {nodereview} WHERE nid = %d", $node->nid));
+    $reviewed_type = node_get_types('type', db_result(db_query("SELECT type FROM {node} WHERE nid=%d", $reviewed_nid)));
     $reviewed_type = $reviewed_type->name;
 
     $links['nodereview_reviewed_node'] = array(
     'title' => t('View @type', array('@type' => $reviewed_type)),
-    'href' => "node/{$node->reviewed_nid}",
+    'href' => "node/{$reviewed_nid}",
     'attributes' => array('title' => t('View the @type being reviewed', array('@type' => $reviewed_type))),
    );
   }
@@ -112,86 +113,153 @@ function nodereview_menu() {
   $items = array();
   global $user;
 
-  $items['admin/content/nodereview'] = array(
-    'title' => t('Review types'),
+  $items['admin/settings/nodereview'] = array(
+    'title' => t('Nodereview'),
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('nodereview_configure'),
+    'page arguments' => array('nodereview_settings'),
     'file' => 'nodereview.admin.inc',
     'file path' => drupal_get_path('module', 'nodereview'),
     'access arguments' => array('administer reviews'),
-    'description' => t('Configure the axes for node type review'),
-    );
+    'description' => t('Configure nodereview'),
+  );
+
+  $items['admin/settings/nodereview/nodereview_type'] = array(
+    'title' => t('Nodereview type'),
+    'page callback' => 'nodereview_type_list',
+    //'page arguments' => array('nodereview_type_list'),
+    'file' => 'nodereview.admin.inc',
+    'file path' => drupal_get_path('module', 'nodereview'),
+    'access arguments' => array('administer reviews'),
+    'description' => t('Configure nodereview types'),
+    'type' => MENU_LOCAL_TASK,
+  );
 
-  $items['admin/content/nodereview/types'] = array(
+  $items['admin/settings/nodereview/nodereview_type/list'] = array(
     'title' => t('List'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('nodereview_configure'),
     'file' => 'nodereview.admin.inc',
     'file path' => drupal_get_path('module', 'nodereview'),
     'access arguments' => array('administer reviews'),
+    'description' => t('List nodereview types'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -1,
-    );
-
-
-  // Add a tab for each node type that we can review
-  // It's slow to put this here, as it should go in
+  );
 
-  foreach(node_get_types() as $type => $info) {
-    if(variable_get('nodereview_use_'. $type, 0)) {
-      $items['admin/content/nodereview/' . $type] = array(
-        'title callback' => 'check_plain',
-        'title arguments' => array($info->name),
-        'page callback' => 'drupal_get_form',
-        'page arguments' => array('nodereview_configure_axes', $type, $info->name),
-        'file' => 'nodereview.admin.inc',
-        'file path' => drupal_get_path('module', 'nodereview'),
-        'access arguments' => array('administer reviews'),
-        'type' => MENU_LOCAL_TASK,
-      );
+  $items['admin/settings/nodereview/nodereview_type/add'] = array(
+    'title' => t('Add'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('nodereview_type_add', 'nodereview_type'),
+    'file' => 'nodereview.admin.inc',
+    'file path' => drupal_get_path('module', 'nodereview'),
+    'access arguments' => array('administer reviews'),
+    'description' => t('Create nodereview types'),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 0,
+  );
 
-    }
+  $items['admin/settings/nodereview/nodereview_type/import'] = array(
+    'title' => t('Import'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('nodereview_type_import', 'nodereview_type'),
+    'file' => 'nodereview.admin.inc',
+    'file path' => drupal_get_path('module', 'nodereview'),
+    'access arguments' => array('administer reviews'),
+    'description' => t('Create nodereview types'),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 0,
+  );
 
-  }
+  $items['admin/settings/nodereview/nodereview_type/%/edit'] = array(
+    'title' => t('Edit'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('nodereview_type_edit', 4),
+    'file' => 'nodereview.admin.inc',
+    'file path' => drupal_get_path('module', 'nodereview'),
+    'access arguments' => array('administer reviews'),
+    'description' => t('Edit nodereview types'),
+    'type' => MENU_CALLBACK,
+    'weight' => -1,
+  );
 
-   $items['node/%/reviews'] = array(
-     'title' => t('Reviews'),
-     'page callback' => 'views_page',
-     'page arguments' => array('review_list', 'page_1', 1),
-     'access callback' => 'read_reviews_access',
-     'access arguments' => array(1),
-     'file' => 'views.module',
-     'file path' => drupal_get_path('module', 'views'),
-     'type' => MENU_LOCAL_TASK,
-     'weight' => 2,
-   );
+  $items['admin/settings/nodereview/nodereview_type/%/review'] = array(
+    'title' => t('Review'),
+    //'title callback' => 'check_plain',
+    //'title arguments' => array('Axes for '. $nr_type_name),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('nodereview_type_configure_axes', 4),
+    'file' => 'nodereview.admin.inc',
+    'file path' => drupal_get_path('module', 'nodereview'),
+    'access arguments' => array('administer reviews'),
+    'description' => t('Configure reviews for nodereview types'),
+    'type' => MENU_CALLBACK,
+    'weight' => 0,
+  );
 
-  
+  $items['admin/settings/nodereview/nodereview_type/%/delete'] = array(
+    'title' => t('Delete'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('nodereview_type_delete', 4),
+    'file' => 'nodereview.admin.inc',
+    'file path' => drupal_get_path('module', 'nodereview'),
+    'access arguments' => array('administer reviews'),
+    'description' => t('Delete nodereview types'),
+    'type' => MENU_CALLBACK,
+    'weight' => 1,
+  );
 
-  $items['node/%node_add_review/addreview'] = array(
-    'title' => t('Add review'),
-    'page callback' => 'node_add',
-    'page arguments' => array('nodereview'),
-    'access callback' => 'addreview_access',
+  $items['node/%/reviews'] = array(
+    'title' => t('Reviews'),
+    'page callback' => 'views_page',
+    'page arguments' => array('review_list', 'page_1', 1),
+    'access callback' => 'read_reviews_access',
     'access arguments' => array(1),
+    'file' => 'views.module',
+    'file path' => drupal_get_path('module', 'views'),
     'type' => MENU_LOCAL_TASK,
-    'weight' => 3,
+    'weight' => 2,
   );
 
-  $items['node/%node_edit_review/editreview'] = array(
-    'title' => t('Edit your review'),
-    'page callback' => 'node_page_edit',
-    'page arguments' => array(1),
-    'access arguments' => array('edit own reviews'),
-    'type' => MENU_LOCAL_TASK,
-    'weight' => 3,
-  );
+  /*
+   * Add an "Add review" tab for every nodereview type
+   * associated with the node type of the current node.
+   */
+  if ((arg(0) == 'node') && (is_numeric(arg(1)))) {
+    $nr_types = db_query("SELECT * FROM {nodereview_type}");
+    while ($nr_type = db_fetch_object($nr_types)) {
+      $items['node/%node_add_review/addreview/'. $nr_type->nrtid] = array(
+        'title' => t('Add review ('. $nr_type->name .')'),
+        'load arguments' => array($nr_type->nrtid),
+        'page callback' => 'node_add',
+        'page arguments' => array('nodereview'),
+        'access callback' => 'addreview_access',
+        'access arguments' => array(1, $nr_type->nrtid),
+        'type' => MENU_LOCAL_TASK,
+        'weight' => 3,
+      );
+    }
+  }
+
+  /*
+   * Do the same for "Edit my review".
+   */
+  if ((arg(0) == 'node') && (is_numeric(arg(1)))) {
+    $nr_types = db_query("SELECT * FROM {nodereview_type}");
+    while ($nr_type = db_fetch_object($nr_types)) {
+      $items['node/%node_edit_review/editreview/'. $nr_type->nrtid] = array(
+        'title' => t('Edit your review ('. $nr_type->name .')'),
+        'load arguments' => array($nr_type->nrtid),
+        'page callback' => 'node_page_edit',
+        'page arguments' => array(1),
+        'access arguments' => array('edit own reviews'),
+        'type' => MENU_LOCAL_TASK,
+        'weight' => 3,
+      );
+    }
+  }
 
   return $items;
 }
 
 
-
 /**
  * Implementation of hook_menu_alter()
  *
@@ -199,12 +267,9 @@ function nodereview_menu() {
 function nodereview_menu_alter(&$callbacks) {
   // Hide the normal node-add page, since we never want users to see it
   unset($callbacks['node/add/nodereview']);
-
-
 }
 
 
-
 /**
  * Implementation of hook_form_alter()
  *
@@ -241,52 +306,45 @@ function nodereview_form_alter(&$form, $
   * named theme_nodereview_configure_axes().
   */
 function nodereview_theme() {
-   return array(
-      'nodereview_configure_axes' => array(
-         'arguments' => array('form'),
-         'file' => 'nodereview.theme.inc',
-         'path' => drupal_get_path('module', 'nodereview'),
-      ),
-      'nodereview_review_body' => array(
-         'arguments' => array('review' => NULL, 'node' => NULL),
-         'file' => 'nodereview.theme.inc',
-         'path' => drupal_get_path('module', 'nodereview'),
-      ),
-      'nodereview_review_preview' => array(
-         'arguments' => array('review' => NULL, 'node' => NULL),
-         'file' => 'nodereview.theme.inc',
-         'path' => drupal_get_path('module', 'nodereview'),
-      ),
-      'nodereview_teaser' => array(
-         'arguments' => array('node' => NULL),
-         'file' => 'nodereview.theme.inc',
-         'path' => drupal_get_path('module', 'nodereview'),
-      ),
-
-   );
+  return array(
+    'nodereview_type_configure_axes' => array(
+      'arguments' => array('form'),
+      'file' => 'nodereview.theme.inc',
+      'path' => drupal_get_path('module', 'nodereview'),
+    ),
+    'nodereview_review_body' => array(
+      'arguments' => array('review' => NULL, 'node' => NULL),
+      'file' => 'nodereview.theme.inc',
+      'path' => drupal_get_path('module', 'nodereview'),
+    ),
+    'nodereview_review_preview' => array(
+      'arguments' => array('review' => NULL, 'node' => NULL),
+      'file' => 'nodereview.theme.inc',
+      'path' => drupal_get_path('module', 'nodereview'),
+    ),
+    'nodereview_teaser' => array(
+      'arguments' => array('node' => NULL),
+      'file' => 'nodereview.theme.inc',
+      'path' => drupal_get_path('module', 'nodereview'),
+    ),
+  );
 }
 
 
 function nodereview_view_reviews($nid) {
-
-  $output = 'test ' . $nid;
-
   drupal_set_title('Reviews');
-
-  return $output;
 }
 
-
-function nodereview_list_axes($node_type) {
+function nodereview_type_list_axes($nrtid) {
   static $axes = array();
 
-  if (! isset($axes[$node_type])) {
-    $result = db_query("SELECT na.aid, na.tag FROM {nodereview_axes} na WHERE na.node_type='%s'", $node_type);
+  if (! isset($axes[$nrtid])) {
+    $result = db_query("SELECT na.aid, na.tag FROM {nodereview_axes} na WHERE na.nrtid=%d", $nrtid);
     while ($record = db_fetch_object($result)) {
-      $axes[$node_type][$record->aid] = $record->tag;
+      $axes[$nrtid][$record->aid] = $record->tag;
     }
   }
-  return $axes[$node_type];
+  return $axes[$nrtid];
 }
 
 
@@ -303,13 +361,18 @@ function nodereview_node_type($op, $info
   menu_rebuild();
 }
 
+/*
+function nodereview_type_node_type($op, $info) {
+  cache_clear_all();
+  menu_rebuild();
+}
+ */
 
 /**
  * Implementation of hook_views_api()
  *
  */
 function nodereview_views_api() {
-
   return array(
     'api' => '2.0',
     'path' =>drupal_get_path('module', 'nodereview'),
@@ -319,54 +382,188 @@ function nodereview_views_api() {
 
 /**
  * Menu callback
- * Returns TRUE if no review for the current node from current user
+ * Returns nid of node to be reviewed if no review for the current node from current user
  * Returns FALSE if review review for the current node from current user
  */
-function node_add_review_load($arg) {
+function node_add_review_load($nid, $nrtid) {
   global $user;
-  $add_review = FALSE;
-  $current_node = node_load($arg);
-  $type =$current_node->type;
-  $axes_count = db_result(db_query("SELECT COUNT(*) FROM {nodereview_axes} WHERE node_type='%s'", $type));
-  if (variable_get('nodereview_use_' . $type, 0) && $axes_count) {
-    $add_review = db_result(db_query("SELECT n.nid FROM {node} n INNER JOIN {nodereview} nr ON n.nid=nr.nid WHERE uid=%d AND reviewed_nid=%d", $user->uid, $arg));
+  $user_reviews = 0;
+  $axes_count = db_result(db_query("SELECT COUNT(*) FROM {nodereview_axes} WHERE nrtid=%d", $nrtid));
+  if ($axes_count) {
+    // Get the number of reviews of the specified type on this node by the current user.
+    $sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {nodereview} nr ON n.nid=nr.nid WHERE uid=%d AND reviewed_nid=%d AND nrtid=%d";
+    $user_reviews = db_result(db_query($sql, $user->uid, $nid, $nrtid));
   }
-  return $add_review ? FALSE : $arg;
+  return $user_reviews ? FALSE : $nid;
 }
 
 
 /**
  * Menu callback
  * Returns FALSE if no review for the current node from current user
- * Returns review node object if review for the current node exists to alter the review
+ * Returns the review node object if it exists for the current node to alter the reviews
  */
-function node_edit_review_load($arg) {
+function node_edit_review_load($nid, $nrtid) {
   global $user;
-  $edit_review = FALSE;
-  $current_node = node_load($arg);
-  $type =$current_node->type;
-  $axes_count = db_result(db_query("SELECT COUNT(*) FROM {nodereview_axes} WHERE node_type='%s'", $type));
-  if (variable_get('nodereview_use_' . $type, 0) && $axes_count) {
-    $edit_review = db_result(db_query("SELECT n.nid FROM {node} n INNER JOIN {nodereview} nr ON n.nid=nr.nid WHERE uid=%d AND reviewed_nid=%d", $user->uid, $arg));
+  $user_reviews = 0;
+  $axes_count = db_result(db_query("SELECT COUNT(*) FROM {nodereview_axes} WHERE nrtid=%d", $nrtid));
+  if ($axes_count) {
+    // Get the number of reviews on this node by the current user.
+    $sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {nodereview} nr ON n.nid=nr.nid WHERE uid=%d AND reviewed_nid=%d AND nrtid=%d";
+    $user_reviews = db_result(db_query($sql, $user->uid, $nid, $nrtid));
+    if ($user_reviews) {
+      // Get the nid of the review.
+      $sql = "SELECT n.nid FROM {node} n INNER JOIN {nodereview} nr ON n.nid=nr.nid WHERE uid=%d AND reviewed_nid=%d AND nrtid=%d";
+      $review = db_fetch_object(db_query($sql, $user->uid, $nid, $nrtid));
+      $edit_review = node_load($review->nid);
+    }
   }
-  return $edit_review ? node_load($edit_review) : FALSE;
+  return $user_reviews ? $edit_review : FALSE;
 }
 
 /**
  * Custom access menucallback for add review
  */
-function addreview_access($arg) {
-  $current_node = node_load($arg);
-  $type =$current_node->type;
-  $axes_count = db_result(db_query("SELECT COUNT(*) FROM {nodereview_axes} WHERE node_type='%s'", $type));
-  return variable_get('nodereview_use_' . $type, 0) && $axes_count && user_access('submit reviews');
+function addreview_access($nid, $nrtid) {
+  $node = node_load($nid);
+  $sql = "SELECT COUNT(nrtid) FROM {nodereview_type_nodetype} WHERE nrtid = %d AND node_type = '%s'";
+  $use = db_result(db_query($sql, $nrtid, $node->type));
+  if ($use) {
+    $axes_count = db_result(db_query("SELECT COUNT(*) FROM {nodereview_axes} WHERE nrtid=%d", $nrtid));
+  }
+  return $use && $axes_count && user_access('submit reviews');
 }
 
 /**
  * Custom access menucallback for read review
  */
 function read_reviews_access($arg) {
+  $read_reviews_access = FALSE;
   $current_node = node_load($arg);
   $type =$current_node->type;
-  return variable_get('nodereview_use_' . $type, 0) && user_access('read reviews');
+  $nr_types = db_query("SELECT * FROM {nodereview_type_nodetype} WHERE node_type = '%s'", $type);
+  if ($nr_type = db_fetch_object($nr_types)) {
+    $read_reviews_access = TRUE;
+  }
+  //return variable_get('nodereview_use_' . $type, 0) && user_access('read reviews');
+  return $read_reviews_access && user_access('read reviews');
+}
+
+
+function nodereview_votingapi_results_alter(&$cache, $content_type, $content_id) {
+  $sql = "SELECT v.value_type, v.uid, na.nrtid, ";
+  $sql .= "COUNT(v.value) as value_count, SUM(v.value * na.multiplier) as value_sum ";
+  $sql .= "FROM {votingapi_vote} v INNER JOIN {nodereview_axes} na ON v.tag = na.aid ";
+  $sql .= "WHERE v.content_type = '%s' AND v.content_id = %d AND v.value_type = 'points' ";
+  $sql .= "GROUP BY v.value_type, v.uid, na.nrtid";
+  $results = db_query($sql, $content_type, $content_id);
+  while ($result = db_fetch_array($results)) {
+    $cache['t'. $result['nrtid'] .'-u'. $result['uid']]['points']['weighed_total'] = $result['value_sum'];
+  }
+}
+
+/**
+ * Features support.
+ */
+
+/**
+ * Implementation of hook_features_api().
+ */
+function nodereview_features_api() {
+  return array(
+    'nodereview' => array(
+      'name' => t('Nodereview types'),
+      'default_hook' => 'nodereview_types_defaults',
+      'features_source' => TRUE,
+      //'file' => drupal_get_path('module', 'nodereview') .'/nodereview.features.inc',
+    )
+  );
+}
+
+/**
+function nodereview_nodereview_types_defaults() {
+  drupal_set_message('nodereview_types_defaults');
+  $nodereview_types = array();
+  $nodereview_types[1000] = array(
+    'nrtid' => 1000,
+    'name' => 'nodereview type test 1',
+    'description' => t(''),
+    'guide' => t(''),
+  );
+  return $nodereview_types;
+}
+ */
+
+/**
+ * Implementation of hook_features_export_options().
+ */
+function nodereview_features_export_options() {
+  $options = array();
+  $nodereview_types = db_query("SELECT nrtid, name FROM {nodereview_type}");
+  while ($nodereview_type = db_fetch_object($nodereview_types)) {
+    $options[$nodereview_type->nrtid] = $nodereview_type->name;
+  }
+  return $options;
+}
+
+/**
+ * Implementation of hook_features_export().
+ */
+function nodereview_features_export($data, &$export, $module_name = '') {
+
+  $export['dependencies'] = array();
+  $export['dependencies']['votingapi'] = 'votingapi';
+  $export['dependencies']['views'] = 'views';
+  foreach ($data as $nodereview_type) {
+    // Add modules that implement the node types used in the nodereview type to node type mapping to the dependencies.
+    $node_types = db_query("SELECT node_type FROM {nodereview_type_nodetype} WHERE nrtid = %d", $nodereview_type);
+    while ($node_type = db_fetch_array($node_types)) {
+      $module = db_result(db_query("SELECT module FROM {node_type} WHERE type = '%s'", $node_type['node_type']));
+      $export['dependencies'][$module] = $module;
+    }
+    $export['features']['nodereview'][$nodereview_type] = $nodereview_type;
+  }
+
 }
+
+/**
+ * Implementation of hook_features_export_render().
+ */
+function nodereview_features_export_render($module_name, $data) {
+  $items = array();
+  foreach ($data as $key) {
+    $nodereview_type = db_fetch_array(db_query("SELECT * FROM {nodereview_type} WHERE nrtid = %d", $key));
+    $node_types = db_query("SELECT * FROM {nodereview_type_nodetype} WHERE nrtid = %d", $key);
+    $nodereview_type['nodetypes'] = array();
+    while ($node_type = db_fetch_array($node_types)) {
+      $nodereview_type['nodetypes'][$node_type['node_type']] = $node_type;
+    }
+    $axes = db_query("SELECT * FROM {nodereview_axes} WHERE nrtid = %d", $key);
+    $nodereview_type['axes'] = array();
+    while ($axe = db_fetch_array($axes)) {
+      $nodereview_type['axes'][$axe['aid']] = $axe;
+    }
+    $items[$key] = $nodereview_type;
+  }
+  $code = "  \$nodereview_types = ". features_var_export($items, '  ') .";\n";
+  $code .= '  return $nodereview_types;';
+  return array('nodereview_types_defaults' => $code);
+}
+
+/**
+ * Implementation of hook_features_revert().
+ */
+/**
+function nodereview_features_revert($module) {
+  $default_nodereview_types = module_invoke($module, 'nodereview_types');
+  if (!empty($default_nodereview_types)) {
+    foreach (array_keys($default_nodereview_types) as $default_nodereview_type) {
+      $nodereview_type = nodereview_nodereview_type_by_name($default_nodereview_type);
+      if ($nodereview_type) {
+        //imagecache_preset_delete($nodereview_type);
+      }
+    }
+  }
+}
+ */
+ 
diff -urp nodereview/nodereview_node_nodereview.inc nodereview_new/nodereview_node_nodereview.inc
--- nodereview/nodereview_node_nodereview.inc	2009-05-16 19:29:51.000000000 +0300
+++ nodereview_new/nodereview_node_nodereview.inc	2010-02-02 09:12:30.000000000 +0300
@@ -33,14 +33,15 @@ function nodereview_access($op, $node) {
   }
 }
 
-
 /**
- * Implementation of hook_form().
+ * Implementation of my hook_form().
  *
  */
 function nodereview_form(&$node) {
+  global $user;
 
-  // This is for the LOCAL_TASK version, node/nid/addreview
+  //$nrtid = arg(3) ? arg(3) : 2;
+  $nrtid = arg(3) ? arg(3) : 4;
   if (!$node->reviewed_nid) {
     $node->reviewed_nid = arg(1);
   }
@@ -55,6 +56,7 @@ function nodereview_form(&$node) {
     '#type' => 'textfield',
     '#title' => t($node_info->title_label),
     '#default_value' => $node->title,
+    '#weight' => -99,
     '#required' => TRUE
   );
 
@@ -63,20 +65,32 @@ function nodereview_form(&$node) {
   $form['reviews']['#tree'] = TRUE;
   $form['reviews']['#weight'] = 0;
 
-  $result = db_query("SELECT * FROM {nodereview_axes} WHERE node_type ='%s' ORDER BY weight, tag", $reviewed_node->type);
-
-  while ($record = db_fetch_object($result)) {
-    _nodereview_form_review($form, $record, $node);
+  // Group axes in a (collapsible) fieldset according to tid (term).
+  $tids = db_query("SELECT DISTINCT(tid) FROM {nodereview_axes} WHERE nrtid =%d ORDER BY tid", $nrtid);
+  while ($tid = db_fetch_object($tids)) {
+    $last_tid = $tid->tid;
+    $form['reviews'][$tid->tid] = array(
+      '#type' => 'fieldset',
+      '#title' => taxonomy_get_term($tid->tid)->name,
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    );
+    $axes = db_query("SELECT * FROM {nodereview_axes} WHERE nrtid =%d AND tid = %d ORDER BY weight, tag", $nrtid, $tid->tid);
+    while ($axis = db_fetch_object($axes)) {
+      _nodereview_form_review($form, $axis, $node, $tid->tid);
+    }
   }
+  $form['reviews'][$last_tid]['#collapsible'] = FALSE;
+  $form['reviews'][$last_tid]['#collapsed'] = FALSE;
 
   // We'll use a single filter format for all textareas on the page
-  $form['filter'] = filter_form($node->format);
+  //$form['filter'] = filter_form($node->format);
 
   return $form;
 }
 
 /**
- * Add the review axis to the node edit form
+ * My version of add the review axis to the node edit form
  *
  * @param $form
  *  The form object for the node edit form
@@ -88,10 +102,11 @@ function nodereview_form(&$node) {
  *  An array of votes (scores) for this review, keyed by axis name
  */
 //function _nodereview_form_review(&$form, $axis, $reviews, $votes) {
-function _nodereview_form_review(&$form, $axis, $node) {
+function _nodereview_form_review(&$form, $axis, $node, $tid) {
   static $options;
   if (!isset($options)) {
     $options = array(
+      0 => '--',
       10 => 1,
       20 => 2,
       30 => 3,
@@ -104,33 +119,29 @@ function _nodereview_form_review(&$form,
       100 => 10,
     );
   }
-  $form['reviews'][$axis->aid] = array(
-    '#type' => 'fieldset',
-    '#title' => $axis->tag,
-    '#collapsible' => TRUE,
-    '#collapsed' => FALSE,
-  );
 
-  $form['reviews'][$axis->aid]['score'] = array(
+  $form['reviews'][$tid][$axis->aid]['score'] = array(
     '#type' => 'select',
     '#title' => t('Score'),
     '#options' => $options,
-    '#default_value' => $node->reviews[$axis->aid]['score'] ? $node->reviews[$axis->aid]['score'] : 50,
+    '#default_value' => $node->reviews[$axis->aid]['score'] ? $node->reviews[$axis->aid]['score'] : 0,
     '#description' => $axis->description,
     '#required' => TRUE,
   );
 
   if (NODEREVIEW_FIVESTAR_ENABLE) {
-    $form['reviews'][$axis->aid]['score']['#type'] = 'fivestar';
-    $form['reviews'][$axis->aid]['score']['#stars'] = variable_get('nodereview_fivestar_stars', 5);
+    $form['reviews'][$tid][$axis->aid]['score']['#type'] = 'fivestar';
+    $form['reviews'][$tid][$axis->aid]['score']['#stars'] = variable_get('nodereview_fivestar_stars', 5);
   }
 
-  $form['reviews'][$axis->aid]['review'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Review'),
-    '#default_value' => $node->reviews[$axis->aid]['review'],
-    '#required' => TRUE,
-  );
+  if (! variable_get('nodereview_textual_grade', 0)) {
+    $form['reviews'][$tid][$axis->aid]['review'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Review'),
+      '#default_value' => $node->reviews[$axis->aid]['review'],
+      '#required' => FALSE,
+    );
+  }
 }
 
 
@@ -143,13 +154,15 @@ function nodereview_validate(&$node) {
     // There is no such node, so error
     form_set_error('reviewed_nid', t('The node you are trying to review does not exist.'));
   }
-  foreach ($node->reviews as $aid => $review) {
-    if (! $review['score']) {
-      form_set_error('', t('You must enter a score for every axis.'));
-    }
-    if (! $review['review']) {
-      form_set_error('', t('You must enter a review for every axis.'));
-    }
+  foreach ($node->reviews as $tid => $axes) {
+  	foreach ($axes as $aid => $review) {
+  		if (! $review['score']) {
+        form_set_error('', t('You must enter a score for every axis.'));
+      }
+//      if (! $review['review']) {
+//        form_set_error('', t('You must enter a review for every axis.'));
+//      }
+  	}
   }
 }
 
@@ -159,33 +172,33 @@ function nodereview_validate(&$node) {
  */
 function nodereview_load($node) {
   // Get the basic information from the nodereview node table
-  $additions = db_fetch_object(db_query('SELECT reviewed_nid FROM {nodereview} WHERE nid = %d', $node->nid));
+  $additions = db_fetch_object(db_query('SELECT reviewed_nid FROM {nodereview} WHERE nid = %d AND nrtid = %d', $node->nid, $node->nrtid));
   // And now get the actual review info.  The numeric scores are stored with voteapi,
   // while textual reviews are in our own auxiliary table.  We need to merge them properly
-
+  
   $criteria = array(
     'content_type' => 'node',
     'content_id' => $additions->reviewed_nid,
     'uid' => $node->uid,
   );
-
+  
   $votes_obj = votingapi_select_votes($criteria);
-
-
+  
   //  $votes_obj = votingapi_get_user_votes('node', $additions->reviewed_nid, $node->uid);
   $votes = array();
   foreach ($votes_obj as $vote) {
-    $votes[$vote['tag']] = $vote;
+  	$votes[$vote['tag']] = $vote;
   }
 
-
   $additions->reviews = array();
-  $result = db_query('SELECT nr.aid, tag, review FROM {nodereview_reviews} nr INNER JOIN {nodereview_axes} na ON nr.aid=na.aid WHERE nid = %d ORDER BY na.weight, na.tag', $node->nid);
+  $result = db_query('SELECT nr.aid, na.tag, nr.review FROM {nodereview_reviews} nr INNER JOIN {nodereview_axes} na ON nr.aid=na.aid WHERE nr.nid = %d ORDER BY na.weight, na.tag', $node->nid);
   while ($record = db_fetch_object($result)) {
+  	
     // Add in the numeric scores
-    $record->score = $votes[$record->tag]['value'];
+    $record->score = $votes[$record->aid]['value'];
     $additions->reviews[$record->aid] = (array)$record;
   }
+  
   return $additions;
 }
 
@@ -195,8 +208,11 @@ function nodereview_load($node) {
  *
  */
 function nodereview_insert($node) {
-  db_query("INSERT INTO {nodereview} (nid, reviewed_nid) VALUES (%d, %d)", $node->nid, $node->reviewed_nid);
+  //$nrtid = arg(3) ? arg(3) : 2;
+  $nrtid = arg(3) ? arg(3) : 4;
+  db_query("INSERT INTO {nodereview} (nid, reviewed_nid, nrtid) VALUES (%d, %d, %d)", $node->nid, $node->reviewed_nid, $nrtid);
   nodereview_save_reviews($node);
+  drupal_goto('applicationstobejudged');
 }
 
 /**
@@ -204,7 +220,9 @@ function nodereview_insert($node) {
  *
  */
 function nodereview_update($node) {
-  db_query("UPDATE {nodereview} SET reviewed_nid=%d WHERE nid = %d", $node->reviewed_nid, $node->nid);
+  //$nrtid = arg(3) ? arg(3) : 2;
+  $nrtid = arg(3) ? arg(3) : 4;
+  db_query("UPDATE {nodereview} SET reviewed_nid=%d, nrtid=%d WHERE nid = %d", $node->reviewed_nid, $node->nrtid, $nrtid);
 
   // Delete and rebuild the textual reviews, but the votingapi takes care of overwriting old values
   db_query("DELETE FROM {nodereview_reviews} WHERE nid=%d", $node->nid);
@@ -214,16 +232,19 @@ function nodereview_update($node) {
 function nodereview_save_reviews($node) {
   global $user;
 
+  //$nrtid = arg(3) ? arg(3) : 2;
+  $nrtid = arg(3) ? arg(3) : 4;
   $votes = array();
+  $axes = nodereview_type_list_axes($nrtid);
+  foreach ($node->reviews as $tid => $axes) {
+  	foreach ($axes as $aid => $review) {
+      // Save the text review
+      db_query("INSERT INTO {nodereview_reviews} (nid, aid, review) VALUES (%d, %d, '%s')", $node->nid, $aid, $review['review']);
 
-  $axes = nodereview_list_axes(db_result(db_query("SELECT type FROM {node} WHERE nid=%d", $node->reviewed_nid)));
-  foreach ($node->reviews as $aid => $review) {
-    // Save the text review
-    db_query("INSERT INTO {nodereview_reviews} (nid, aid, review) VALUES (%d, %d, '%s')", $node->nid, $aid, $review['review']);
-
-    // And use the votingapi to save the score
-    $votes[] = array('value'=>$review['score'], 'tag'=>$axes[$aid], 'content_type' => 'node', 'content_id' => $node->reviewed_nid);
+      // And use the votingapi to save the score
+      $votes[] = array('value'=>$review['score'], 'tag'=>$aid, 'content_type' => 'node', 'content_id' => $node->reviewed_nid, 'value_type' => 'points');
 
+  	}
   }
   //  votingapi_set_vote('node', $node->reviewed_nid, $votes, $node->uid);
   votingapi_set_votes($votes);
@@ -235,19 +256,25 @@ function nodereview_save_reviews($node) 
  */
 function nodereview_delete($node) {
   db_query('DELETE FROM {nodereview} WHERE nid = %d', $node->nid);
+  $aids = db_query("SELECT aid FROM {nodereview_reviews} WHERE nid = %d", $node->nid);
   db_query('DELETE FROM {nodereview_reviews} WHERE nid=%d', $node->nid);
 
-
- $criteria = array(
+  $tags = array();
+  while ($aid = db_fetch_object($aids)) {
+  	$tags[] = $aid->aid;
+  }
+  $criteria = array(
     'content_type' => 'node',
     'content_id' => $node->reviewed_nid,
     'uid' => $node->uid,
+    'tag' => $tags,
   );
 
   $vote_obj = votingapi_select_votes($criteria);
   // Delete the votes in the votingapi associated with this node
   votingapi_delete_votes($vote_obj);
   votingapi_recalculate_results('node', $node->reviewed_nid);
+  
 }
 
 
@@ -257,49 +284,51 @@ function nodereview_delete($node) {
  */
 function nodereview_view($node, $teaser = FALSE, $page = FALSE) {
   //$node = node_prepare($node, $teaser);
-  $aids = array_keys($node->reviews);
-  $num_aids = sizeof($aids);
   // Previews are just plain ugly, because the $node object is not really a node
   // but a mutated $_POST.  It has to be handled completely differently.
-
+	
   if ($node->op == 'Preview') {
     // We have to load in our axis data, which the $_POST doesn't have but we need
-    $result = db_query("SELECT tag, aid
+    $result = db_query("SELECT tag, aid, tid
                         FROM {nodereview_axes} na
-                        INNER JOIN {node} n ON na.node_type=n.type
-                        WHERE n.nid=%d", $node->reviewed_nid);
+                        INNER JOIN {nodereview_type_nodetype} ntn ON na.nrtid = ntn.nrtid
+                        INNER JOIN {node} n ON ntn.node_type = n.type
+                        WHERE n.nid=%d ORDER BY tid, tag", $node->reviewed_nid);
     while ($record = db_fetch_array($result)) {
-      $node->reviews[$record['aid']]['tag'] = $record['tag'];
+      $review = db_fetch_object(db_query("SELECT review
+                                          FROM {nodereview_reviews} nr
+                                          INNER JOIN {nodereview} n ON nr.nid = n.nid
+                                          WHERE n.reviewed_nid = %d
+                                          AND nr.aid = %d", $node->reviewed_nid, $record['aid']));
+      $node->reviews[$record['tid']][$record['aid']]['tag'] = $record['tag'];
+      $node->reviews[$record['tid']][$record['aid']]['aid'] = $record['aid'];
+      $node->reviews[$record['tid']][$record['aid']]['tid'] = $record['tid'];
+      $node->reviews[$record['tid']][$record['aid']]['review'] = $review->review;
     }
 
-    foreach ($node->reviews as $review) {
-      $node->content['reviews'][$review['tag']] = array(
-        '#value' => theme('nodereview_review_preview', $review, $node),
-      );
+    foreach ($node->reviews as $tid => $axes) {
+      foreach ($axes as $aid => $review) {
+        $node->content['reviews']['#value'] .= theme('nodereview_review_preview', $review, $node);
+      }
     }
     return $node;
   }
   else {
-    $node = node_prepare($node, $teaser);
+  	$node = node_prepare($node, $teaser);
 
     // Do a markup check on the fields
-    for ($i=0; $i < $num_aids; $i++) {
-      $node->reviews[$aids[$i]]['review'] = check_markup($node->reviews[$aids[$i]]['review']);
+    foreach ($node->reviews as $aid => $review) {
+      $node->reviews[$aid]['review'] = check_markup($node->reviews[$aid]['review']);
     }
     if ($teaser) {
-      $node->content['reviews'] = array(
-          '#value' => theme('nodereview_teaser', $node),
-        );
+        $node->content['reviews']['#value'] = theme('nodereview_teaser', $node);
     }
     if ($page) {
-      foreach ($node->reviews as $review) {
-        $node->content['reviews'][$review['tag']] = array(
-          '#value' => theme('nodereview_review_body', $review, $node),
-        );
+      foreach ($node->reviews as $aid => $review) {
+        $node->content['reviews']['#value'] .= theme('nodereview_review_body', $review, $node);
       }
     }
 
-
     return $node;
   }
 }
diff -urp nodereview/nodereview.theme.inc nodereview_new/nodereview.theme.inc
--- nodereview/nodereview.theme.inc	2009-05-16 19:29:51.000000000 +0300
+++ nodereview_new/nodereview.theme.inc	2010-01-26 16:31:47.000000000 +0300
@@ -11,7 +11,7 @@
  * We declare this function to theme the axes in table
  * format
  */
-function theme_nodereview_configure_axes($form) {
+function theme_nodereview_type_configure_axes($form) {
 
   $rows = array();
   $output = '';
@@ -20,17 +20,23 @@ function theme_nodereview_configure_axes
     // Strip out the labels on each form element, since they're redundant with the header
     $form['axes'][$key]['use']['#title'] = '';
     $form['axes'][$key]['tag']['#title'] = '';
+    $form['axes'][$key]['hide_description']['#title'] = '';
     $form['axes'][$key]['description']['#title'] = '';
+    $form['axes'][$key]['tid']['#title'] = '';
+    $form['axes'][$key]['multiplier']['#title'] = '';
     $form['axes'][$key]['weight']['#title'] = '';
 
     $row[] = drupal_render($form['axes'][$key]['aid']) . drupal_render($form['axes'][$key]['use']);
     $row[] = drupal_render($form['axes'][$key]['tag']);
+    $row[] = drupal_render($form['axes'][$key]['hide_description']);
     $row[] = drupal_render($form['axes'][$key]['description']);
+    $row[] = drupal_render($form['axes'][$key]['tid']);
+    $row[] = drupal_render($form['axes'][$key]['multiplier']);
     $row[] = drupal_render($form['axes'][$key]['weight']);
     $rows[] = $row;
   }
 
-  $header = array('use', 'name', 'description', 'weight');
+  $header = array('use', 'name', 'hide', 'description', 'term', 'multiplier', 'weight');
 
   // This is how we get the table to be "inside" the fieldset
   $form['axes']['#children'] = theme('table', $header, $rows);
@@ -45,21 +51,22 @@ function theme_nodereview_configure_axes
  * view
  *
  */
-
 function theme_nodereview_review_body($review, $node) {
   //Logger::debug_var('review', $review);
-
+	
   $output = '';
 
   $title = $review['tag'];
+  $multiplier = db_result(db_query("SELECT multiplier FROM {nodereview_axes} WHERE aid = %d", $review['aid']));
+  $title .= ' (Weight = ' . $multiplier . ')';
   if (NODEREVIEW_FIVESTAR_ENABLE) {
     $output = theme('fivestar_static', $review['score'], variable_get('nodereview_fivestar_stars', 5));
   }
   else {
-    $title .= ': ' . $review['score']/10 . '/10';
+    $title .= ': ' . ($multiplier * $review['score']/10) . '/' . ($multiplier * 10);
   }
   $output = theme('box', $title, $output . $review['review']);
-
+  
   return $output;
 }
 
@@ -74,14 +81,16 @@ function theme_nodereview_review_preview
   $output = '';
 
   $title = $review['tag'];
+  $multiplier = db_result(db_query("SELECT multiplier FROM {nodereview_axes} WHERE aid = %d", $review['aid']));
+  $title .= ' (Weight = ' . $multiplier . ')';
   if (NODEREVIEW_FIVESTAR_ENABLE) {
     $output = theme('fivestar_static', $review['score']);
   }
   else {
-    $title .= ': ' . $review['score']/10 . '/10';
+    $title .= ': ' . ($multiplier * $review['score']/10) . '/' . ($multiplier * 10);
   }
   $output = theme('box', $title, $output . check_markup($review['review'], $node->format));
-
+  
   return $output;
 }
 
@@ -100,17 +109,20 @@ function theme_nodereview_teaser($node) 
   // Presumably teaser will be called multiple times on different nodes
   // on the same page, so static cache the static strings
   if (!isset($header)) {
-    $header = array(t('axis'), t('score'), t('review'));
+    $header = array(t('axis'), t('weight'), t('score'), t('review'));
   }
 
+  $rows = array();
   foreach ($node->reviews as $review) {
     $row = array();
     $row[] = $review['tag'];
+    $multiplier = db_result(db_query("SELECT multiplier FROM {nodereview_axes} WHERE aid = %d", $review['aid']));
+    $row[] = $multiplier;
     if (NODEREVIEW_FIVESTAR_ENABLE) {
       $row[] = theme('fivestar_static', $review['score'], variable_get('nodereview_fivestar_stars', 5));
     }
     else {
-      $row[] = $review['score']/10 . '/10';
+      $row[] = ($multiplier * $review['score'])/10 . '/' . ($multiplier * 10);
     }
     $row[] = truncate_utf8($review['review'], 50, TRUE, TRUE);
     $rows[] = $row;
