* * Lets wikis on a wiki farm refer to each other * * Developed and tested using the PmWiki 2.2.0-beta series. * * To install, add the following to your configuration file: $SisterFmt = array( 'Name' => array( 'dirfmt' => '[...]/wiki.d/{$FullName}', 'scripturl' => 'http://[...]', 'attachurlprefix' => 'http://[...]', 'passwdread' => '' ), [...] ); include_once("$FarmD/cookbook/sisterly.php"); * where the contents of $SisterFmt match you farm layout. * * For more information, please see the online documentation at * http://www.pmwiki.org/wiki/Cookbook/Sisterly * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, * Version 2, as published by the Free Software Foundation. * http://www.gnu.org/copyleft/gpl.html */ $RecipeInfo['Sisterly']['Version'] = '2008-10-14'; if (empty($SisterFmt)) return; $Sisters = new SisterStore($SisterFmt); $WikiLibDirs[] = &$Sisters; SDVA( $SearchPatterns['farm'], $SearchPatterns['default'] ); SDV( $SearchPatterns['farm']['farm'], ''); # $SearchPatterns['default']['farm'] = ''; # $SearchPatterns['farm']['farm'] = "/^\w[\w-]*:/"; $FmtPV['$Wiki'] = 'preg_replace("/^(?:([^:]+):)?.*$/","$1",$group)'; $FmtPV['$PageUrl'] = '$GLOBALS["Sisters"]->pageurl("$group","$name")'; Markup( '{sister$var}', '<{$var}', '/\\{((?:\w[\w-]*):!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w+)\\}/e', "PRR(PVSE(PageVar(\$pagename, '$2', '$1')))" ); Markup( 'Attach:sister','get("$1","attachurlprefix")' ); ## fixes for included sister pages if (IsEnabled($EnableSisterFixIncluded,1)) SDVA( $QualifyPatterns, array( '/(\\[\\[(?>[^\\]]+?->)?\\s*)([^:]+?([|#?].*?)?\\]\\])/e' => "preg_match('/^\w[-\w]*:/',\$group,\$sm) ? PSS('$1').\$sm[0].PSS('$2') : PSS('$0')", '!\\bAttach:([^:.]+/)?([^:./]+\\.)!e' => 'preg_match("/^(\w[-\w]*):(.*)$/",$group,$sm) ? $GLOBALS["Sisters"]->get($sm[1],"attachurlprefix").( "$1">"" ? "$1" : $sm[2]."/" ).PSS("$2") : PSS("$0")', )); $MakePageNameFunction = 'MakeSisterPageName'; function MakeSisterPageName( $basepage, $str ) { global $PageNameChars, $PagePathFmt, $MakePageNamePatterns; SDV($PageNameChars,'-[:alnum:]'); SDV($MakePageNamePatterns, array( "/'/" => '', # strip single-quotes "/[^$PageNameChars]+/" => ' ', # convert everything else to space '/((^|[^-\\w])\\w)/e' => "strtoupper('$1')", '/ /' => '')); $str = preg_replace('/[#?].*$/', '', $str); if (!preg_match( "/^(?:(\w[\w-]*):)?(.*)/", $str, $sm )) return ''; $m = preg_split( '/[.\\/]/', $sm[2] ); if ( count($m)<1 || count($m)>2 || $m[0]=='' ) return ''; if (empty($sm[1])) $site = ''; else $site = preg_replace( array_keys($MakePageNamePatterns), array_values($MakePageNamePatterns), $sm[1] ) . ':'; ## handle "Group.Name" conversions if (@$m[1] > '') { $group = preg_replace( array_keys($MakePageNamePatterns), array_values($MakePageNamePatterns), $m[0] ); $name = preg_replace( array_keys($MakePageNamePatterns), array_values($MakePageNamePatterns), $m[1] ); return "$site$group.$name"; } $name = preg_replace( array_keys($MakePageNamePatterns), array_values($MakePageNamePatterns), $m[0] ); $isgrouphome = count($m) > 1; foreach((array)$PagePathFmt as $pg) { if ($isgrouphome && strncmp($pg, '$1.', 3) !== 0) continue; $pn = $site . FmtPageName(str_replace('$1', $name, $pg), $basepage); if (PageExists($pn)) return $pn; } if ($isgrouphome) { foreach((array)$PagePathFmt as $pg) if (strncmp($pg, '$1.', 3) == 0) return $site . FmtPageName(str_replace('$1', $name, $pg), $basepage); return "$site$name.$name"; } return $site . preg_replace('#[^/.]+$#', $name, $basepage); } class SisterStore extends PageStore { var $iswrite = FALSE; var $fmt; var $attr; function SisterStore( $sfmt, $a=NULL ) { $this->fmt = $sfmt; $this->attr = (array)$a; $GLOBALS['PageExistsCache'] = array(); } ## enables case-insensitive access function get($sn,$prop) { foreach( array_keys($this->fmt) as $s ) if (!strcasecmp($s,$sn)) return $this->fmt[$s][$prop]; return ''; } ## used in $FmtPV['$PageUrl'] function pageurl($group,$name) { global $ScriptUrl, $EnablePathInfo; if ( preg_match( '/^(\w[\w-]*):(.+)$/', $group, $m ) && ( $surl = $this->get($m[1],'scripturl') ) ) $group = $m[2]; else $surl = $ScriptUrl; # return PUE( ( ($group=='Main') && ($name=='HomePage') ) ? "$surl/" : ( ($name==$group) ? "$surl/$group" : "$surl/$group/$name" ) ); return PUE( $EnablePathInfo ? "$surl/$group/$name" : "$surl?n=$group.$name" ); } function pagefile($pagename) { if ( preg_match( '#^(\w[\w-]*):([^./]+)[./](.+)$#', $pagename, $sm ) && ( $sdf = $this->get($sm[1],'dirfmt') ) ) { $dfmt = str_replace( array( '{$FullName}', '{$Group}' ), array( $sm[2].'.'.$sm[3], $sm[2] ), $sdf ); # return FmtPageName( $dfmt, $pagename ); return $dfmt; } return FALSE; } function read($pagename, $since=0) { $page = parent::read($pagename,$since); if ($page) { $page['passwdattr'] = '@lock'; $page['passwdedit'] = '@lock'; $page['passwdupload'] = '@lock'; } if ( empty($page['passwdread']) && preg_match('#^(\w[\w-]*):.*[./]GroupAttributes$#i',$pagename,$sm) ) $page['passwdread'] = $this->get($sm[1],'passwdread'); return $page; } ## inherited: function exists($pagename) function write($pagename,$page) { Abort("Cannot write page to $pagename on sister site...changes not saved"); } function delete($pagename) { Abort("Cannot delete page $pagename on sister site...changes not saved"); } function ls($pats=NULL) { global $GroupPattern, $NamePattern; StopWatch("SisterStore::ls begin"); $pats=(array)$pats; if (!isset($pats['farm'])) return array(); array_push( $pats, "/^\w[\w-]*:$GroupPattern\.$NamePattern$/" ); $out = array(); foreach( array_keys($this->fmt) as $sister ) { $dir = $this->pagefile($sister.':$Group.$Name'); $maxslash = substr_count($dir, '/'); $dirlist = array(preg_replace('!/*[^/]*\\$.*$!','',$dir)); while (count($dirlist)>0) { $dir = array_shift($dirlist); $dfp = @opendir($dir); if (!$dfp) { continue; } $dirslash = substr_count($dir, '/') + 1; $o = array(); while ( ($pagefile = readdir($dfp)) !== false) { if ($pagefile{0} == '.') continue; if ($dirslash < $maxslash && is_dir("$dir/$pagefile")) { array_push($dirlist,"$dir/$pagefile"); continue; } if ($dirslash == $maxslash) $o[] = "$sister:$pagefile"; } closedir($dfp); StopWatch("SisterStore::ls merge $sister"); $out = array_merge($out, MatchPageNames($o, $pats)); } } StopWatch("SisterStore::ls end"); return $out; } }