Recently my folksonomy, or "free tagging", support has been committed to Drupal HEAD. Since the general public won't see this until Drupal 4.7, and there was a fair amount of "hey! I wanna use this now!", I've backported it to Drupal 4.6. In a nutshell, the core difference is the input method: unlike normal taxonomies which are administratively controlled, a "free tagging" vocabulary allows tag creation when the node is submitted. It does this through a text input box, as opposed to a dropdown or selectbox.

The following patch:

  • Removes the useless "Preview form" of a vocabulary.
  • Alters the vocabulary table to include a new "tags" column.
  • Adds a new "Free tagging" preference on vocabulary creation/editing.
  • Modifies the vocabulary overview to support pagers for free tagging vocabs.

The new code integrates tightly with the existing taxonomy code. The only additional processing occurs on node save and edit, where we parse through the tags associated with a node. All other display (and thus, code) remains the same. The following screenshots illustrate the changes, integration, and workflow:

To install (and this assumes a fair bit of "I've done this before" knowledge):

  1. Login to your Drupal site as the administrator user.
  2. Grab the latest patch from my sandbox.
  3. Install the patch with patch -p0 -u < taxonomy_all_4.6.patch.
  4. Visit update.php in your browser and run the 2005-04-20 update.
  5. Now create/reconfigure a vocab to be "free tagging", then edit/create a node.

There has been some additional work regarding folksonomies with my taxonomy_similar module, but you can go there and check out the screenshots if need be. It sorta assumes you ALREADY have a very large (2000+ terms, easily) vocabulary for its "similarity" magic (English only) to work.

These additions were made during the exploration and customization of Drupal by http://www.NHPR.org. In loving support of open source software, http://www.NHPR.org will continue to contribute code they feel the community will benefit from. Questions about this code should be directed to morbus@disobey.com.

Comments

chrisada’s picture

That's one off my wish list. Thank you so much for this. I wanted this feature so badly I was tempted to use the folksonomy module, but I figured that might give me trouble upgrading to 4.7. And I thought it might come out in core in 4.6.1, something like a month or two away.

Anyway, I'm going to try this this evening and report back if it goes ok.

chrisada’s picture

To sum it up, there was no surprise in the upgrading process, which is always a good thing. The feature works like expected. But I am still doing some soul searching with regards to hierachy vs. free tagging. The few ways of using taxonomy that I am pondering now are:
- 1 main vocab, single level, and 1 free tagging vocab
this was suggested before, and could work quite well. Except I don't like the fact that the two vocabularies are actually the same classification.
- free tagging without hieracy. Just like any other tools out there. It's not the best, but I can (and have) live with that.
- free tagging plus hierachy on a single vocabulary. One will have to spend time putting things into places, but this can be done, say, once a month or once there are too many free floating terms in the system, and not everytime a node is created.

So far I like the last one the best. But is there other ways that could make life easier?

Morbus Iff’s picture

Regarding #1: how are they the same classification? If they're the same classification, why would you need the main vocab at all, especically if it were only "single level" (which is what, from a reader POV, free tags look like)? #1 sounds exactly like #2, with the addition of a "controlled vocab" - what would stop someone from entering "Funny", a controlled vocab term (for example), as ALSO a free tagging term? Would they "mean" the same thing, and/or be displayed as such?

As for #3, I'd say it'd give you the most flexibility out there, but you'd not be able to specify hierachies in the free tagging box (there's been lots of discussions about this already). The hierarchy would only come into play as an administrator (when you're messing with it) and as a reader if you were browsing a tree of all terms (or else, playing around with parent/child relationships in a URL).

My gut reaction is #3: even if it's creaky, it's has the most flexible future. Define "better"?

http://disobey.com/
http://gamegrene.com/

chrisada’s picture

#1 was considered mainly because a pure free-tagging system will slice my site's content into too small grains when users browse the taxonomy. (no tree structure in free-tagging) So the 'main' vocab kind of slot them into the coarser classification.

It is an alternative to #3, should work ok if 2 level of hierachy is enough for a site. And this way, the site admin does not have to get involved or have to assign taxonomy admin privilege to users.

I'll probably be using #3 for my personal site, and #1 for the few sites I look after.

syscrusher’s picture

