00985: Same group link formatting

Summary: Same group link formatting
Created: 2007-10-03 11:48
Status: Open
Category: Feature
From: pjv
Priority: 31
Version: 2.2.0-beta63

Description: For my website I wanted the sidebar to have links for each group and to further have specific CSS styling if the current page is of that group. Unfortunately, the current PmWiki only seems to offer 'selflink' and 'wikilink' classes. I wanted an additional class 'grouplink' to be added to any link that targets the same group as the current page.

I made the following changes to pmwiki.php, LinkPage function:

  • new global variable $LinkGroupFmt.
  • small code change -- $fmt now set as follows:
$tgtgroup = PageVar($tgtname, '$Group');
$pagegroup = PageVar($pagename, '$Group');
$fmt = ($tgtname == $pagename && $qf == '') 
     ? $LinkPageSelfFmt 
     : ($tgtgroup == $pagegroup)
     ? $LinkGroupFmt : $LinkPageExistsFmt;
  • in local/config.php I added two lines:
$LinkPageSelfFmt = '<a class=\'selflink grouplink\' href=\'$LinkUrl\'>$LinkText</a>';
$LinkGroupFmt = '<a class=\'wikilink grouplink\' href=\'$LinkUrl\'>$LinkText</a>';

I have no idea if this is a good way of achieving my desired result, but it works for me. I'm adding it to PITS because I'd prefer not to have to patch every time I upgrade, and would like to know if there's a better way of achieving the same result.

You could achieve the same result without having to patch the core (see below):

  1. Define your own version of the LinkPage function into a separate source file (cookbook/linkpagegroup.php for example),
  2. Add your variable definitions to it,
  3. And register your function as the new link page handler.

You may then use it directly from local/config.php with include_once("$FarmD/cookbook/linkpagegroup.php");.

Related source code:

<?php if (!defined('PmWiki')) exit();

function LinkPageGroup($pagename,$imap,$path,$title,$txt,$fmt=NULL) {
  global $QueryFragPattern, $LinkPageExistsFmt, $LinkPageSelfFmt,
    $LinkPageCreateSpaceFmt, $LinkPageCreateFmt, $LinkTargets,
    $EnableLinkPageRelative, $LinkGroupFmt;
  if (!$fmt && $path{0} == '#') {
    $path = preg_replace("/[^-.:\\w]/", '', $path);
    return ($path) ? "<a href='#$path'>$txt</a>" : '';
  if (!preg_match("/^\\s*([^#?]+)($QueryFragPattern)?$/",$path,$match))
    return '';
  $tgtname = MakePageName($pagename, $match[1]); 
  if (!$tgtname) return '';
  $qf = @$match[2];
  if (!$fmt) {
    if (!PageExists($tgtname) && !preg_match('/[&?]action=/', $qf))
      $fmt = preg_match('/\\s/', $txt) 
             ? $LinkPageCreateSpaceFmt : $LinkPageCreateFmt;
    else {
      $tgtgroup = PageVar($tgtname, '$Group');
      $pagegroup = PageVar($pagename, '$Group');
      $fmt = ($tgtname == $pagename && $qf == '') 
             ? $LinkPageSelfFmt 
             : ($tgtgroup == $pagegroup)
             ? $LinkGroupFmt : $LinkPageExistsFmt;
  $url = PageVar($tgtname, '$PageUrl');
  if (@$EnableLinkPageRelative) 
    $url = preg_replace('!^[a-z]+://[^/]*!i', '', $url);
  $fmt = str_replace(array('$LinkUrl', '$LinkText'),
                     array($url.PUE($qf), $txt), $fmt);
  return FmtPageName($fmt,$tgtname);

$LinkPageSelfFmt = '<a class=\'selflink grouplink\' href=\'$LinkUrl\'>$LinkText</a>';
$LinkGroupFmt = '<a class=\'wikilink grouplink\' href=\'$LinkUrl\'>$LinkText</a>';

$LinkFunctions['<:page>'] = 'LinkPageGroup';

BTW, you just come to write your own cookbook recipe. I'll let you release it as a real one ;)

Dfaure October 04, 2007, at 07:59 AM

Thanks! Of course, maintaining a whole function in a cookbook entry is actually more work than updating two lines in pmwiki.php when upgrading. Still, it's a bit cleaner I suppose. Do you happen to know if the solution is correct? I couldn't work out what $qf is used for in the original code.

- pjv

Improved Solution: Active Page Group Parents

I updated your suggestions and came up with the following solution which also adds extra information about the link. Here is an illustration, imagine a list of links possibly put in a Group header.

  • Home Page
  • Group 1
    • Group 1 parent 1
    • Group 1 parent 2
  • Group 2
  • Group 3

If we are currently viewing the Group 1 parent 2 then the following class names are applied to the links:

  • Home Page - wikilink
  • Group 1 - wikilink grouplink groupparentindex
    • Group 1 parent 1 - wikilink grouplink
    • Group 1 parent 2 - wikilink grouplink selflink
  • Group 2 - wikilink
  • Group 3 - wikilink

Notice that only the group members of the currently selected page have grouplink applied. Most important, however, is the groupparentindex which is applied to the parent of the currently selected page. For example, the following pages:

  • Vocation/Vocation
    • Vocation/Flight
    • Vocation/CarRental

The best way to achieve this is to overwrite the default LinkPage function (as suggested above) using a Cookbook. Download the cookbook file and read more about it on my wiki konstruktors.com/Notes/PmWikiPageLinkClasses http://konstruktors.com/Notes/PmWikiPageLinkClasses

There is a working solution from some time -- you can have a different CSS class to links to other WikiGroups. Check it at Cookbook.ExternalLinks. --Petko November 15, 2007, at 06:18 PM