CustomPagelistSortOrderFunctions

Summary: Custom functions for creating custom page sort orders with pagelists
Version: 2007-03-06
Prerequisites: pmwiki 2.2.0 beta
Status:
Maintainer:
Categories: Searching PageList

Description

Custom functions for creating custom page sort orders with pagelists.

Sorting pages by integer pagetextvar data:

See also (new for 2.2.110): $PageListSortCmpFunction.

Here is a custom PagelistSortOrder function for sorting pages by numerical PageTextVariable data.
The pagetextvariable $:Books is used as an example.

Add to local config (or recipe script):

# sorting pages by numerical integer pagetextvar data
function IntegerDataCompare($x, $y, $var) {
  # get integer value of the page text variable
  $xval = intval(GetCachedPTV($x, $var));
  $yval = intval(GetCachedPTV($y, $var));
  # compare integer values
  if($xval == $yval) return 0;
  return ($xval > $yval) ? 1 : -1;
}

# we have to directly use the cached PTVs when they exist
# otherwise we quickly hit the $MaxPageTextVars limits
function GetCachedPTV($pn, $var) {
  global $PCache;
  if (@$PCache[$pn]['=pagetextvars'])
    return @$PCache[$pn]["=p_$var"];
  return PageTextVar($pn, $var);
}

# defining order=books to sort integers numerical by pagetextvar $:Books
$PageListSortCmp['books'] = 'IntegerDataCompare($x, $y, "Books")';

Then use in your PageList directive with order=books (numerical sort smallest number first) or order=-books (largest number first)

For other integer page text variables just create another array item for $PageListSortCmp, as done above with "Books".

See also $MaxPageTextVars. Calling directly PageTextVar() many times, which may happen in a $PageListSortCmp function, will quickly hit the $MaxPageTextVars limits. For this reason we use the GetCachedPTV() function which will use the once-cached values.

Sorting pages by integer numbers of pagename (Title)

Add to local config (or recipe script):

function IntegerNameCompare($x, $y) {
      # get integer value of the page name or title
      $xval = intval(PageVar($x, '$Title'));
      $yval = intval(PageVar($y, '$Title'));
      # compare integer values
      if($xval > $yval) $c = 1;
      elseif($xval < $yval) $c = -1;
      else $c = 0;
      return $c;
}
$PageListSortCmp['intname'] = 'IntegerNameCompare($x, $y)';

Then use in your PageList directive with order=intname (numerical sort smallest number first) or order=-intname (largest number first). To exclude other page names from the list and use only pagenames starting with a digit use in the pagelist directive: name=[0-9]*

Example: (:pagelist group={$Group} name=[0-9]* order=intname fmt=#title :)

Sorting pages by integer numbers of any Page variable

Add to local config (or recipe script):

function IntegerPVCompare($x, $y, $var) {
      # get integer value of the page name or title
      $var = '$' . $var;
      $xval = intval(PageVar($x, $var));
      $yval = intval(PageVar($y, $var));
      # compare integer values
      if($xval > $yval) $c = 1;
      elseif($xval < $yval) $c = -1;
      else $c = 0;
      return $c;
}
$PageListSortCmp['votes'] = 'IntegerPVCompare($x, $y, 'Votes')';

If you use "order=votes" or "order=-votes" in a pagelist, the above code will order the list on the {$Votes} variable (assuming there is one, coming from a recipe like VoteCounter.

Sorting pages using locale (sort 'é', 'è', 'ê', etc. with 'e' for example)

Add to local config (or recipe script):

$PageListSortCmp['namelocalesort'] = 'LocaleSort($x, $y)';
function LocaleSort($a, $b) {
  $x = array($a, $b);
  setlocale(LC_ALL, 'fr_FR'); ## or 'fr_FR.utf8'
  sort($x, SORT_LOCALE_STRING);
  return ($x[0]==$a)? -1:1;
}
# if you want to enable locale sort for the page "title"
$PageListSortCmp['title'] = // Note: 'titlelocalesort' won't work
  'LocaleSort($PCache[$x][\'=title\'], $PCache[$y][\'=title\'])';

Then use in your PageList directive with order=namelocalesort

Example: (:pagelist group={$Group} order=namelocalesort fmt=#title :) (demo)

(from Petko Yotov in pmwiki-users, 2009/05/23) For locale sorting, php7.2 working, see also : TestSort.

Sorting by title, disregarding leading A/An/The

Assumes pages named or titled as in "A Title" or "The Title" and you wish to disregard the leading A/An/The.

$FmtPV['$TitleNoArticle'] = 
   'preg_replace("/^ *(?:The|An?) /i", "", (@$page["title"] ? $page["title"] : $AsSpacedFunction($name)), 1)';
(:pagelist ... order=$TitleNoArticle ...:)

Sorting with last name first

Assumes pages named or titled as ZachAble, JohnSmith, AaronZimmerman and the desire is to have it sort in that order, by last name.
Note that McBain or other last names with an embedded capital will not work in this setup.

$FmtPV['$TitleLastFirst'] =
   'preg_replace("/^(.*?)([A-Z][a-z0-9_]*)$/", "\\\\2, \\\\1", (@$page["title"] ? $page["title"] : $AsSpacedFunction($name)))';
(:pagelist ... order=$TitleLastFirst ...:)

Notes

Wouldn't it be easier to just use strnatcasecmp()? http://us3.php.net/manual/en/function.strnatcasecmp.php

$PageListSortCmp['natural'] = 'strnatcasecmp($x, $y)';

It can handle combinations of integers and text, so that Page11 < Page100, etc.

Ben Stallings March 15, 2007, at 01:08 PM

Release Notes

If the recipe has multiple releases, then release notes can be placed here. Note that it's often easier for people to work with "release dates" instead of "version numbers".

See Also

Contributors

Comments

See discussion at CustomPagelistSortOrderFunctions-Talk

User notes +1: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.