Two things:

  1. Free-tag vocabularies are wonderful for use as the image navigation vocabulary, but you really need to apply this patch and create the image vocabulary before installing image.module, if you can. Otherwise, you need to go into the database manually and toggle the auto-created one from image.module to be a free-tagged one. (It looks as if the latest version of Morbus' patch allows you to do this from the web UI, but I haven't tested this exhaustively. So maybe this is no longer an issue.)
  2. My upcoming mass-import module for images, image_import.module, specifically exploits Morbus' patch if available. I've been working with it a lot and highly recommend it. +1 indeed!

Scott

Morbus Iff’s picture

Regarding #1, yeah, that was a patch that got thrown into HEAD a week or so ago. It's not mine, and it was unintentional to backport that change. I don't think that's a problem though, so I'll just leave it in.

And thanks :)

http://disobey.com/
http://gamegrene.com/

thorpexmachine’s picture

Anybody interested in free tagging in the aggregator module?

The use case in my mind is for shared blogs/aggregators based on drupal where people read news. Tagging them in another way than the predefined categories can help getting what's hot without posting.
Kind of a local technorati but with a limited lifespan (aggregated news are deleted after sometime if I am not wrong).

Other approach would be to enable tagging from the aggregated view, it would automatically post a blog node with the news link in it and propose to add text.
As it is for a multiuser application, the aggregator should be aware of the fact that a news has been already blogged. So if others want to tag the news from the aggregator, they actually modify/add tags to this node and can add a comment.

Just a thought based on how we use RSS feeds and drupal within my company.

moshe weitzman’s picture

there was an effrot a while ago to make nodes out of aggregated items. it was called node_import.module. with this, you could easily free tag RSS items.

that project did not receive all that much support, so it has died.

philoxenia’s picture

I'm having an incredibly hard time patching the file on the server. Would anyone be willing simply to email me the updated taxonomy.module? Or is it posted anywhere?

Thanks,

John

Carl Ditzler’s picture

Need to also do this... I should have something by the end of the weekend, I hope.

mcbrider’s picture

Here is what I am doing:
$ patch -p0 -u < taxonomy_all_4.6.patch

This is what happens:
patching file database/database.mysql
patching file database/database.pgsql
patching file database/updates.inc
Hunk #1 FAILED at 105.
Hunk #2 FAILED at 2365.
2 out of 2 hunks FAILED -- saving rejects to file database/updates.inc.rej
patching file misc/drupal.css
Hunk #1 succeeded at 368 (offset 1 line).
patching file modules/taxonomy.module
Hunk #10 succeeded at 981 (offset 3 lines).
Hunk #11 succeeded at 999 (offset 3 lines).
Hunk #12 succeeded at 1053 (offset 3 lines).
Hunk #13 succeeded at 1071 (offset 3 lines).

Any help would be greatly appreciated!

Anonymous’s picture

Here's an excerpt of my errors:

patch -p0 -u < taxonomy_all_4.6.patch
patching file database/database.mysql
patching file database/database.pgsql
Hunk #1 succeeded at 735 (offset -3 lines).
patching file database/updates.inc
Hunk #1 FAILED at 105.
Hunk #2 succeeded at 2394 (offset 29 lines).
1 out of 2 hunks FAILED -- saving rejects to file database/updates.inc.rej
patching file misc/drupal.css
Hunk #1 succeeded at 368 (offset 1 line).
patching file modules/taxonomy.module
Hunk #10 succeeded at 1121 (offset 3 lines).
Hunk #11 succeeded at 1153 (offset 3 lines).
Hunk #12 succeeded at 1204 (offset 3 lines).
Hunk #13 succeeded at 1222 (offset 3 lines).

And of update.php:

Fatal error: Cannot redeclare update_130() (previously declared in /homepages/20/d88608368/htdocs/kambiz/anthropology/sandbox/database/updates.inc:2370) in /homepages/20/d88608368/htdocs/kambiz/anthropology/sandbox/database/updates.inc on line 2396

Any suggestions what what I can do? Really need this feature badly!

jon@207.210.84.96__jdwatson’s picture

Same error here. Nobody appears to know why?

degerrit’s picture

I had the same problem, but I seemed to fix it as follows *:

1) In the Drupal folder open the file database/updates.inc (using pico, vi, or your favorite editor)

