00908: Enhance the link parameter of [[PmWiki/page list(s)]] (multiple and exclusions)

Summary: Enhance the link parameter of page list (multiple and exclusions)
Created: 2007-03-28 08:52
Status: Closed, added for 2.3.0
Category: Feature
From: Feral
Priority: 555554444

See Cookbook:PageListMultiTargets for an implementation. --Petko April 14, 2013, at 09:39 AM


Feature request:

Add/allow multiple and exclusions in link parameter of page list, in the same form, style and idea as pagelist's group and name parameters.


Take for instance Category.Skins.
Currently we are limited to listing only backlinks, I.e. link=Category.Skins which is wonderful, however if we have multiple links and exclusions similar to the group and name params, then we gain a lot of power.

For instance, let us presume that we wish to know all of the skins that NEED updating, this then becomes a simple matter of link=Category.Skins,Category.UpdateMe
Or perhaps that do NOT need updating link=Category.Skins,-Category.UpdateMe, etc.

In my work with feralblog2 I am finding such a feature would be REALLY handy for allowing the user to really be able to display what they want to see. In my case currently if we say do NOT want all of the 'blog' related (I.e. tagged) entries, well we are out of luck. An if we wish to know about er stories and fancy cars then we need two separate pagelists, one with link=Category.Stories and another for link=Category.Fancycars. With the above proposed addition we could simply say link=Category.Stories,Category.Fancycars. An in the example of not wanting to see a category, link=-Category.Blog

By allowing group/name style parameters we can do something like link=Category.Stories,-Category.Fancycars, i.e. stories that presumably have nothing to do with fancy cars.

To a small extent we should be able to achieve this via search style "apple -pie", however in regards to categories this is far too limited. As we may mention fancy cars in passing in a page that has nothing to do with them and everything to do with stories and a link=Category.Stories -Fancycars style listing would leave us in the dark. Where as the above proposed would allow this and do exactly what we wish.

In essence this feature is useful in particular for a nested web of categories, such that a page is in multiple categories, and when we wish to view only a particular subset of a given category, or perhaps multiple categories.


Er, my brain went south on me when I wrote the above didn't it?

link=Category.Skins,Category.UpdateMe is saying all of the links to Category.Skins AND Category.UpdateMe, which is NOT at all what I was thinking.

I believe the link=Category.Skins,-Category.UpdateMe notation is correct (pages in Category.Skins that are NOT in Category.UpdateMe.)

  • sigh* This base idea even if I have the semantics confused...

I am not sure where to comment about this feature so I am putting it here. This feature would provide a great way to extend the Category feature by providing a good way to produce a list of pages based on the intersection and exclusion of pages marked with multiple categories. Currently I have to use Categories and hidden PageVariables (is hard for novice users to understand) to try and mark pages in a way that I can then automaticlly select via a pagelist command. This still falls short of what can be selected and increases, in my opinion, the complexity of the procedure needed to create a usefully marked page. It would be nice to be able to markup pages like this:

Using Multiple Categories

*Monday night basketball
[[!Activity]] [[!Teen]] [[!Adult]]

*ROCK Around the Clock
[[!Activity]] [[!Teen]]

*Bingo at the park
[[!Activity]] [[!Adult]]

*Video night
[[!Activity]] [[!Single]]

*Coloring Corner Hour
[[!Activity]] [[!Preschool]]

Then list pages like so:

!All adult and teen activities
(:pagelist link=Category/Activity,Category/Adult,Category/Teen :)
* Monday night basketball

!All teen activities
(:pagelist link=Category/Activity,Category/Teen :)
* Monday night basketball
* ROCK Around the Clock

Rather than using Categories and page variables (I don't know how to make the first one work)

(:Agegroup: Adult, Teen:)
*Monday night basketball

(:Agegroup: Teen:)
*ROCK Around the Clock

(:Agegroup: Adult:)
*Bingo at the park


My two cents.

I'd simply like to be able to ask "give me all the categories used in the Cookbook group, eg

(:pagelist group=Cookbook link=Category.* list=normal:)

Also (or)

(:pagelist group=Cookbook link=Category/ list=normal:) (groups)
(:pagelist group=Cookbook link=Category.w* list=normal:) (wildcards)
simon May 23, 2011, at 04:26 AM

Here's my implementation:

--- before.txt	Wed Aug 03 14:24:23 2011
+++ after.txt	Wed Aug 03 14:27:15 2011
@@ -345,9 +345,17 @@
         $opt['=exclp'][] = '$'.implode('|', array_map('preg_quote',$excl)).'$i';

       if (@$opt['link']) {
-        $link = MakePageName($pn, $opt['link']);
-        $opt['=linkp'] = "/(^|,)$link(,|$)/i";
-        $indexterms[] = " $link ";
+        foreach (explode(',', $opt['link']) as $link) {
+          $excl = ($link[0] == '-');
+          if ($excl) $link = substr($link, 1);
+          $link = MakePageName($pn, $link);
+          if ($excl) {
+            $opt['=linkp'][] = "-/(^|,)$link(,|$)/i";
+          } else {
+            $opt['=linkp'][] = "/(^|,)$link(,|$)/i";
+            $indexterms[] = " $link ";
+          }
+        }

       if (@$opt['=cached']) return 0;
@@ -365,8 +373,14 @@
     case PAGELIST_ITEM:
       if (!$page) { $page = ReadPage($pn, READPAGE_CURRENT); $opt['=readc']++; }
       if (!$page) return 0;
-      if (@$opt['=linkp'] && !preg_match($opt['=linkp'], @$page['targets'])) 
-        { $reindex[] = $pn; return 0; }
+      if (@$opt['=linkp']) {
+        foreach ($opt['=linkp'] as $pat) {
+          $excl = ($pat[0] == '-');
+          if ($excl) $pat = substr($pat, 1);
+          if (!preg_match($pat, @$page['targets']) xor $excl)
+              { $reindex[] = $pn; return 0; }
+        }
+      }
       if (@$opt['=inclp'] || @$opt['=exclp']) {
         $text = $fold($pn."\n".@$page['targets']."\n".@$page['text']);
         foreach((array)@$opt['=exclp'] as $i) 

It does not support OR operations:

  • link=Foo,Bar lists pages that link to both
  • link=Foo,-Bar lists pages linking to Foo but not Bar
  • spreading between multiple link= statements makes no difference

I hereby release this as free for anyone to use - I'd be happy to see it in PmWiki. Maxim? August 03, 2011, at 08:53 AM

See also

  • 00521   Add ?action=backlinks
  • 00943   allow logical NOT and AND for pagelists link attribute, allow wildcards
  • 01203   Backlinks to incorporate pagelists, redirect, and include