<?php if (!defined('PmWiki')) exit(); /* powertools.php a PmWiki 2.2 extension, copyright Hans Bracker 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. {(plist )} markup expression returns a comma separated list of full pagenames from pagenames including wildcards. syntax {(plist PageName1 PageName2 ... -PageName3 ....)} PageName - source pages from PageName or Group. Allowed are Wiki wildcards * and ? OR PageName#section. -PageName - PageName excluded from source pagelist, wildcards allowed. Extra options: group=GROUP - source pages from GROUP (same as pagelist group= option) (wiki wildcards and comma-separated listing allowed) name=NAME - source pages NAME from any group (same as pagelist name= option) (wiki wildcards and comma-separated listing allowed) fmt=groups - output only list of group names. groups=GROUPPATTERN - as group=GROUPPATTERN but with fmt=groups output: groups=* will give a list of all group names. sep=SEPARATOR - character or string inserted between each full pagename. Default is a comma. CR or \n makes new line separations. pre=PREFIX - PREFIX string is put in front of every name. suf=SUFFIX - SUFFIX string is put behind every name. {(pagelist )} markup expression returns a comma separated list of full pagenames and accepts all parameters of the (:pagelist :) directive. Default output format is a comma-separated list (fmt=csv), not a HTML list of links. Other formats can be given via a fmt= parameter {(rename PAGELIST group=GROUP pre=PREFIX suf=SUFFIX)} with input from plist or pagelist returns new pagelist with new Group.PageNames GROUP.PREFIX.PageName.SUFFIX if parameters are specified. Use for page backup forms. {(pagecount PAGELIST)} markup expression returns the number of pages from a comma-separated pagelist supplied as argument. {(wordcount STRING|PAGENAME|PAGELIST)} returns count of words in argument STRING or page PAGENAME or csv PAGELIST. {(trail [next|prev] label trailpagename)} markup expresion returns a link for eithe rnext or previous page on wiki trail set on trailpagename. If no trailpage is given all pages in the current wiki group are used as trail. {(serialname Group Name)} returns incremented pagename of format Group.Name0001 (appended 4-digit number defined by var $SerialStart, incrementing number of Group.Name1234 pages) {(serial Group Name)} returns incremented serial number for Group.Name1234 pages (4-digit number defined by $SerialStart) {(newticket Group)} returns auto increasing pagename of format Group.20071220001 (today date and 3 digit number) {(sumdata PAGE|PAGELIST data=PTVLIST)} returns sum of PTVs listed from pages in PAGELIST {(allptvs PAGE|PAGELIST)} show all PTVs as name: value; input argument: PageName or csv list of pagenames for instance with (plist) {(random LIST)} returns item selected at random from csv list provided. Doubles are prevented. sep= to specify custom listitem separator */ $RecipeInfo['PowerTools']['Version'] = '2022-11-01'; ## (plist ...) $MarkupExpr['plist'] = 'MxMakePList($pagename, @$args, @$argp)'; function MxMakePList($pagename, $args, $opt='') { if (isset($args[0]) && $args[0]=='' && $opt=='') return $pagename; StopWatch('plist start'); $grp = PageVar($pagename, '$Group'); $exlist = array(); $inlist = array(); $plist = array(); if (isset($opt['groups'])) { $grps = explode(",",$opt['groups']); foreach($grps as $g) $args[] = "$g.*"; $opt['fmt'] = 'groups'; } if (isset($opt['group'])) { $gp = explode(",",$opt['group']); foreach($gp as $g) $args[] = "$g.*"; } if (isset($opt['name'])) { $ns = explode(",",$opt['name']); foreach($ns as $n) $args[] = "*.$n"; } foreach($args as $src) { $pgs = preg_split("/[\\s,|]+/", $src, -1, PREG_SPLIT_NO_EMPTY); $plist = array_merge($plist, $pgs); } foreach((array)$plist as $pn) { //check for exclusions if($pn[0]=='-') { $pn = substr($pn, 1); //check for group.name pattern if (strstr($pn,'.')) $pgpat = $pn; else $pgpat = $grp.".".$pn; //make preg pattern from wildcard pattern $prpat = GlobToPCRE(FixGlob($pgpat)); //make list from preg name pattern $exlist = array_merge($exlist, ListPages("/$prpat[0]/")); } //check for section suffix elseif (strstr($pn,'#')) $inlist[] = $pn; //additions else { //check for group.name pattern if (strstr($pn,'.')) $pgpat = $pn; else $pgpat = $grp.".".$pn; //make preg pattern from wildcard pattern $prpat = GlobToPCRE(FixGlob($pgpat)); //make list from preg name pattern $inlist = array_merge($inlist, ListPages("/$prpat[0]/")); } } $plist = array_diff($inlist, $exlist); sort($plist); if (isset($opt['fmt']) && $opt['fmt']=='groups') { $glist = array(); foreach($plist as $p) { $pp = explode('.',$p); if (in_array($pp[0], $glist)) continue; $glist[] = $pp[0]; } $plist = $glist; } $sep = (@$opt['sep']) ? $opt['sep'] : ","; $sep = str_replace('\n',"\n",$sep); if ($sep=='LF') $sep = "\n"; foreach ($plist as $i => $p) $plist[$i] = @$opt['pre'].$p.@$opt['suf']; StopWatch('plist end'); return implode($sep, $plist); } ## (pagelist ......) [all pagelist parameters allowed] $MarkupExpr['pagelist'] = 'MxPageList($pagename, preg_replace_callback($rpat, "cb_expandkpv", $params))'; function MxPageList($pagename, $args) { StopWatch('pagelist start'); $opt = array('o' => $args, 'fmt' => 'csv'); $out = FmtPageList('$MatchList', $pagename, $opt, 0); $out = preg_replace("/[\n]+/s","\n",$out); StopWatch('pagelist end'); return $out; } $FPLFormatOpt['csv'] = array('fn' => 'FPLSimpleText'); function FPLSimpleText($pagename, &$matches, $opt) { $matches = MakePageList($pagename, $opt, 0); ## extract page subset according to 'count=' parameter if (@$opt['count']) { list($r0, $r1) = CalcRange($opt['count'], count($matches)); if ($r1 < $r0) $matches = array_reverse(array_slice($matches, $r1-1, $r0-$r1+1)); else $matches = array_slice($matches, $r0-1, $r1-$r0+1); } $opt['sep'] = ((@$opt['sep']) ? $opt['sep'] : ","); $opt['sep'] = str_replace('\n',"\n",$opt['sep']); if ($opt['sep']=='LF') $opt['sep'] = "\n"; return Keep(implode($opt['sep'], $matches), 'P'); } ## (rename (plist ...) [group=NEWGROUP] [pre=NAMEPREFIX] [suf=NAMESUFFIX]) $MarkupExpr['rename'] = 'MxPageRename($pagename, $args[0], @$argp)'; function MxPageRename($pagename, $plist, $opt='') { $plist = explode(",", $plist); foreach($plist as $k => $pn) { if (!strstr($pn,".")) { $grp = PageVar($pagename, '$Group'); $pn = $grp.".".$pn; } $plist[$k] = explode(".", $pn); } $pre = ($opt['pre'] ? $opt['pre'] : ''); $suf = ($opt['suf'] ? $opt['suf'] : ''); $newplist = array(); foreach($plist as $i => $pn) { foreach($plist[$i] as $grp => $name) { if ($opt['group']) $newplist[$i] = $opt['group'].".".$pre.$name.$suf; else $newplist[$i] = $plist[$i][0].".".$pre.$name.$suf; } } return implode(",", $newplist); } ## (pagecount (plist ...)) $MarkupExpr['pagecount'] = 'PageCount($pagename, @$args[0])'; function PageCount($pn, $arg='') { if ($arg=='') return 0; return count(explode(",", $arg)); } ## (wordcount PageName), (wordcount (plist ...)) (wordcount 'string') (wordcount) $MarkupExpr['wordcount'] = 'WordCount($pagename, @$args[0])'; function WordCount($pn, $arg='') { //wordcount current page if ($arg=='') { $page = RetrieveAuthPage($pn, 'read', false, READPAGE_CURRENT); return str_word_count($page['text']); } //wordcount string if (strpos($arg," ")) { return str_word_count($arg); } //wordcount page(s) PageName1,PageName2,PageName3 ... else { $pglist = explode(",", $arg); $wcnt = 0; foreach($pglist as $pg) { $pn = MakePagename($pn, $pg); $page = RetrieveAuthPage($pn, 'read', true); $wcnt = $wcnt + str_word_count($page['text']); } return $wcnt; } } ## {(trail [next|prev] label trailpagename)} $MarkupExpr['trail'] = 'MakeTrailStopNext($pagename, $args[0], $args[1], $args[2])'; function MakeTrailStopNext($pagename, $which='', $label='', $trailname='') { $trail = array(); $link=''; if ($which=='') $which ='next'; if ($label=='') $label = $which; //if no trailname make trail from all group pages if ($trailname=='') { $grp = PageVar($pagename, '$Group'); $gplist = ListPages("/^$grp\\..+/"); sort($gplist); foreach($gplist as $i => $p) $trail[$i]['pagename'] = $p; } else $trail = ReadTrail($pagename, $trailname); for($i=0; $i < count($trail); $i++) { if ($trail[$i]['pagename']==$pagename) { if ($which=='next') { if ($i+1<count($trail)) $link = "[[".$trail[$i+1]['pagename']."|".$label."]]"; } if ($which=='prev') { if ($i>0) $link = "[[".$trail[$i-1]['pagename']."|".$label."]]"; } } } return $link; } ## {(rndpage label trailpagename group=GroupName exclude=PageA,PageB)} $MarkupExpr['rndpage'] = 'MXRandomPageLink($pagename, $args[0], $args[1], $argp)'; function MXRandomPageLink($pagename, $label, $args, $trailname='' ) { global $RandomPageNamesUsed; $trail = array(); //if no trailname make trail from all group pages if ($trailname=='') { if (isset($args['group'])) $group = $args['group']; else $group = PageVar($pagename, '$Group'); $gplist = ListPages("/^$group\\..+/"); $exclude = array( $pagename, $group.'.RecentChanges', $group.'.RecentUploads', $group.'.GroupHeader', $group.'.GroupFooter', $group.'.GroupAttributes', ); if (isset($args['exclude'])) { $excl = explode(',',$args['exclude']); foreach($excl as $i => $p) $excl[$i] = MakePageName($group.'.HomePage',$p); $exclude = array_merge($exclude, $excl); } foreach($gplist as $i => $p) if (in_array($p,$exclude) || in_array($p,(array)$RandomPageNamesUsed)) unset($gplist[$i]); sort($gplist); foreach($gplist as $i => $p) $trail[$i]['pagename'] = $p; } else $trail = ReadTrail($pagename, $trailname); //pick random pagename from trail $max = count($trail)-1; $i = rand(0,$max); $pn = $trail[$i]['pagename']; $RandomPageNamesUsed[] = $pn; if ($label=='title') $label = '+'; if ($label=='') $label = 'next'; if ($label=='name') $label = PageVar($pn, '$Name'); return "[[$pn|$label]]"; } SDV($SerialStart,'0001'); # add markup expression {(serialname Group Name)} # creates auto increasing pagename of format # Group.Name0001 (appended 4-digit number defined by $SerialStart # incrementing number of Group.Name1234 pages $MarkupExpr['serialname'] = 'MakeSerialPageName($pagename, $args[0], $args[1])'; function MakeSerialPageName($pagename, $grp="", $name="" ) { global $SerialStart; $len = strlen($SerialStart); if (!$grp) $grp = PageVar($pagename, '$Group'); $n = $SerialStart-1; foreach(ListPages("/^$grp.$name\\d/") as $p) { preg_match("/.*[^\\d](\\d+)$/",$p, $m); $mlen = strlen($m[1]); if($mlen>$len) $len = $mlen; $n = max($n,$m[1]); } $target= $grp.".".$name.sprintf("%0{$len}d",$n+1); return $target; } # add markup expression {(serial Group Name)} # creates auto increasing number only defined by $SerialStart # incrementing number of Group.Name1234 pages $MarkupExpr['serial'] = 'MakeSerialNumber($pagename, $args[0], $args[1])'; function MakeSerialNumber($pagename, $grp="", $name="" ) { global $SerialStart; $len = strlen($SerialStart); if (!$grp) $grp = PageVar($pagename, '$Group'); $n = $SerialStart-1; foreach(ListPages("/^$grp.$name\\d/") as $p) { preg_match("/.*[^\\d](\\d+)$/",$p, $m); $mlen = strlen($m[1]); if($mlen>$len) $len = $mlen; $n = max($n,$m[1]); } return sprintf("%0{$len}d",$n+1); } # add markup expression {(newticket Group)} # creates auto increasing pagename of format # Group.20061220001 (date and 3 digit number) $MarkupExpr['newticket'] = 'MakeNewTicket($pagename, $args[0])'; function MakeNewTicket($pagename, $grp) { if (!$grp) $grp = PageVar($pagename, '$Group'); $issue = '0'; foreach(ListPages("/^$grp.\\d{11}/") as $p) $issue = max(@$issue,substr($p,-11)); $issueday = substr($issue,0,8); $today = date('Ymd', time()); if($issueday==$today) { $nextissue = $issue+1; $target = $grp.".".$nextissue; } else $target = $grp.".".$today."001"; return $target; } # {(sumdata PAGELIST data=PTVLIST)} # returns sum of PTVs listed from pages in PAGELIST # example: {(sumdata (plist Test.*) data=PTV1,PTV2 )} $MarkupExpr['sumdata'] = 'MXSumDataPTVs($pagename, $args[0], $argp)'; function MXSumDataPTVs($pagename, $list, $args) { $sum = ''; if(!isset($args['data'])) return 'no data PTVs selected'; $ptvs = explode(',',$args['data']); $plist = (isset($list)) ? explode(',',$list) : array($pagename); foreach($plist as $pn) { $pn = MakePageName($pagename, $pn); foreach ($ptvs as $d) { $v = PageTextVar($pn, $d); $sum += floatval($v); } } return $sum; } # {(allptvs PAGELIST|PAGENAME)} # show all ptvs as name: value; input argument: PageName or list of page names $MarkupExpr['allptvs'] = 'MXDisplayAllPTVs($pagename, $args[0])'; function MXDisplayAllPTVs($pagename, $list) { global $PCache; $pgout = array(); $out = array(); $plist = (isset($list)) ? explode(',',$list) : array($pagename); foreach($plist as $pn) { $pn = MakePageName($pagename, $pn); $pgout[$pn][0] = "!!!![[$pn]]\n"; PageTextVar($pn, ''); foreach($PCache[$pn] as $key => $val) { if (substr($key,0,3)!="=p_") continue; $pgout[$pn][] = "'''".substr($key,3)."''': ".$val."\\\\\n"; } if (!isset($pgout[$pn][1])) { unset($pgout[$pn]); continue; } sort($pgout[$pn]); $out[] = implode("\n",$pgout[$pn]); } return implode("\n",$out); } # {(random CSV-List)} {(random LIST sep=separator>)} # select item at random from csv list provided. No doubles. sep= to specify custom listitem separator $MarkupExpr['random'] = 'MXRandomItem($pagename,$args[0],$argp)'; function MXRandomItem($pagename, $list, $args) { global $RandomItemsUsed; $sep = (isset($args['sep'])) ? $args['sep'] : ','; $sep = str_replace('\n',"\n",$sep); $list = explode($sep,$list); foreach($list as $i => $item) if (in_array($item,(array)$RandomItemsUsed) || $item=='') unset($list[$i]); sort($list); $i = rand(0,count($list)-1); $RandomItemsUsed[] = $list[$i]; return $list[$i]; } # restores kept/protected strings if (! function_exists('cb_expandkpv')) { function cb_expandkpv($m) { return $GLOBALS['KPV'][$m[1]]; } }