2) underneath the entry
"2005-04-14" => "update_129",
add the following:
"2005-04-20" => "update_130_1",

3) there are probably two functions called update_130, find the one which alters the vocabulary and rename it to update_130_1 (which is what you referenced above)

So it will look like this:

function update_130_1() {
$ret = array();

if ($GLOBALS['db_type'] == 'mysql') {
...

After that, go to update.php. Seems to work for me.

* the .rej file mentioned in the patch-error message contains what failed to be patched, this is the file which basically contains the information needed to fix it (like I did above)

oziumjinx’s picture

I've tried applying this patch through SSH. I've moved to the /modules directory (which is where I uploaded the patch file).

I then entered the command:

Only garbage was found in the patch input.

Am I doing this incorrectly?

Thanks,
-=Vince

Technology White Papers
IT Executive Blogs

Steven Mansour’s picture

Hi, just wondering if there was a quick and dirty (or slow and clean...) way of making individual tag entry during node creation spaces instead of commas... most sites which use tagging use spaces, and not commas.

Thanks!

s.

Morbus Iff’s picture

There's no user-modifiable way, no, though you could certainly modify the regular expression that handles the parsing to accept spaces instead of commas. Commas were used to allow multiword tags such as "bungie jumping" or "horse riding" or "kevin hemenway" as opposed to WikiWordsSyntax. Stylistically within Drupal, commas are also used in profile.module fields with similar intent ("list your interests here")

http://disobey.com/
http://gamegrene.com/

chrisada’s picture

I keep creating new terms where I actually wanted to tag nodes with more than one term. I think

term1 term2 "multi-word term"

is better too.

Steven Mansour’s picture

Something else that would be great would be tag URL aliases... basically, instead of each tag still being "taxonomy/term/45", it would be "tag/puppies".

This would allow anyone to quickly see all terms with a certain tag simply by going to http://site.com/tags/puppies, "just like on" (must love it when people say that...) TagSurf, del.icio.us and Flickr.

Maybe this could actually be done by using some stuff from the pathauto.module?

dykstranet’s picture

I agree, tag URL aliases would be very useful. Also, a dynamic feeds based on items tagged a certain way would be fantastic.

-dykstranet.com

venkat-rk’s picture

awtags does this exactly (www.site.com/tags/puppies), but I am not sure what the status of the module is right now.

Edit: Oops! I think I got it wrong. awtags sure does the kind of urls you mentioned, but I am not sure if they are aliases of taxonomy terms.

Boris Mann’s picture

tagadelic does weighted font size tag cloud thingies.

Pathauto will automatically generate URL aliases for you -- set your tag vocabulary to use tags/[cat] and you're done.

venkat-rk’s picture

Thanks for the pointer. But, where is tagedelic? I couldn't locate it anywhere.

Ian Ward’s picture

Using URL aliases with taxonomy makes OR and AND combos not work. For example, term 1 is planets and term 2 is stars. The normal "AND" url is taxonomy/term/1+2 which will produce your combined view as well as combined RSS feed. However, if you alias terms, you cannot make these pages. (well, you can by using the tids, but using the terms aliases does not work)

Looking at the taxonomy module in the taxonomy_term_page function, it appears the URL is written in this part:

 if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str_tids)) {
    $operator = 'or';
    // The '+' character in a query string may be parsed as ' '.
    $tids = preg_split('/[+ ]/', $str_tids);
  }
  else if (preg_match('/^([0-9]+,)*[0-9]+$/', $str_tids)) {
    $operator = 'and';
    $tids = explode(',', $str_tids);
  }
  else {
    drupal_not_found();
  }  

which is made to work with tids. Has anyone tried making this work for aliased terms?

kovacs’s picture

I tried updating my taxonomy module to use free tagging but it didn't work. It fails on the database/update.inc patch part. Is there a way to attach a file to this posting so I can post my update.inc file?

noid’s picture

Hi kovacs,

Where can I download your 4.6.3 patch? Thanks! :)

jasonwhat’s picture

Before I dig into how I could actually apply this patch, I was wondering if using this patch will complicated the 4.7 upgrade.

Anybody have a patched version of 4.6.3 taxonomy for this they can post or email.

cybe’s picture

seems to work! =)

but update.php complained tjhat it cant create a column named tags (because it already exists) so I had to manually remove the line that created it it from database/updates.inc

