tagging: Unify the clickable tag link generation.
authorMatthijs Kooijman <matthijs@stdin.nl>
Fri, 12 Mar 2010 14:35:35 +0000 (15:35 +0100)
committerMatthijs Kooijman <matthijs@stdin.nl>
Fri, 12 Mar 2010 20:47:01 +0000 (21:47 +0100)
This ensures that clicking a tag anyhere on the page does the same (adds
or removes it from the current filter, depending on if it was in there
already).

This also ensures that both url and HTML escaping is consistently
applied to the generated links, preventing a duplicate escaping of
&amp; that could occur in $current_filter before. It now makes use of
blosxom_html_escape instead of encoding only &.

xtaran/tagging

index f6167e0373484c0ffd90e3dc0ce668e5469e0619..988f3229df56f33e02650ab308c700a74e4bf05c 100644 (file)
@@ -290,9 +290,7 @@ sub story {
     $tag_list = '';
     my %other_stories = ();
     foreach my $tag (sort { lc($a) cmp lc($b) } keys %localtags) {
-       my $l_tag = &url_escape($tag);
-       $tag_list .= 
-           qq! <a href="$base_url{$link_tag}$l_tag" rel="tag">$tag</a>,!;
+       $tag_list .= " " . make_tag_link($link_tag, $tag, (rel => "tag")) . ",";
 
 #      $tag_list .= qq! <a href="$base_url{blosxom}$tag&-technorati-hack=/$tag" rel="tag" title="Look for tag $tag in this blog"!.($invisible_plugin_tags ? qq! style="display:none;"! : '').qq!>$tag</a>! if $add_plugin_tags;
 
@@ -411,8 +409,6 @@ sub filter {
     }
 
     my $diff = $max - $min;
-    my $conj = ($filter_conj eq 'and' ? '&-conj=and' : '');
-    my $l_filter_tags = &url_escape($filter_tags);
 
     foreach my $tag (sort { lc($a) cmp lc($b) } keys %tags) {
        next if grep { $_ eq $tag } @tag_cloud_blacklist;
@@ -429,15 +425,8 @@ sub filter {
        $style .= qq!font-size: $tag_percent%;! if $show_tag_no_by_size && $diff;
        $style .= qq!color: #$color;! if $show_tag_no_by_color && $diff;
 
-       my $l_tag = &url_escape($tag);
-       $global_tag_list .= 
-           qq| <a href="$base_url{$link_cloud}|.
-            ((($link_cloud eq 'blosxom') and 
-              ($filter_tags !~ /(^|,)\Q$tag\E($|,)/) and
-              $filter_tags) ?
-             "$l_filter_tags," : '').
-            qq|$l_tag$conj" title="$title" style="$style">$tag</a>|.
-           qq|$tag_no_display,\n|;
+       $global_tag_list .= make_tag_link($link_cloud, $tag, (title => $title, style => $style)).
+                           qq|$tag_no_display,\n|;
     }
 
     $global_tag_list =~ s/,$//;
@@ -454,7 +443,7 @@ sub filter {
       FILES:
        foreach my $file (@$files) {
            # If all tags should match
-           if ($conj) {
+           if ($filter_conj eq 'and') {
                foreach my $ctag (@tags) {
                    if (!grep { $_ eq $file } @{$tags{$ctag}}) {
                        next FILES;
@@ -468,25 +457,18 @@ sub filter {
 
     %$files_ref = %localfiles;
 
-    $current_filter_short = join($conj ? ' + ' : ' | ',
-                                map { s/\&/\&amp;/g; $_; } 
-                                sort { lc($a) cmp lc($b) } 
-                                @tags);
+    $current_filter_short = blosxom::blosxom_html_escape(
+                              join($filter_conj eq 'and' ? ' + ' : ' | ',
+                                  sort { lc($a) cmp lc($b) } @tags
+                           ));
 
-    $conj = ($conj ? 
+    my $l_filter_tags = &url_escape($filter_tags);
+    $conj = ($filter_conj eq 'and' ? 
             qq! <em><a href="$base_url{blosxom}$l_filter_tags">and</a></em> ! : 
             qq! <em><a href="$base_url{blosxom}$l_filter_tags&amp;-conj=and">or</a></em> !);
     $current_filter = ($current_filter_prefix.
                       join($conj,
-                           map {
-                               my $tags = $filter_tags;
-                               $tags =~ s/\Q$_,\E// || $tags =~ s/\Q,$_\E// || $tags =~ s/\Q$_\E//;
-
-                               s/\&/\&amp;/g; 
-
-                               my $l_tags = &url_escape($tags);
-                               qq!<a href="$base_url{blosxom}$l_tags">$_</a>!;
-                           } 
+                           map { make_tag_link('blosxom', $_); } 
                            sort { lc($a) cmp lc($b) } 
                            @tags).
                       $current_filter_suffix);
@@ -500,12 +482,11 @@ sub filter {
                          keys %related_tags) {
            next if ((grep { $_ eq $rtag } @related_tags_tag_blacklist) or
                     $related_tags{$rtag} < $min_tag_relations);
-           my $l_rtag = &url_escape($rtag);
            my $rel_no = $show_tag_shares ? " ($related_tags{$rtag})" : '';
-           $related_tags .= 
-               qq!<a href="$base_url{$link_rtag}$l_rtag" rel="tag" class="$related_tag_class" title="Coincided $related_tags{$rtag} times">$rtag</a>$rel_no$related_tag_join!;
+           $related_tags .= make_tag_link($link_rtag, $rtag, (rel => "tag", class => $related_tag_class, title => "Coincided $related_tags{$rtag} times")).
+                            "$rel_no$related_tag_join";
            last if $i++ >= $max_related_tags;
-           }
+       }
        $related_tags =~ s/\Q$related_tag_join\E$//;
 
        #use Data::Dumper;
@@ -521,6 +502,47 @@ sub filter {
     1;
 }
 
+# Create the url for a given tag. Depending on the tag and link type given,
+# this adds to, removes or replaces the current tag list. The link type given
+# is one of the keys of %base_url
+sub make_tag_link {
+    my ($link, $tag, %attrs) = @_;
+    my $filter_tags = CGI::param('-tags');
+    my $conj = (CGI::param('-conj') eq 'and' ? '&-conj=and' : '');
+    # If we're linking to ourselves, the currently selected tag list is not
+    # empty, and this tag is not in there yet, prefix the link with the
+    # current filter list.
+    my $tags;
+    if (($link_cloud eq 'blosxom') and $filter_tags) {
+       if ($filter_tags =~ /(^|,)\Q$tag\E($|,)/) {
+           # The tag is already in there, remove it
+           $tags = $filter_tags;
+           $tags =~ s/\Q,$tag,\E/,/ || $tags =~ s/(^|,)\Q$tag\E($|,)//;
+       } else {
+           # The tag is not in there, add it
+           $tags = "$filter_tags,$tag";
+       }
+       $tags = &url_escape($tags);
+       $tags .= $conj;
+    } else {
+       # We're linking externally, or don't have a filter yet. Just use the
+       # selected tag as the filter
+       $tags = &url_escape($tag);
+    }
+
+    # Set the href attribute
+    $attrs{href} = "$base_url{$link}$tags";
+
+    # Generate attribute values
+    my $attrs = join('',
+                map { $val = blosxom::blosxom_html_escape($attrs{$_});
+                     qq! $_="$val"!;
+               } keys %attrs);
+
+    return "<a$attrs>" . blosxom::blosxom_html_escape($tag) . "</a>";
+}
+
+
 sub color_calc {
     my ($tag_no, $min, $max) = @_;
     my $diff = $max - $min;