=== modified file 'planet.info'
--- planet.info	2009-03-01 02:54:23 +0000
+++ planet.info	2009-03-13 08:51:04 +0000
@@ -1,6 +1,7 @@
 ; $Id: planet.info,v 1.2 2007/05/30 03:22:01 daryl Exp $
 name = Planet
 description = Planet blog aggregator
+; TODO better module definition, including specificity if possible.
 package = Community - optional
 version = 6.x
 core = 6.x

=== modified file 'planet.install'
--- planet.install	2009-03-01 03:00:14 +0000
+++ planet.install	2009-03-13 08:46:18 +0000
@@ -10,37 +10,43 @@
     'description' => t('The base table for planet.'),
     'fields' => array(
       'fid' => array(
-        'description' => t('The primary identifier for a planet_feeds table.'),  
+        'description' => t('Primary Key: Unique identifier for a planet RSS feed.'),  
         'type' => 'serial',
         'unsigned' => TRUE,
         'not null' => TRUE,
       ),
       'uid' => array(        
+        'description' => t('Foreign key to {users}.uid . Identifies user who choose the feed.'),  
         'type' => 'int',
         'unsigned' => 1,
         'not null' => FALSE,
       ),
       'title' => array(        
         'type' => 'varchar',
+        'description' => t('Title of the feed.'),  
         'length' => 50,
         'not null' => TRUE,
       ),
       'link' => array(        
         'type' => 'varchar',
+        'description' => t('URL to the feed'),  
         'length' => 80,
         'not null' => TRUE,
       ),
       'image' => array(
+        'description' => t('An image representing the feed'),  
         'type' => 'varchar',
         'length' => 120,
         'not null' => FALSE,
       ),
       'checked' => array(        
+        'description' => t('Last time feed was checked for new items, as Unix timestamp'),  
         'type' => 'int',
         'not null' => FALSE,
       ),
       'frozen' => array(        
-        'type' => 'int',        
+          // TODO: add field description        'description' => t(''),
+          'type' => 'int',        // TODO change to boolean when supported        
         'not null' => TRUE,
         'default' => 0,
       ),
@@ -52,7 +58,7 @@
     'description' => t('contain feed id and its corresponding nid'),
     'fields' => array(
       'id' => array(
-        'description' => t('The primary identifier for a planet_items table'),
+        'description' => t('Primary key: Unique identifier for a planet feed item'),
         'type' => 'serial',
         'unsigned' => 1,
         'not null' => TRUE,
@@ -91,11 +97,9 @@
 /**
  * Implementation of hook_install()
  *
- * This will automatically install the database tables for the planet module for MySQL.
+ * This will automatically install the database tables for the planet
+ * module, using Drupal's data abstraction layer.
  *
- * If you are using another database, you will have to install the tables by hand, using the queries below as a reference.
- *
- * 
  */
 
 function planet_install() {
@@ -106,9 +110,9 @@
 /**
  * Implementation of hook_uninstall()
  *
- * This will automatically uninstall the database tables for the planet module for MySQL.
+ * Uninstalls planet module by removing its own database tables, nodes 
+ * and persistent variables.
  * 
- *  
  */
 
 function planet_uninstall() {

=== modified file 'planet.module'
--- planet.module	2009-03-08 19:00:05 +0000
+++ planet.module	2009-03-13 21:27:34 +0000
@@ -3,7 +3,13 @@
 
 /**
  * @file
- * The planet module
+ * The planet module.
+ *
+ * Planet is an aggregator that allows you to aggregate the blogs for
+ * users in a given role (e.g. staff) and associate content with the
+ * users rather than as a detached feed. This provides the benefit of
+ * showing avatars with content, providing per-user aggregation of
+ * planet content in addition to blog content, etc.
  * 
  */
 
@@ -33,6 +39,7 @@
       $output .= '<li><strong>General Settings</strong>. The role to select bloggers from lets you narrow the user list for when you\'re adding a feed and associating it with a user. A common setting will be to create a staff role and use this for planet.</li>';
       $output .= '<li><strong>Feeds</strong>. This section lets you add a new feed. Give it a title, select an author, provide the feed url, and you\'re off. You\'ll have to manually refresh it or wait for a cron run for items to be imported.</li>';
       $output .= '<li><strong>Feeds</strong>. This section lists current feeds, when they were last updated, how many items they have, and it allows you to edit, refresh, or freeze them. Freezing is a quick way to temporarily suspend updates from the given feed.</li>';
+      $output .= '</ul>';
       return $output;
     case 'admin/modules#description':
       return t('Aggregates RSS feeds and faciliates their association with site users who belong to a given role.');
@@ -41,8 +48,10 @@
 
 function planet_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) {
   if ($page === true && variable_get('planet_redirect_page', 0) == 1) {
-    $obj = db_fetch_object(db_query('SELECT * FROM {planet_items} WHERE nid = %d', $node->nid));
-    if ($obj->nid == $node->nid && $obj->link != '') {
+    $obj = db_fetch_object(db_query('SELECT link FROM {planet_items} WHERE nid = %d', $node->nid));
+    // if the query succeeds, $obj->nid == $node->nid , otherwise, $obj==FALSE,
+    // only 'link' field is used, so I restricted the query 
+    if ($obj && $obj->link != '') {
       header('Location: '. $obj->link);
       exit;
     }
@@ -128,6 +137,10 @@
   return $items;
 }
 
+
+/**
+ * Page callback for 'admin/settings/planet/refresh/%' ("planet refresh")
+ */
 function planet_call_refresh() {  
   $title = planet_refresh();
   watchdog('planet', 'Feed "'. $title .'" refreshed.');
@@ -135,6 +148,9 @@
   drupal_goto('admin/settings/planet');
 }
 
+/**
+ * Page callback for 'admin/settings/planet/(un|)freeze/%' ("planet freeze")
+ */
 function planet_toggle_frozen() {
   
   $fid = intval(arg(4));
@@ -144,53 +160,47 @@
 }
 
 
-function planet_user_feeds() {
-global $user;
-if ($_POST) {  
-    $edit = $_POST;
-    if ($_POST['op'] == 'Delete' && intval($edit['fid']) > 0) {
+/**
+ * Deletes a feed and related items
+ * @param $fid the feed identifier key (integer)
+ */
+function planet__drop_feed($fid) {
       $result = db_query('SELECT nid FROM {planet_items} WHERE fid = %d', intval($edit['fid']));
       while ($node = db_fetch_object($result)) {
         $nodes[$node->nid] = TRUE;
       }
-      return drupal_get_form('planet_multiple_delete_confirm', $nodes, intval($edit['fid']), 'user/'. $user->uid .'/planet');
-    }
-    else if ($_POST['op'] == 'Delete all' && $_POST['confirm'] == 1) {
-      $edit['fid'] = intval(arg(3));
+      return drupal_get_form('planet_multiple_delete_confirm', $nodes, 
+                             intval($edit['fid']), 'user/'. $user->uid .'/planet');
+}
+
+/**
+ * Page callback for 'user/%user/planet' ("Planet Feeds")
+ */
+function planet_user_feeds() {
+  global $user;
+  if ($_POST) {  
+    $edit = $_POST;
+    $fid = intval($edit['fid']);
+    if (($_POST['op'] == 'Delete') && ($fid != 0)) {
+      return planet__drop_feed($fid);
+    }  else if ($_POST['op'] == 'Delete all' && $_POST['confirm'] == 1) {      
+      $edit['fid'] = intval(arg(3)); // @deprecated arg()
       $edit['redirect'] = 'user/'. $user->uid .'/planet';
       return drupal_get_form('planet_multiple_delete_confirm_submit', $edit);
-    }
-    else {    
-      if (isset($edit['fid']) && intval($edit['fid']) == 0) {
-        db_query('INSERT INTO {planet_feeds} (uid, title, link, image, checked, frozen) VALUES(%d, "%s", "%s", "%s", 0, 0)', $user->uid, $edit['title'], $edit['link'], $edit['image']);
-	$edit_r = db_fetch_array(db_query('SELECT fid FROM {planet_feeds} WHERE uid = %d AND title = "%s" AND link = "%s"', $user->uid, $edit['title'], $edit['link']));
-	$title = planet_refresh(intval($edit_r['fid']));
-        drupal_set_message('Added new feed: ' . $title);    
-      }
-      else if ($edit['fid'] && intval($edit['fid']) > 0) {            
-        db_query('UPDATE {planet_feeds} SET uid = %d, title="%s", link = "%s", image="%s" WHERE fid=%d', $user->uid, $edit['title'], $edit['link'], $edit['image'], $edit['fid']);
-        drupal_set_message('Edited "'. $edit['title'] .'" feed.');      
-      }
-      else {
-        if ($edit['planet_author_roles']) {            
-          variable_set('planet_author_roles', $edit['planet_author_roles']);
-        }
-	if ($edit['planet_filter_formats']) {
-	  variable_set('planet_filter_formats', $edit['planet_filter_formats']);
-	}
-        if ($edit['planet_redirect_page'] == 1) {
-          variable_set('planet_redirect_page', $edit['planet_redirect_page']);
+    } else {    
+      if (isset($edit['fid'])) {
+        if (intval($edit['fid']) == 0) {
+          planet__add_feed($edit);
+        } else {
+          planet__update_feed($edit);
         }
-        else {
-          variable_del('planet_redirect_page');
-        }
-        drupal_set_message('Edited general planet settings.');              
+      } else {
+          planet__update_vars($edit);
       }      
     }  
     drupal_goto('user/'. $user->uid .'/planet');  
-  }
-  else {    
-    $fid = intval(arg(3));
+  }  else { // no $_POST    
+    $fid = intval(arg(3));      // @deprecated: arg()
     if ($fid > 0) {      
       $edit = db_fetch_array(db_query('SELECT * FROM {planet_feeds} WHERE fid = %d', $fid));
       $output .= drupal_get_form('planet_feed_form', $edit, true, $user);
@@ -199,32 +209,100 @@
     
       $output .= drupal_get_form('planet_feed_form', $edit, false, $user);
     
-     // $result = db_query('SELECT *, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds}');
-      $result = db_query('SELECT COUNT(f.fid) cnt, f.*, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds} f LEFT OUTER JOIN {planet_items} i ON i.fid = f.fid WHERE f.uid = %d GROUP BY f.fid;', $user->uid);
+      $output .= '<h2>Feeds</h2>';
+      $output .= planet__build_feeds_table1();
+    }
+    print theme('page', $output);    
+  }
+}
+
+// Note: I use 'planet__' prefix to name internal (private) functions
+// TODO: apply the same naming convention (this one or another) in whole module
+/**
+ * TODO merge with planet__build_feeds_table()
+ */
+function planet__build_feeds_table1() {
+  global $user;
+      $feeds = db_query('SELECT  fid, title, checked FROM {planet_feeds} '
+                        . ' WHERE uid = %d;', $user->uid);
       $rows = array();
       $headers = array('Feed', 'Items', 'Edit', 'Last checked');
-      while ($feed = db_fetch_object($result)) {
-        $checked = intval($feed->_checked / 60) .' minutes';
-        if ($feed->_checked % 60 > 0) {
+      $now = time();
+      $items_statement = 'SELECT count(*) FROM {planet_items}'
+        . ' WHERE fid=%d';
+      // TODO: change this to prepared statement when support by drupal DB abastraction layer.
+      while ($feed = db_fetch_object($feeds)) {
+        $_checked = $now - $feed->checked;
+        $checked = intval($_checked / 60) .' minutes';
+        if ($_checked % 60 > 0) {
           $checked .= ', '. $feed->_checked % 60 .' seconds';
         }
         $checked .= ' ago';
+        $items = db_query($items_statement, $feed->fid);
+        if (!$items) trigger_error('ERROR while counting feed items.');
+        $cnt = db_result($items);
         array_push($rows, array(
           $feed->title,
-          $feed->cnt,
+          $cnt,
           l('edit', 'user/'. $user->uid .'/planet/'. intval($feed->fid)),
           $checked,
           )
         );
       }
-      $output .= '<h2>Feeds</h2>';
-      $output .= theme('table', $headers, $rows);      
-    }
-    print theme('page', $output);    
-  }
+      return theme('table', $headers, $rows);      
 }
 
+/**
+ * Adds a new feed to planet_feeds table.
+ * @param $data associative array with keys 
+ *        'uid' (optional), 'title', 'link', 'image' (optional)
+ */
+function planet__add_feed($data) {
+  $data['checked'] = 0;
+  $data['frozen']  = 0;
+  $rslt = drupal_write_record('planet_feeds', $data);
+  if ($rslt!=SAVED_NEW) trigger_error('Failed to add new feed');
+  $title = planet_refresh(intval($data['fid']));
+  drupal_set_message('Added new feed: ' . $title);    
+}
 
+/**
+ * Updates an existing feed in planet_feeds table.
+ * @param $data associative array with keys 
+ *        'fid' (mandatory, primary key), 
+ *         other fields as needed:
+ *        'uid', 'title', 'link', 'image', 'checked', 'frozen'
+ */
+function planet__update_feed($data) {
+  $rslt = drupal_write_record('planet_feeds', $data, 'fid');
+  if ($rslt!=SAVED_UPDATED) trigger_error('Failed to edit feed');
+  drupal_set_message('Edited "'. $data['title'] .'" feed.');
+}      
+
+/**
+ * Updates an planet settings persistent variables.
+ * @param $data associative array with all optional keys 
+ *        'planet_author_roles', 'planet_filter_formats',
+ *        'planet_redirect_page'.
+ */
+function planet__update_vars($data) {
+  if ($edit['planet_author_roles']) {            
+    variable_set('planet_author_roles', $edit['planet_author_roles']);
+  }
+  if ($edit['planet_filter_formats']) {
+    variable_set('planet_filter_formats', $edit['planet_filter_formats']);
+  }
+  if ($edit['planet_redirect_page'] == 1) {
+    variable_set('planet_redirect_page', $edit['planet_redirect_page']);
+  } else {
+    variable_del('planet_redirect_page');
+  }
+  drupal_set_message('Edited general planet settings.');              
+}
+
+/**
+ * Page callback for 'admin/settings/planet' ("Planet Settings")
+ */
 function _planet_settings() {
   if ($_POST) {  
     $edit = $_POST;
@@ -241,37 +319,23 @@
       $edit['redirect'] = 'admin/settings/planet';
       return drupal_get_form('planet_multiple_delete_confirm_submit', $edit);
     }
-    else {    
-      if (isset($edit['fid']) && intval($edit['fid']) == 0) {
-        db_query('INSERT INTO {planet_feeds} (uid, title, link, image, checked, frozen) VALUES(%d, "%s", "%s", "%s", 0, 0)', $edit['uid'], $edit['title'], $edit['link'], $edit['image']);
-        $edit_r = db_fetch_array(db_query('SELECT fid FROM {planet_feeds} WHERE uid = %d AND title = "%s" AND link = "%s"', $edit['uid'], $edit['title'], $edit['link']));
-        $title = planet_refresh(intval($edit_r['fid']));
-        drupal_set_message('Added new feed: ' . $title);    
-      }
-      else if ($edit['fid'] && intval($edit['fid']) > 0) {            
-        db_query('UPDATE {planet_feeds} SET uid = %d, title="%s", link = "%s", image="%s" WHERE fid=%d', $edit['uid'], $edit['title'], $edit['link'], $edit['image'], $edit['fid']);
-        drupal_set_message('Edited "'. $edit['title'] .'" feed.');      
-      }
-      else {
-        if ($edit['planet_author_roles']) {            
-          variable_set('planet_author_roles', $edit['planet_author_roles']);
-        }
-	if ($edit['planet_filter_formats']) {
-	  variable_set('planet_filter_formats', $edit['planet_filter_formats']);
-	}
-        if ($edit['planet_redirect_page'] == 1) {
-          variable_set('planet_redirect_page', $edit['planet_redirect_page']);
-        }
-        else {
-          variable_del('planet_redirect_page');
-        }
-        drupal_set_message('Edited general planet settings.');              
+    else { 
+      if (isset($edit['fid'])) {
+        if (intval($edit['fid']) == 0) {
+          planet__add_feed($edit);
+        } else {
+          planet__update_feed($edit);
+        }
+      } else {
+        // TODO if user needs to click separately for each fieldset,
+        //  why not using different forms ?
+        // or conversely, allow setting everything at once ?
+        planet__update_vars($edit);
       }      
     }  
     drupal_goto('admin/settings/planet');  
-  }
-  else {    
-    $fid = intval(arg(3));
+  } else {    
+    $fid = intval(arg(3)); // @deprecated arg()
     if ($fid > 0) {      
       $edit = db_fetch_array(db_query('SELECT * FROM {planet_feeds} WHERE fid = %d', $fid));
       $output .= drupal_get_form('planet_feed_form', $edit, true);
@@ -279,38 +343,49 @@
     else {
     
       $output .= drupal_get_form('planet_settings_form');  
-      //$output .= drupal_get_form('settings', $form);
-      //$output .= $form;
 
       $output .= drupal_get_form('planet_feed_form', $edit);
     
-     // $result = db_query('SELECT *, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds}');
-      $result = db_query('SELECT COUNT(f.fid) cnt, f.*, (UNIX_TIMESTAMP(NOW()) - checked) _checked FROM {planet_feeds} f LEFT OUTER JOIN {planet_items} i ON i.fid = f.fid GROUP BY f.fid;');
-      $rows = array();
-      $headers = array('Feed', 'Items', 'Edit', 'Last checked', 'Refresh', 'Freeze');
-      while ($feed = db_fetch_object($result)) {
-        $checked = intval($feed->_checked / 60) .' minutes';
-        if ($feed->_checked % 60 > 0) {
-          $checked .= ', '. $feed->_checked % 60 .' seconds';
-        }
-        $checked .= ' ago';
-        array_push($rows, array(
-          $feed->title,
-          $feed->cnt,
-          l('edit', 'admin/settings/planet/'. intval($feed->fid)),
-          $checked,
-          l('refresh', 'admin/settings/planet/refresh/'. intval($feed->fid)),
-          l($feed->frozen ? 'unfreeze' : 'freeze', 'admin/settings/planet/'. ($feed->frozen ? 'unfreeze/' : 'freeze/') . intval($feed->fid))          
-          )
-        );
-      }
       $output .= '<h2>Feeds</h2>';
-      $output .= theme('table', $headers, $rows);      
+      $output .= planet__build_feeds_table();
     }
     print theme('page', $output);    
   }
 }
 
+function planet__build_feeds_table() {
+  global $user;
+  $feeds = db_query('SELECT  fid, title, checked, frozen FROM {planet_feeds} '
+                    . ' WHERE uid = %d;', $user->uid);
+  $rows = array();
+  $headers = array('Feed', 'Items', 'Edit', 'Last checked', 'Refresh', 'Freeze');
+  $now = time();
+  $items_statement = 'SELECT count(*) FROM {planet_items} WHERE fid=%';
+  // TODO: change this to prepared statement when supported by drupal DB Abstraction Layer.
+  while ($feed = db_fetch_object($feeds)) {
+    $_checked = $now - $feed->checked;
+    $checked = intval($_checked / 60) .' minutes';
+    if ($_checked % 60 > 0) {
+      $checked .= ', '. $feed->_checked % 60 .' seconds';
+    }
+    $checked .= ' ago';
+    $items = db_query($items_statement, $feed->fid);
+    if (!$items) trigger_error('ERROR while counting feed items.');
+    $cnt = db_result($items);
+    $fid = strval($feed->fid);
+    array_push($rows, array(
+                            $feed->title,
+                            $cnt,
+                            l('edit', 'admin/settings/planet/'. $fid),
+                            $checked,
+                            l('refresh', 'admin/settings/planet/refresh/'. $fid),
+                            l($feed->frozen ? 'unfreeze' : 'freeze', 'admin/settings/planet/'. ($feed->frozen ? 'unfreeze/' : 'freeze/') . $fid)          
+                            )
+               );
+  }
+  return theme('table', $headers, $rows);      
+}
+
 function planet_multiple_delete_confirm(&$form_state, $nodes, $fid, $redirect) {
   $form_state['values']['fid'] = $fid;
   $form_state['values']['redirect'] = $redirect;
@@ -1229,10 +1304,16 @@
       }
       //print '<pre>'. print_r($entry, 1) .'</pre>';
       node_save($entry);
-      db_query('INSERT INTO {planet_items} (fid, nid, guid, link, created) VALUES(%d, %d, "%s", "%s", UNIX_TIMESTAMP(NOW()))', $feed->fid, $entry->nid, $guid, $link);              
+      $item_record = array('fid' => $feed->fid,
+                           'nid' => $entry->nid,
+                           'guid'=> $guid,
+                           'link' =>$link,
+                           'created' => time());
+      drupal_write_record('planet_items', $item_record);
       watchdog('planet', 'Adding '. $title);
       drupal_set_message('Adding '. $title);
     }  
+    // TODO split this huge function
   }
 
   return $items_added;
@@ -1333,6 +1414,9 @@
   }
 }
 
+/**
+ * Page callback for 'planet' ("Planet")
+ */
 function planet_page_last() {
   global $user;
 
@@ -1351,6 +1435,9 @@
   print theme('page', $output);
 }
 
+/**
+ * Page callback for 'planet/feed' ("Planet")
+ */
 function planet_feed() {
   $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'planet' AND n.status = 1 ORDER BY n.created DESC"), 0, 15);
   $title = db_fetch_array(db_query("SELECT link_title FROM {menu_links} WHERE link_path = 'planet'"));
@@ -1409,6 +1496,9 @@
   }
 }
 
+/**
+ * Page callback for 'planet/%' ("planet")
+ */
 function planet_page_user($uid) {
   global $user;
 