Prometheus6’s picture

If you apply this patch to 4.6.x then upgrade to 4.7, ignore the error. Deleting the tags column and reinserting it would essentially convert any freetagging vocabulary into a regular one.

cybe’s picture

I've had to modify he maxlength of the input box to a much larger value since I use ALOT of tags on my nodes.

See http://merlib.org/node/1092/ for instance

freyquency’s picture

I just updated and reapplied the patch to 4.6.4 and there do not seem to be any problems.

kaparo’s picture

Hi,

I added this patch to show a text area with already defined tags, so the user can look at and choose one before introducing new ones.

Replace this code:

      $typed_string = implode(', ', $typed_terms) . (array_key_exists('tags', $terms) ? $terms['tags'][$vocabulary->vid] : NULL);
      $result[] = form_textfield($vocabulary->name, 'taxonomy][tags]['. $vocabulary->vid, $typed_string, 50, 100, t('A comma-separated list of terms describing this content (Example: funny, bungie jumping, "Company, Inc.").'), NULL, ($vocabulary->required ? TRUE : FALSE));

with this one

      $typed_string = implode(', ', $typed_terms) . (array_key_exists('tags', $terms) ? $terms['tags'][$vocabulary->vid] : NULL);
      $result[] = form_textfield($vocabulary->name, 'taxonomy][tags]['. $vocabulary->vid, $typed_string, 50, 100, t('A comma-separated list of terms describing this content (Example: funny, bungie jumping, "Company, Inc.").'), NULL, ($vocabulary->required ? TRUE : FALSE));
      
      // saoma added
      $allTerms = array();
      $children = taxonomy_get_tree($vocabulary->vid);
      foreach ($children as $term) {
        $allTerms[] = $term->name;
      }      
      $result[] = form_textarea(t("Existing ").$vocabulary->name, 
                                  "saoma_all_terms", // add this name to tinymce.module to disable rich-editing on this textarea
                                  implode(', ', $allTerms), 
                                  50, 4, 
                                  t("Existing tags in %voc_name. Before introducing new tags, please look at this list of already defined tags if you can reuse some of them.", array('%voc_name' => $vocabulary->name)),
                                  NULL);

in your patched taxonomy.module.

Cheers :).

Ian Ward’s picture

This sounds great. Do you have a screenshot? I'm imagining something like the way del.icio.us does it?

pjdevries’s picture

Thanx for the patch. It's very usefull indeed. I also see why you want the textarea to be ignored by TinyMCE, but where do I add the "saoma_all_terms"?

By the way, why not use a multiple select listbox (instead of a textarea) from which one can select one or more terms and add them to the textarea? I'm not a good enough Drupal/PHP programmer (yet) to accomplish that myself, but by the looks of your patch, you are. Can you give it a try?

kaparo’s picture

add to this section :)

