Index: views_bookmark.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views_bookmark/views_bookmark.module,v
retrieving revision 1.6.2.42
diff -u -F^f -r1.6.2.42 views_bookmark.module
--- views_bookmark.module	25 Jan 2008 21:02:22 -0000	1.6.2.42
+++ views_bookmark.module	28 Jan 2008 00:18:36 -0000
@@ -645,12 +645,6 @@ function views_bookmark_views_tables() {
         ),
       ),
       'fields' => array(
-        'vbid' => array(
-          'name' => t('Bookmark: Ops for @s', array('@s' => $bookmark->title)),
-          'handler' => 'views_bookmark_field_handler_ops',
-          'query_handler' => 'views_bookmark_qhandler_ops',
-          'vbid' => $bookmark->vbid,
-        ),
         'timestamp' => array(
           'name' => t('Bookmark: @s Marked Time', array('@s' => $bookmark->title)),
           'sortable' => TRUE,
@@ -722,20 +716,22 @@ function views_bookmark_views_tables() {
     );
     $tables["views_bookmark_users_$bookmark->vbid"] = $table;
 
-    $table = array(
-      'name' => 'views_bookmarks', 
-      'provider' => 'views_bookmark',
-      'join' => array(
-        'left' => array(
-          'table' => 'views_bookmark_nodes_$bookmark->vbid', // pseudo
-          'field' => 'vbid'
-        ), 
-        'right' => array(
-          'field' => 'vbid'
-        ), // no need for extra because the table it links through already has that
-      ),
-    );
-    $tables["views_bookmarks_$bookmark->vbid"] = $table;
+    // This table seems to have never been used.
+    //
+    // $table = array(
+    //   'name' => 'views_bookmarks', 
+    //   'provider' => 'views_bookmark',
+    //   'join' => array(
+    //     'left' => array(
+    //       'table' => 'views_bookmark_nodes_$bookmark->vbid', // pseudo
+    //       'field' => 'vbid'
+    //     ), 
+    //     'right' => array(
+    //       'field' => 'vbid'
+    //     ), // no need for extra because the table it links through already has that
+    //   ),
+    // );
+    // $tables["views_bookmarks_$bookmark->vbid"] = $table;
 
     $table = array(
       'name' => 'views_bookmark_nodetypes', 
@@ -790,6 +786,40 @@ function views_bookmark_views_tables() {
       ),
     );
     $tables["views_bookmark_node_count_$bookmark->vbid"] = $table;   
+
+    $table = array(
+      'name' => 'views_bookmark_nodes',
+      'join' => array(
+        'left' => array(
+          'table' => 'node',
+          'field' => 'nid',
+        ), 
+        'right' => array(
+          'field' => 'nid',
+        ),
+        'extra' => array(
+          'vbid' => $bookmark->vbid,
+          'uid' => '***CURRENT_USER***',
+          // Note: since this is a LEFT JOIN, we also get records where
+          // uid is empty; that is, nodes which haven't been bookmarked.
+          // This is intentional, as we want to display the Ops field
+          // for unbookmarked nodes too.
+          // The Ops field handler utilizes uid being empty (NULL) to 
+          // efficiently figure out whether or not a node is bookmarked.
+        ),
+      ),
+      'fields' => array(
+        'ops' => array(
+          'field' => 'uid',
+          'name' => t('Bookmark: Ops for @s', array('@s' => $bookmark->title)),
+          'help' => t('Display an AJAX link to bookmark, or unbookmark, the node. Note that the operation is made on behalf of the user who <em>browses the page</em> and not the user whose name happens to appear adjacent to the link.'),
+          'handler' => 'views_bookmark_field_handler_ops',
+          'query_handler' => 'views_bookmark_query_handler_ops',
+          'vbid' => $bookmark->vbid,
+        ),
+      ),
+    );
+    $tables["views_bookmark_ops_$bookmark->vbid"] = $table;
   }
 
   return $tables;
@@ -812,31 +842,36 @@ function view_bookmark_filter_list_vbid(
  */
 function views_bookmark_field_handler_ops($fieldinfo, $fielddata, $value, $data) {
   $vbid = $fieldinfo['vbid'];
-  $type_field = 'views_bookmark_nodetypes_' . $vbid . '_type';
-  if (!$data->$type_field) {
+
+  $node_type_field = 'views_bookmark_nodetypes_'. $vbid .'_type';
+  if (!$data->$node_type_field) {
+    // bookmark does not apply to this node.
+    return;
+  }
+
+  $bookmarks = views_bookmark_get_bookmarks(NULL, $GLOBALS['user']);
+  if (!isset($bookmarks[$vbid])) {
+    // bookmark does not apply to this user.
     return;
   }
-  $table = "views_bookmarks_$vbid";
+  $bookmark = $bookmarks[$vbid];
 
   if (module_exists('token')) {
     $node = node_load($data->nid);
-    foreach ($data as $field => $value) {
-      if (strpos($field, $table) === 0) {
-        $data->$field = token_replace($value, $type = 'node', $node);
-      }
-    }
+    $bookmark->mark = token_replace($bookmark->mark, $type = 'node', $node);
+    $bookmark->mark_long = token_replace($bookmark->mark_long, $type = 'node', $node);
+    $bookmark->unmark = token_replace($bookmark->unmark, $type = 'node', $node);
+    $bookmark->unmark_long = token_replace($bookmark->unmark_long, $type = 'node', $node);
   }
 
-  $mark = $table . "_mark";
-  $mark_long = $mark . "_long";
-  $unmark = $table . "_unmark";
-  $unmark_long = $unmark . "_long";
-
-  $mark_html = l($data->$mark, "views_bookmark/mark/$data->nid/$vbid", array('class' => "views-bookmark-mark links_bookmark_$vbid", 'title' => $data->$mark_long), "destination=$_GET[q]");
-  $unmark_html = l($data->$unmark, "views_bookmark/unmark/$data->nid/$vbid", array('class' => "views-bookmark-unmark links_bookmark_$vbid", 'title' => $data->$unmark_long), "destination=$_GET[q]");
+  $mark_html = l($bookmark->mark, "views_bookmark/mark/$data->nid/$vbid", array('class' => "views-bookmark-mark links_bookmark_$vbid", 'title' => $bookmark->mark_long), "destination=$_GET[q]");
+  $unmark_html = l($bookmark->unmark, "views_bookmark/unmark/$data->nid/$vbid", array('class' => "views-bookmark-unmark links_bookmark_$vbid", 'title' => $bookmark->unmark_long), "destination=$_GET[q]");
 
   views_bookmark_add_js($data->nid, $vbid, $mark_html, $unmark_html);
 
+  // The value of this field is NULL if there isn't a record for this
+  // node in the 'views_bookmark_nodes' table. That is, value is NULL if
+  // this node isn't bookmarked.
   if ($value) {
     return $unmark_html;
   }
@@ -846,20 +881,17 @@ function views_bookmark_field_handler_op
 }
 
 /**
- * handler that makes sure the right fields are available for a bookmark,
- * because the actual link text is completely variable.
+ * This handler loads the type of the node so the display handler, above,
+ * can determine if the bookmark applies to it.
  */
-function views_bookmark_qhandler_ops($field, $fieldinfo, &$query) {
-  $bookmark = views_bookmark_get_bookmark($fieldinfo['vbid']);
+function views_bookmark_query_handler_ops($field, $fieldinfo, &$query) {
+  $vbid = $fieldinfo['vbid'];
 
-  // Add the fields so that they get aliased just like normal fields
-  // in order to prevent accidental collisions.
-  $query->add_field('type', "views_bookmark_nodetypes_$bookmark->vbid", "views_bookmark_nodetypes_$bookmark->vbid"  . "_type");
-  $table = "views_bookmarks_$bookmark->vbid";
-  $query->add_field('"' . db_escape_string($bookmark->mark) . '"', '', $table . "_mark");
-  $query->add_field('"' . db_escape_string($bookmark->mark_long) . '"', '', $table . "_mark_long");
-  $query->add_field('"' . db_escape_string($bookmark->unmark) . '"', '', $table . "_unmark");
-  $query->add_field('"' . db_escape_string($bookmark->unmark_long) . '"', '', $table . "_unmark_long");
+  // Load the type of the node.
+  // I could simply do $query->add_field('type', 'node', 'node_type') and get
+  // rid of this pseudo table, defined in hook_views_tables(), but I suspect
+  // that it will be easier to port to Views 2 if we don't hardcode the 'node'.
+  $query->add_field('type', "views_bookmark_nodetypes_$vbid", "views_bookmark_nodetypes_$vbid" .'_type');
 }
 
 /**
@@ -1004,8 +1036,8 @@ function views_bookmark_views_default_vi
         'sortable' => '1',
       ),
       array (
-        'tablename' => "views_bookmark_nodes_$bookmark->vbid",
-        'field' => 'vbid',
+        'tablename' => "views_bookmark_ops_$bookmark->vbid",
+        'field' => 'ops',
         'label' => 'Ops',
       ),
     );
Index: views_bookmark.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views_bookmark/views_bookmark.install,v
retrieving revision 1.2.2.13
diff -u -F^f -r1.2.2.13 views_bookmark.install
--- views_bookmark.install	25 Jan 2008 21:02:22 -0000	1.2.2.13
+++ views_bookmark.install	28 Jan 2008 00:18:39 -0000
@@ -298,11 +298,19 @@ function views_bookmark_update_7() {
   return $ret;
 }
 
+function views_bookmark_update_5100() {
+  // (code moved to 5101.)
+  return array();
+}
+
 /**
  * Update all views that use the 'views_bookmark_nodes_N.uid' field to use
  * the 'views_bookmark_users_N.name' one. See http://drupal.org/node/211112
+ *
+ * Update all views that use the 'views_bookmark_nodes_N.vbid' field to use
+ * the 'views_bookmark_ops_N.ops' one. See http://drupal.org/node/213488
  */
-function views_bookmark_update_5100() {
+function views_bookmark_update_5101() {
   $ret = array();
   // Ensure views is available.
   include_once(drupal_get_path('module', 'views') .'/views.module');
@@ -317,8 +325,9 @@ function views_bookmark_update_5100() {
   while ($view = db_fetch_object($result)) {
     $view = views_load_view($view->vid);
     $views[$view->name] = $view;
-    // Check if this view uses a 'views_bookmark_nodes_N.uid' field.
     foreach ($view->field as $delta => $field) {
+
+      // Check if this view uses a 'views_bookmark_nodes_N.uid' field.
       if (strpos($field['tablename'], 'views_bookmark_nodes_') === 0 && $field['field'] == 'uid') {
         // If so, change it to use 'views_bookmark_users_N.name' instead.
         $view->field[$delta]['tablename'] = str_replace('_nodes_', '_users_', $field['tablename']);
@@ -326,6 +335,16 @@ function views_bookmark_update_5100() {
         // Put the updated message in the return array.
         $ret[] = array('success' => TRUE, 'query' => t('The view %name has been updated to use the <em>views_bookmark_users_N.name</em> field', array('%name' => $view->name)));
       }
+
+      // Check if this view uses a 'views_bookmark_nodes_N.vbid' field.
+      if (strpos($field['tablename'], 'views_bookmark_nodes_') === 0 && $field['field'] == 'vbid') {
+        // If so, change it to use 'views_bookmark_ops_N.ops' instead.
+        $view->field[$delta]['tablename'] = str_replace('_nodes_', '_ops_', $field['tablename']);
+        $view->field[$delta]['field'] = 'ops';
+        // Put the updated message in the return array.
+        $ret[] = array('success' => TRUE, 'query' => t('The view %name has been updated to use the <em>views_bookmark_ops_N.ops</em> field', array('%name' => $view->name)));
+      }
+
     }
     _views_save_view($view);
   }
@@ -335,10 +354,17 @@ function views_bookmark_update_5100() {
   $default_views_warnings = array();
   foreach ($default_views as $view) {
     foreach ($view->field as $delta => $field) {
+
       // Check if this view uses a 'views_bookmark_nodes_N.uid' field.
       if (strpos($field['tablename'], 'views_bookmark_nodes_') === 0 && $field['field'] == 'uid') {
         $default_views_warnings[] = t('%name needs the %field field updated.', array('%name' => $view->name, '%field' => $field['id']));
       }
+
+      // Check if this view uses a 'views_bookmark_nodes_N.vbid' field.
+      if (strpos($field['tablename'], 'views_bookmark_nodes_') === 0 && $field['field'] == 'vbid') {
+        $default_views_warnings[] = t('%name needs the %field field updated.', array('%name' => $view->name, '%field' => $field['id']));
+      }
+
     }
   }
 
