--- UPGRADE.txt	Sun Jan 22 17:35:30 2006
+++ UPGRADE.txt	Sun Jan 22 17:35:30 2006
--- README.txt	Sun May 01 12:10:35 2005
+++ README.txt	Sun May 01 12:10:35 2005
--- LICENSE.txt	Sun Apr 23 03:54:26 2006
+++ LICENSE.txt	Sun Apr 23 03:54:26 2006
--- INSTALL.txt	Thu Oct 04 09:19:53 2007
+++ INSTALL.txt	Thu Oct 04 09:19:53 2007
--- freelinking.module	Thu Oct 04 09:19:53 2007
+++ freelinking.module	Tue Jan 15 15:15:36 2008
@@ -32,30 +32,24 @@
 function freelinking_page($thetitle = NULL) {
   if ($thetitle) { // find the matching title
     $freelink = _freelinking_make_link($thetitle);
-    drupal_goto($freelink['path'], isset($freelink['args']) ? $freelink['args'] : '');
+    drupal_goto($freelink['path'], $freelink['args']);
   }
   else { // no title was passed -- show a list of wikiwords and status
     $header = array('phrase', 'target');
-    $query = "SELECT phrase, path FROM {freelinking} ORDER BY phrase";
+    $query = 'SELECT phrase, nid FROM {freelinking} ORDER BY phrase';
     $result = db_query($query);
     $i = 0;
-    while ($freelink = db_fetch_object($result)) { // looping through phrase, target pairs
+    while ($freelink = db_fetch_object($result)) { // looping through phrase/nid pairs
       $rows[$i][] = urldecode($freelink->phrase);
-      if (preg_match('/^(http|mailto|https|ftp):/', $freelink->path)) { // an absolute link
-        $rows[$i][] = '<a class="freelink" href="' . $freelink->path . '">' . $flpair->path . '</a>';
-      }
-      else { // a freelink
-        $fltargetnid = _freelinking_exists($freelink->phrase);
-        $freelink = _freelinking_make_link($freelink->phrase);
-        if ($fltargetnid) {
-          $link = l(t('see this content'), drupal_get_path_alias('node/' . $fltargetnid));
+      if ($freelink->nid) {
+        $link = l(t('See this content'), drupal_get_path_alias('node/'. $freelink->nid));
         }
         else { // content not found, show link to create
-          $link = '<a href=' . url($freelink['path'], $freelink['args']) . '>' . t('create this content') . '</a>';
+        $freelink = _freelinking_make_link($freelink->phrase);
+        $link = l(t('Create this content'), $freelink['path'], array('query' => $freelink['args']));
         }
         $rows[$i][] = $link;
-      }
-      $i++;
+      $i = $i + 1;
     }
     if (isset($rows)) {
       return theme('table', $header, $rows);
@@ -86,14 +80,14 @@
         '#maxlength' => 60,
         '#description' => t('Title of the block that shows freelinked phrases without content.')
       );
-      for ($i = 5; $i <=30; $i=$i+5) {
+      for ($i = 5; $i <= 30; $i += 5) {
         $options[$i] = $i;
       }
       $form['freelinking_block_options']['freelinking_blocknum'] = array(
         '#title' => t('Number of non-existing link phrases to show'),
         '#type' => 'select',
         '#options' => $options,
-        '#default_value' => variable_get('freelinking_blocknum', '10'),
+        '#default_value' => variable_get('freelinking_blocknum', 10),
         '#description' => t('Number of phrases to show in the block.')
       );
       return $form;
@@ -102,89 +96,82 @@
     case 'view':
       switch ($delta) {
         case 0:
-          $query = 'SELECT * FROM {freelinking} WHERE path LIKE "%node/add%" ORDER BY RAND()';
-          $result = db_query($query);
-          $i = 0;
-          $content = '';
+          $query = 'SELECT phrase FROM {freelinking} WHERE nid = 0 ORDER BY RAND() LIMIT %d';
+          $result = db_query($query, variable_get('freelinking_blocknum', 10));
+
+          $items = array();
           while ($freelink = db_fetch_object($result)) {
-            if ($i == variable_get('freelinking_blocknum', 10)) { // we're done
-              break;
+            $items[] = l(urldecode($freelink->phrase), 'freelinking/'. urldecode($freelink->phrase));
             }
-            $items[] = l(urldecode($freelink->phrase), $freelink->path, array(), $freelink->args);
-            $i++;
-          } // endwhile looping through flpairs
+          
           $block['subject'] = variable_get('freelinking_blocktitle', 'Create This Content');
           $block['content'] = theme('item_list', $items);
+          
           return $block;
         default:
           break;
-      } // endswitch $delta
+      }
     default:
       break;
   } // endswitch $op
 } // endfunction freelinking_block
 
 function freelinking_settings() {
-  $notfoundoptions = array(
-    'create only' => t('Only try to create content'),
-    'no access search' => t('Search for content if user can\'t create'),
-    'always search' => t('Always search for content'),
-  );
-  $form["freelinking_nodetype"] = array(
+  $form['freelinking_nodetype'] = array(
     '#title' => t('Default for new content'),
     '#type' => 'select',
     '#options' => node_get_types('names'),
-    '#default_value' => variable_get("freelinking_nodetype", 'story'),
+    '#default_value' => variable_get('freelinking_nodetype', 'story'),
     '#description' => t('Type of content that the freelinking filter will create when clicking on a freelink without a target.')
   );
   $form['freelinking_notfound'] = array(
     '#title' => t('What to do if content not found'),
     '#type' => 'select',
-    '#options' => $notfoundoptions,
+    '#options' => array(
+      'create only' => t('Only try to create content'),
+      'no access search' => t('Search for content if user can\'t create'),
+      'always search' => t('Always search for content'),
+    ),
     '#default_value' => variable_get('freelinking_notfound', 'no access search'),
     '#description' => t('What to do when clicking on a freelink without a target. Choose to always attempt to create the content, search if the user doesn\'t have permission to create (the default), or to always search. NOTE: search functions require search.module to be activated.'),
   );
 
-  $form["freelinking_restriction"] = array(
+  $form['freelinking_restriction'] = array(
     '#title' => t('Restrict free links to this content type'),
     '#type' => 'select',
     '#options' => array_merge(array('none' => t('No restrictions')), node_get_types('names')),
-    '#default_value' => variable_get("freelinking_restriction", 'none'),
+    '#default_value' => variable_get('freelinking_restriction', 'none'),
     '#description' => t('If desired, you can restrict the freelinking title search to just content of this type. Note that if it is not the same as the "Default for new content," above, new freelinked content cannot be found.')
   );
-  $form["freelinking_camelcase"] = array(
+  $form['freelinking_camelcase'] = array(
     '#title' => t('Allow CamelCase linking'),
     '#type' => 'checkbox',
-    '#default_value' => variable_get("freelinking_camelcase", 0) == 0 ? TRUE : FALSE,
+    '#default_value' => variable_get('freelinking_camelcase', 0),
     '#description' => t('If desired, you can enable CamelCase linking')
   );
-  $form["freelinking_onceonly"] = array(
+  $form['freelinking_onceonly'] = array(
     '#title' => t('Only link first occurance'),
     '#type'  => 'checkbox',
-    '#default_value' => variable_get("freelinking_onceonly", 0) == 1 ? TRUE : FALSE,
+    '#default_value' => variable_get('freelinking_onceonly', 0),
     '#description' => t('If desired you can only turn the first occurance of a freelink into a link. This can improve the appearance of content that includes a lot of the same CamelCase words.')
   );
 
   return system_settings_form($form);
 }
 
-
 function freelinking_filter($op, $delta = 0, $format = -1, $text = '') {
   switch ($op) {
     case 'list':
       return (array(0 => t('freelinking filter')));
       break;
 
-    case 'name':
-      return t('freelinking filter');
-      break;
-    
     case 'description':
       return t('Enables freelinking between nodes with CamelCase or delimiters like [[ and ]].');
       break;
 
     case 'process':
-      return _freelinking_do_filtering($text, FALSE);
+      $wikiwords = _freelinking_find_freelinks($text);
+      return _freelinking_do_filtering($text, $wikiwords, arg(1));
       break;
 
     case 'prepare':
@@ -196,11 +183,21 @@
 
 function freelinking_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
   switch ($op) {
-    case 'update':
-      _freelinking_do_filtering($node->body, TRUE);
+    case 'delete': // Make sure we clear the freelinking DB when a node is deleted
+    
+      // If this node was a freelink target, clear it out
+      _freelinking_store($node->title, 0);
+      
+      // Cleanup relationship this node had with freelinks
+      _freelinking_update_freelinks(array(), $node->nid);
       break;
     case 'insert':
-      _freelinking_do_filtering($node->body, TRUE);
+      // Update the DB so that this page, if represented by a freelink, is stored
+      _freelinking_store($node->title, $node->nid);
+    case 'update':
+      // Update the DB for all contained freelinks for being attached to this node
+      $wikiwords = _freelinking_find_freelinks($node->body);
+      _freelinking_update_freelinks($wikiwords['internal'], $node->nid);
       break;
   } // endswitch $op
 } // endfunction freelinking_nodeapi
@@ -231,8 +228,12 @@
   return t($output);
 }
 
+/**
+ * Check that this is a new node we're adding and if an edit variable
+ * from freelinking is found, set the title to that value
+ */
 function freelinking_form_alter(&$form, $form_state, $form_id) {
-  if (isset($form['type'])) {
+  if (isset($form['type']) && arg(1) == 'add' && isset($_GET['edit'])) {
     $type = $form['type']['#value'];
     if (variable_get('freelinking_nodetype', 'story') == $type && $_GET['edit']) { // on the right node type, with GET data
       $form['title']['#default_value'] = urldecode($_GET['edit']['title']); // prepopulate the title field
@@ -249,94 +250,204 @@
  *
 */
 
-function _freelinking_do_filtering($text, $store = FALSE) {
-  $allowcamelcase = variable_get("freelinking_camelcase", TRUE);
-  $freelinkingregexp = '/\[\[.+]]/U'; // this finds [[links like this]], un-greedily
+function _freelinking_do_filtering($text, $wikiwords, $nid) {
+  
+  // Find all freelinks attached to this node that don't have
+  // have a node
+  $qry = db_query('SELECT phrase FROM {freelinking_node_rel} WHERE nid = %d', $nid);
+  $lack_nodes = array();
+  while ($o = db_fetch_object($qry)) {
+    $lack_nodes[$o->phrase] = true;
+  }  
+  
+  // Handle external links
+  foreach ($wikiwords['external'] as $wikiword => $data) {
+    $replacement = l($wikiword, $data['text']?$data['text']:$wikiword, array('attributes' => array('class' => 'freelinking external')));
+    $text = str_replace($data['orig_text'], $replacement, $text);
+  }
+  
+  // Handle internal links
+  foreach ($wikiwords['internal'] as $wikiword => $data) {
+    $class = 'freelinking';
+    
+    // Add another class for freelinks that don't have nodes
+    if (array_key_exists($wikiword, $lack_nodes)) {
+      $class .= ' nonexistent';
+    }
+    
+    $replacement = l($data['text']?$data['text']:urldecode($wikiword), 'freelinking/'. $wikiword, array('attributes' => array('class' => $class)));
+    $text = str_replace($data['orig_text'], $replacement, $text);
+  }
+  
+  return $text;
+}
+
+/**
+ * Returns an array of both internal and external links. These
+ * links are represented by key, text, and orig_text.
+ */
+function _freelinking_find_freelinks($text) {
+  $freelinkingregexp = '/\[\[(.+)]]/U'; // this finds [[links like this]], un-greedily
   preg_match_all($freelinkingregexp, $text, $flmatches);
-  if ($allowcamelcase) {
+  if (variable_get('freelinking_camelcase', TRUE)) {
      $camelcaseregexp = '/\b([[:upper:]][[:lower:]]+){2,}\b/'; // this gets us close, but is not perfect. Example: ThisIsACamelCaseWord won't match (two caps in a row)
      preg_match_all($camelcaseregexp, $text, $ccmatches);
-     $wikiwords = array_merge($ccmatches[0], $flmatches[0]);
+    $wikiwords = array($flmatches[0] + $ccmatches[0], $flmatches[1] + $ccmatches[1]);
   }
   else {
-     $wikiwords = $flmatches[0];
+    $wikiwords = $flmatches;
+  }
+  
+  // Sort freelinks into internal and external lists of links
+  // Links are represented by key, text, and orig_text
+  $nice_array = array(
+    'internal' => array(),
+    'external' => array()
+  );
+
+  for ($i=0;$i<count($wikiwords[1]);$i++) {
+    $wikiword = $wikiwords[1][$i];
+    // If this is a dual-freelink, split it up into correct pieces
+    if (strpos($wikiword, '|')) {
+      list($freelink, $phrase) = explode('|', $wikiword);
   }
-  foreach (array_unique($wikiwords) as $wikiword) {
-    if (substr($wikiword, 0, 2) == '[[') { // if it's a freelink, the expressions are different
-      $phrase = substr($wikiword, 2, -2);
-      $freelink = $phrase;
-      $barpos = strpos($phrase, '|');
-      $pattern = '/\[\[' . preg_quote($phrase,'/') . ']]/';
-      if ($barpos) {
-         $freelink = substr($freelink, 0, $barpos);
-         $phrase = substr($phrase, $barpos + 1);
+    else {
+      $phrase = $wikiword;
+      $freelink = '';
       }
+    
+    // Sort into external and internal arrays
       if (preg_match('/^(http|mailto|https|ftp):/', $freelink)) {
-         $replacement = '<a class="freelinking external" href="' . $freelink . '">' . $phrase . '</a>';
+      $nice_array['external'][$phrase] = array('text' => $freelink, 'orig_text' => $wikiwords[0][$i]);
       }
       else {
-        $replacement = l($phrase, 'freelinking/' . rawurlencode($freelink), array('class' => 'freelinking'));
+      $nice_array['internal'][urlencode($phrase)] = array('text' => $freelink, 'orig_text' => $wikiwords[0][$i]);
+    }
+  }
+
+  return $nice_array;
       }
+
+/**
+ * Checks all freelinks found in a node and updates them in the DB,
+ * whether that means adding or deleting their relationship
+ * 
+ * @param $nid The node ID which these wikiwords are IN
+ */
+function _freelinking_update_freelinks($wikiwords, $nid) {
+  
+  // Grab all the freelinks that had been attached to this node
+  $qry = db_query('SELECT phrase FROM {freelinking_node_rel} WHERE nid = %d', $nid);
+  $old_freelinks = array();
+  while ($o = db_fetch_object($qry)) {
+    $old_freelinks[] = $o->phrase;
+  }
+  
+  // Get all the freelinks that are now in this node
+  $new_freelinks = array_keys($wikiwords);
+
+  // For all the old relationships that don't still exist, remove them
+  $relationships_to_remove = array_diff($old_freelinks, $new_freelinks);
+  if (!empty($relationships_to_remove)) {
+    db_query('DELETE FROM {freelinking_node_rel} WHERE nid = %d AND phrase IN ("%s")', $nid, implode('","', $relationships_to_remove));
+
+    // Cleanup any phrases orphaned by their relationship removal
+    // First start with all relationships we found we need to remove...
+    $qry = db_query('SELECT phrase, COUNT(1) AS count FROM {freelinking_node_rel} WHERE phrase IN ("%s") GROUP BY phrase', implode('","', $relationships_to_remove));
+    $freelinks_to_remove = $relationships_to_remove;
+    while ($o = db_fetch_object($qry)) {
+      // ...and then remove freelinks that still have relationships...
+      unset($freelinks_to_remove[array_search($o->phrase, $freelinks_to_remove)]);
     }
 
-    else if ($allowcamelcase) { // it's a CamelCase, expressions are a bit simpler
-      $pattern = '/\b' . $wikiword . '\b(?![^<]*>)/';
-      $phrase = $wikiword; // consistency for the db
-      $freelink = $wikiword; // also for the db
-      $replacement = l($wikiword, 'freelinking/' . urlencode($wikiword));
+    // ...and delete those that no longer have any relationships
+    if (!empty($freelinks_to_remove)) {
+      db_query('DELETE FROM {freelinking} WHERE phrase IN ("%s")', implode('","', $relationships_to_remove));
     }
-    $text = preg_replace($pattern, $replacement, $text, variable_get("freelinking_onceonly", 0) ? 1 : -1);
     
-    if ($store) {
-      _freelinking_store($freelink, $replacement);
     }
-  } // foreach wikiword
-  return $text;
-} // endfunction _freelinking_do_filtering
 
-function _freelinking_store($phrase, $path, $args=NULL) { // store freelinking pair in the db
-  $hash = md5($phrase . $path . $args);
-  $query = "SELECT hash FROM {freelinking} WHERE phrase = '%s'";
+  // For all the new relationships that didn't already exist, add them
+  $relationships_to_add = array_diff($new_freelinks, $old_freelinks);
+  if (!empty($relationships_to_add)) {
+    $sql = 'INSERT INTO {freelinking_node_rel} (phrase, nid) VALUES';
+    $args = array();
+    foreach ($relationships_to_add as $phrase) {
+      $sql .= (!empty($args)?',':'') .' ("%s", %d)';
+      $args[] = $phrase;
+      $args[] = $nid;
+    }
+    db_query($sql, $args);
+  }
+  
+  // Grab all freelinks that exist for wikiwords found
+  $qry = db_query('SELECT phrase, nid FROM {freelinking} WHERE phrase IN ("%s")', $nid, implode('","', $relationships_to_add));
+  $real_links = array();
+  while ($o = db_fetch_object($qry)) {
+    $real_links[] = $o->phrase;
+  }
+  
+  // For each freelink not declared in the DB, add it
+  $freelinks_to_add = array_diff($new_freelinks, $real_links);
+  if (!empty($freelinks_to_add)) {
+    $sql = 'INSERT INTO {freelinking} (phrase, nid) VALUES';
+    $args = array();
+    foreach ($freelinks_to_add as $phrase) {
+      $sql .= (!empty($args)?',':'') .' ("%s", %d)';
+      $args[] = $phrase;
+      $args[] = 0;
+    }
+    db_query($sql, $args);
+  }
+}
+
+/**
+ * 
+ * @param $insert Used for when updating of a row is required and not generation
+ * of new rows
+ */
+function _freelinking_store($phrase, $nid, $insert = TRUE) { // store freelinking pair in the db
+  $phrase = urlencode($phrase);
+  
+  // Search for the phrase
+  $query = 'SELECT nid FROM {freelinking} WHERE phrase = "%s"';
   $result = db_query($query, $phrase); 
-  $num_rows = FALSE;
-  while ($dbobj = db_fetch_object($result)) {
-    $num_rows = TRUE;
-    $dbhash = $dbobj;
-  }
-  if ( !$num_rows) { // not in the db
-    $query = "INSERT INTO {freelinking} (hash, phrase, path, args) VALUES ('%s', '%s', '%s', '%s')";
-    $result = db_query($query, $hash, $phrase, $path, $args);
-  } // endif row not found in table
-  else { // in the db, but does it match?
-    if ($dbhash->hash != $hash) { // hashes don't match, replace db entry with new values
-      $query = "UPDATE {freelinking} SET hash = '%s', path = '%s', args = '%s' WHERE phrase = '%s'";
-      $result = db_query($query, $hash, $path, $args, $phrase);
-    } // endif hashes don't match
-  } // endifelse row found
-} // endfunction _freelinking_store
+  $freelink_nid = db_result($result);
+
+  // Only update DB if nids differ for this phrase
+  if ($freelink_nid !== FALSE && $freelink_nid != $nid) {
+    $query = 'UPDATE {freelinking} SET nid = %d WHERE phrase = "%s"';
+    db_query($query, $nid, $phrase);
+  }
+}
 
 function _freelinking_exists($thetitle) { // helper function for freelinking_page
   // looks through the db for nodes matching $title. Returns the nid if such a node exists, otherwise, returns 0
   $title = urldecode($thetitle);
-  $query = "SELECT nid FROM {node} WHERE title = '%s'";
+  $query = 'SELECT nid FROM {node} WHERE title = "%s"';
   $noderestrict = variable_get('freelinking_restriction', 'none');
   if ($noderestrict != 'none') { // need to add the where clause
-    $query .= " AND type = '%s'";
-    $result = db_query($query, $title, $noderestrict);
+    $query .= ' AND type = "%s"';
+    $result = db_query($query .' LIMIT 1', $title, $noderestrict);
   }
   else { // no restriction. query is fine but db_query doesn't need the extra argument
-    $result = db_query($query, $title);
+    $result = db_query($query .' LIMIT 1', $title);
   }
-// FIXME ***
-  while ($node = db_fetch_object($result)) { // only one, I hope... what if there's more than one?
+  
+  $nid = 0;
+  if ($node = db_fetch_object($result)){
     $nid = $node->nid;
   }
-  return (empty($nid) ? 0 : $nid);
+  return $nid;
 }
 
 
-function _freelinking_make_link($thetitle) { // helper function for freelinking_page
+function _freelinking_make_link($thetitle) { // helper function or freelinking_page
   global $user;
+  
+  // Create a default array to prevent key lookup misses
+  $freelink = array('path' => '', 'args' => '');
+  
   // Returns a link to a node named $thetitle if found, or a link to new content otherwise.
   $nid = _freelinking_exists($thetitle); 
   if ($nid) { // the node exists, set the path to go there
@@ -346,12 +457,12 @@
     switch (variable_get('freelinking_notfound', 'no access search')) {
       case 'create only':
         $freelink['path'] = 'node/add/' . variable_get('freelinking_nodetype', 'story');
-        $freelink['args'] = 'edit[title]=' . $thetitle;
+        $freelink['args'] = 'edit[title]='. urlencode($thetitle);
         break;
       case 'no access search':
         if (node_access('create', variable_get('freelinking_nodetype', 'story'))) {
           $freelink['path'] = 'node/add/' . variable_get('freelinking_nodetype', 'story');
-          $freelink['args'] = 'edit[title]=' . $thetitle;
+          $freelink['args'] = 'edit[title]='. urlencode($thetitle);
         }
         else {
           $freelink['path'] = 'search/node/' . $thetitle;
@@ -360,10 +471,7 @@
       case 'always search':
         $freelink['path'] = 'search/node/' . $thetitle;
         break;
-    } // endswitch notfound options
   }
-  _freelinking_store($thetitle, $freelink['path'], isset($freelink['args']) ? $freelink['args'] : '');
+  }
   return $freelink;
-} // endfunction _freelinking_make_link
-
-// vim: tw=300 nowrap syn=php
+}
--- freelinking.install	Thu Oct 04 09:19:53 2007
+++ freelinking.install	Tue Jan 15 17:25:37 2008
@@ -1,75 +1,187 @@
 <?php
 
-function freelinking_install() {
+function freelinking_schema() {
+  $schema = array();
 
-  switch ($GLOBALS['db_type']) {
-    case 'mysql':
-    case 'mysqli':
-      db_query('CREATE TABLE {freelinking} (
-                   hash   CHAR(32)     NOT NULL,
-                   phrase VARCHAR(200) NOT NULL,
-                   path   VARCHAR(200) NOT NULL,
-                   args   VARCHAR(200) NOT NULL, 
-                   PRIMARY KEY(hash))
-                TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;');
-      break;
-    case 'pgsql':
-      db_query('CREATE TABLE {freelinking} (
-                  hash   CHAR(32)     NOT NULL,
-                  phrase VARCHAR(200) NOT NULL,
-                  path   VARCHAR(200) NOT NULL,
-                  args   VARCHAR(200) NOT NULL,
-                  PRIMARY KEY(hash));');
-      break;
+  $schema['freelinking'] = array(
+    'fields' => array(
+      'phrase' => array(
+        'type' => 'varchar',
+        'length' => 200,
+        'not null' => TRUE
+      ),
+      'nid' => array(
+        'type' => 'int',
+        'size' => 'normal',
+        'not null' => TRUE,
+        'default' => 0
+      )
+    ),
+    'primary key' => array('phrase'),
+    'index' => array('nid')
+  );
+
+  $schema['freelinking_node_rel'] = array(
+    'fields' => array(
+      'phrase' => array(
+        'type' => 'varchar',
+        'length' => 200,
+        'not null' => TRUE
+      ),
+      'nid' => array(
+        'type' => 'int',
+        'size' => 'normal',
+        'not null' => TRUE,
+        'default' => 0
+      )
+    ),
+    'primary key' => array('phrase', 'nid'),
+    'index' => array('phrase')
+  );
+  return $schema;
     }
-} // endfunction freelinking_install
-
-function freelinking_update_1() {
-  $ret = array();
-  switch ($GLOBALS['db_type']) {
-    case 'mysql':
-    case 'mysqli':
-      $ret[] = update_sql('ALTER TABLE {freelinking} DROP PRIMARY KEY');
-      break;
-    case 'pgsql':
-      $ret[] = update_sql('ALTER TABLE {freelinking} DROP CONSTRAINT {freelinking}_pkey');
-      break;
-  } // endswitch on db type
-
-  $ret[] = _system_update_utf8(array('freelinking'));
-
-  return $ret;
-};
-
-function freelinking_update_2() { // this is the update to the 4.7 version
-  $ret = array();
 
-  switch ($GLOBALS['db_type']) {
-    case 'mysql':
-    case 'mysqli':
-      $ret[] = update_sql('ALTER TABLE {freelinking} ADD COLUMN hash CHAR(32)');
-      $ret[] = update_sql('ALTER TABLE {freelinking} ADD COLUMN path VARCHAR(200)');
-      $ret[] = update_sql('ALTER TABLE {freelinking} ADD COLUMN args VARCHAR(200)');
-      $ret[] = update_sql('UPDATE      {freelinking} SET path = target');
-      $ret[] = update_sql('UPDATE      {freelinking} SET hash = MD5(CONCAT(phrase, path))');
-      $ret[] = update_sql('ALTER TABLE {freelinking} DROP COLUMN target');
-      $ret[] = update_sql('ALTER TABLE {freelinking} ADD PRIMARY KEY hash (hash)');
-      break;
-
-    case 'pgsql':
-      $ret[] = update_sql('ALTER TABLE {freelinking} DROP COLUMN target');
-      db_add_column($ret, 'freelinking', 'hash', 'char(32)');
-      db_add_column($ret, 'freelinking', 'path', 'varchar(200)');
-      db_add_column($ret, 'freelinking', 'args', 'varchar(200)');
-      $ret[] = update_sql('ALTER TABLE {freelinking} ADD PRIMARY KEY hash');
-      break;
-  } // endswitch db_table
-  return $ret;
+function freelinking_install() {
+  drupal_install_schema('freelinking');
 }
 
 function freelinking_uninstall() {
   drupal_uninstall_schema('freelinking');
+  variable_del('freelinking_restriction');
+  variable_del('freelinking_notfound');
+  variable_del('freelinking_nodetype');
+  variable_del('freelinking_blocktitle');
+  variable_del('freelinking_blocknum');
+  variable_del('freelinking_camelcase');
+  variable_del('freelinking_onceonly');
 }
 
-// vim: tw=300 nowrap syn=php
-?>
+/**
+ * First update to prepare for 6.x compatibility
+ * and this version
+ */
+function freelinking_update_6000() {
+  $ret = array();
+  /*
+  // Alter 'freelinking' table
+  db_drop_primary_key($ret, 'freelinking');
+  db_drop_field($ret, 'freelinking', 'hash');
+  db_drop_field($ret, 'freelinking', 'args');
+  $int_field = array(
+    'type' => 'int',
+    'size' => 'normal',
+    'not null' => TRUE,
+    'default' => 0
+  );
+  db_add_field($ret, 'freelinking', 'nid', $int_field);
+  
+  // Remove all external links
+  db_query('DELETE FROM {freelinking} WHERE path LIKE "%%freelinking external%%"');
+  
+  // Update old entries to new format
+  $qry = db_query('SELECT phrase FROM {freelinking} WHERE path NOT LIKE "node/add/%%"');
+  while ($o = db_fetch_object($qry)) {
+    // If freelink has a node attached to it, attach it
+    if ($nid = _freelinking_exists($o->phrase)) {
+      db_query('UPDATE {freelinking} SET nid = %d WHERE phrase = "%s"', $nid, $o->phrase);
+    }
+  }
+  db_drop_field($ret, 'freelinking', 'path');
+  db_add_primary_key($ret, 'freelinking', array('phrase'));
+  db_add_index($ret, 'freelinking', 'nid', array('nid'));
+  
+  // Create new 'freelinking_node_rel' table
+  $freelinking_node_rel = array(
+    'fields' => array(
+      'phrase' => array(
+        'type' => 'varchar',
+        'length' => 200,
+        'not null' => TRUE
+      ),
+      'nid' => array(
+        'type' => 'int',
+        'size' => 'normal',
+        'not null' => TRUE,
+        'default' => 0
+      )
+    ),
+    'primary key' => array('phrase', 'nid')
+  );
+  db_create_table($ret, 'freelinking_node_rel', $freelinking_node_rel);
+  
+  // Fill freelinking_node_rel table
+  // Filter query down to only relevant node types
+  $sql = 'SELECT n.nid, nr.body FROM {node} n INNER JOIN {node_revisions} nr ON nr.nid = n.nid WHERE';
+  $args = array();
+  if (($rest = variable_get('freelinking_restriction', 'none')) != 'none') {
+    $sql .= ' n.type = "%s"';
+    $args[] = $rest;
+  }
+  else {
+    $sql .= ' 1';
+  }
+  $qry = db_query($sql, $args);
+  while ($o = db_fetch_object($qry)) {
+    $wikiwords = _freelinking_find_freelinks($o->body);
+    _freelinking_update_freelinks($wikiwords['internal'], $o->nid);
+  }
+  */
+  
+  // Delete the old table
+  db_drop_table($ret, 'freelinking');
+  
+  // Just create the tables again since updating is difficult
+  $freelink_table = array(
+    'fields' => array(
+      'phrase' => array(
+        'type' => 'varchar',
+        'length' => 200,
+        'not null' => TRUE
+      ),
+      'nid' => array(
+        'type' => 'int',
+        'size' => 'normal',
+        'not null' => TRUE,
+        'default' => 0
+      )
+    ),
+    'primary key' => array('phrase'),
+    'index' => array('nid')
+  );
+  $freelinking_node_rel_table = array(
+    'fields' => array(
+      'phrase' => array(
+        'type' => 'varchar',
+        'length' => 200,
+        'not null' => TRUE
+      ),
+      'nid' => array(
+        'type' => 'int',
+        'size' => 'normal',
+        'not null' => TRUE,
+        'default' => 0
+      )
+    ),
+    'primary key' => array('phrase', 'nid'),
+    'index' => array('phrase')
+  );
+  db_create_table($ret, 'freelinking', $freelink_table);
+  db_create_table($ret, 'freelinking_node_rel_table', $freelinking_node_rel_table);
+  
+  // Refill the freelinking tables
+  $sql = 'SELECT n.nid, nr.body FROM {node} n INNER JOIN {node_revisions} nr ON nr.nid = n.nid WHERE';
+  $args = array();
+  if (($rest = variable_get('freelinking_restriction', 'none')) != 'none') {
+    $sql .= ' n.type = "%s"';
+    $args[] = $rest;
+  }
+  else {
+    $sql .= ' 1';
+  }
+  $qry = db_query($sql, $args);
+  while ($o = db_fetch_object($qry)) {
+    $wikiwords = _freelinking_find_freelinks($o->body);
+    _freelinking_update_freelinks($wikiwords['internal'], $o->nid);
+  }
+  return $ret;
+}
--- freelinking.info	Thu Oct 04 09:25:04 2007
+++ freelinking.info	Thu Oct 04 09:25:04 2007
--- CHANGELOG.txt	Sun Jan 22 17:35:30 2006
+++ CHANGELOG.txt	Sun Jan 22 17:35:30 2006