function theme_tinymce_theme($init, $textarea_name, $theme_name, $is_running) {
  switch ($textarea_name) {
    // Disable tinymce for these textareas

It could be bad in the check box case, if you have hundreds of terms in the vocab ... that's why I came up with the textarea

amanda’s picture

In a PHP Template theme (http://drupal.org/phptemplate) you can call the hook in your "template.php" rather than editing the .module file. The gory details are all here: http://drupal.org/node/11811

pjdevries’s picture

When applying the patch to the Drupal 4.6.5 taxonomy.module, foreign taxonomy vocabularies mysteriously disappear from the categories list. With 'foreign' I mean vocabularies that were created by modules other than the taxonomy module itself, such as the forum module and the userstag module (from GoJoinGo). When putting back the original 4.6.5 taxonomy module, the vocabularies re-appear.

Is this a known side effect of the patch and if so, is there a remedy available?

pjdevries’s picture

I made a small modification to the patched taxonomy module which made the hidden vocabularies re-appear. The problem is introduced by the following condition in function taxonomy_overview():

if ($vocabulary->module == 'taxonomy') {
  .....
  .....
  .....
}

I disabled the if statement and voila, there were my vocabularies again. I'm not sure what the side effects of this modification may be though. Can I do this unpunished?

kae’s picture

note this patch does not work on a civicspace distribution because the databas has a different name. google on civicspace free tagging and you will find that patch. it has a mysql file that you will need to process. I got an error that hunk #13 failed but I checked the line number and it seemed to deal with help text so I thought it may not be crucial.

Right now free tagging seems to be working. know that you have to enable it through administer--categories--add vocabulary (see Robert Douglas book on Drupal)

pjdevries’s picture

Thanks for the comment on CivicSpace, although I can't remember having mentioned using it, which actually I don't :-) I have the distinct feeling that you are refering to Drupal 4.7 though, all the more because you mention Robert Douglas's book on Drupal, which describes Drupal 4.7. My problem with Free Tagging concerns the backported 4.6 patch, which this topic is all about.

kae’s picture

i'm talking about 4.6. i just posted here to let other cs users know.
also, the free tagging patch can be patched in manually if you give it the correct name of the file when it asks.

C-Watootsi’s picture

We've been pondering that question here:

http://civicspacelabs.org/home/node/16593

How are tags actually stored? Will they survive an upgrade on CivicSpace or from 4.6 upwards?

freyquency’s picture

An upgrade to the latest 4.6 release will mean that you will have to attempt to patch this again. I haven't had the chance to try it yet, so i'm not sure if it works or not.

C-Watootsi’s picture

...but what do 4.6/CS users do with the tags that have been created with the patched code? Will there be an update path that keeps this data safe?

freyquency’s picture

If you upgrade to a 4.6.x without the patch you will get multiple select menus instead. Freetagging just adds those terms to a taxonomy through the node/add interface instead of having to administrate a taxonomy. So all of the data is the same, it's just a different way of entering it in.

Does that answer your question?

C-Watootsi’s picture

That's very helpful to know, and answers my question.

Case

amanda’s picture

I am about to dive into this and feeling entirely wiggly about the prospect. Here is what I think understand:

* this patch is still not part of the 4.6.x core, so I do need the patch if I want to use freetagging on any 4.6.x site and specifically on my 4.6.6 site.

* The patch I want is "freetag-4_6_3.patch" from Morbus's sandbox.

* I don't want taxonomy_all.patch or taxonomy_all_5.patch (both from http://drupal.org/node/19697) -- those are old?

The patch appears to patch, among other things, /database/database.mysql -- my table definitions. Is there somewhere, an "alter table" script that I can use if I am trying to get this running on an existing 4.6.6 site? Or is that where update.php comes in?

These feel like dumb questions but I keep reading this page and the discussion of the taxonomy_all.patch files and I find that I am still entirely confused.

Thanks,
Amanda

nathandigriz’s picture

I have been using this on a live intranet site for a few weeks and it works. All the patching has been pre done. the ALTER table sql is in there too.

http://www.hiveminds.co.uk/drupal-4-6-6-taxonomy-module-for-i18n-and-acc...

Evan Leeson’s picture

I didn't see any obvious link to a seperate patch, just a circular clickpath that leads back to this thread. Can you post a link to the CS-specific patch?

I want to be a farmer.

C-Watootsi’s picture

So far as I know. No-one seems able to explain what exactly happens when you try to use this patch on a CS site.

Ariadoss’s picture

Would it be possible to use this code from 4.7 to have auto-completion for the field?:

function taxonomy_autocomplete($vid, $string = '') {
  // The user enters a comma-separated list of tags. We only autocomplete the last tag.
  // This regexp allows the following types of user input:
  // this, "somecmpany, llc", "and ""this"" w,o.rks", foo bar
  $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  preg_match_all($regexp, $string, $matches);
  $array = $matches[1];

  // Fetch last tag
  $last_string = trim(array_pop($array));
  if ($last_string != '') {
    $result = db_query_range("SELECT name FROM {term_data} WHERE vid = %d AND LOWER(name) LIKE LOWER('%%%s%%')", $vid, $last_string, 0, 10);

    $prefix = count($array) ? implode(', ', $array) .', ' : '';

    $matches = array();
    while ($tag = db_fetch_object($result)) {
      $n = $tag->name;
      // Commas and quotes in terms are special cases, so encode 'em.
      if (preg_match('/,/', $tag->name) || preg_match('/"/', $tag->name)) {
        $n = '"'. preg_replace('/"/', '""', $tag->name) .'"';
      }
      $matches[$prefix . $n] = check_plain($tag->name);
    }
    print drupal_to_js($matches);
    exit();
  }
}