<?php if (!defined('PmWiki')) exit();
/*
cmsmode.php - Adds some CMS Mode features for PmWiki
Copyright 2006,2012,2014 by Hagan Fox
This program is distributed under the terms of the
GNU General Public License, Version 2

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.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

This recipe makes your wiki look and act like an ordinary website
when non-authors visit by adding the following to a PmWiki site:

* Certain changes to the site's behavior when the visitor isn't permitted
  to edit pages.
  - Any action (?action=<something>) not explicitly permitted is ignored.
  - Only your site's content pages will appear in search results, not
    PmWiki documentation or other content you may specify.
  - Most PmWiki-related pages will be inaccessible as well as unsearchable.
  - The rel="nofollow" attribute is removed from external links, which
    will signal search engines to index them.
  - Page modification times are simplified to just a date.

* (All)RecentChanges pages are modified so they're more appropriate to
  be used as public web (RSS) feeds.
  - RecentChanges pages other than $SiteGroup.AllRecentChanges will
    have a web feed-friendly format, with PmWiki-related pages excluded.
  - A Main.AllRecentChanges page is created that is appropriate to be used
    as a public site-wide web feed page.

By default there are pages that visitors can visit but they don't appear
in search results. For example, by default,
  - Pages in a group named Test/ are off-limits to non-authors.
  - Pages in a group named Temp/ can be visted, but not searched.
  - Neither Test/ nor Temp/ pages appear in the public feed.

Copy the script to the cookbook/ directory and add the following to
your configuration file:

   ## Make the  wiki look and act like a normal website for non-authors.
   $pagename = ResolvePageName($pagename);
   include_once("$FarmD/cookbook/cmsb-cmsmode.php");

Version: 2014-05-18
	Now getting the group and page names without using PageVar().
Version: 2014-05-17 
	Added 'logout' to the default allowed actions list,
	and other improvements for authors from the Search Page.
	Removed $CMSNoNavCSS setting; added $CMSPmSkinCSS setting.
Version: 2014-05-16
	Removed 'diff' from the default allowed actions list. 
Version: 2014-05-15
	Renamed $CMSRedirPages to $CMSRedirNames and 
	$CMSExclARCPages to $CMSExclARCNames.  Added
	$CMSExclSearchGroups and $CMSExclSearchNames settings.
	Search tests the test page not the current page now.
Version: 2014-05-14
	Improved compatibility with the default PmWiki skin by
	hiding footer navigation links with "display:none" CSS.
	Added CMSEditTestPage setting for author-or-not test.
	These are now configurable settings: $CMSRedirGroups,
	$CMSRedirPages, $CMSExclARCGroups, $CMSExclARCPages
Version: 2012-07-27 
	Keep Draft RecentChanges separate. 
Version: 2006-07-27
	Updated method of checking for edit permissions and added
	'comment' and 'approvesites' as default allowed actions.
Version: 2006-06-05 - Added new $CMSAllowedActions setting.
Version: 2006-06-01 - Added documentation.
Version: 2006-03-28 - Initial version.
*/
SDV($RecipeInfo['CMSMode']['Version'], '2014-05-18');

## Some default settings
SDV($EnableCMSMode, TRUE);
## We need to determine if the visitor is an author.
SDV($CMSEditTestPage, $DefaultGroup.'.WikiSandbox'); // Authors can edit this page.
SDV($FeedAllRecentChanges, 'Main.AllRecentChanges'); // Public A.R.C. feed
SDV($CMSAllowedActions, // These actions are allowed for non-authors.
  array('browse', 'print', 'search', 'edit', 'login', 'logout', 'rss', 'atom',
  'addlink', 'skin', 'setskin', 'comment', 'approvesites', 'setprefs'));
SDV($EnableDraftRedir, TRUE); // Non-authors can't see drafts (-Draft pages).
SDV($EnableTalkRedir, TRUE); // Non-authors can't see -Talk discussion pages.
SDV($CMSRedirGroups, // Authors can visit these groups, non-authors can't. 
  array('Test', 'PmWiki', 'SiteAdmin', 'Profiles'));
SDV($CMSRedirNames, // Authors can visit these pages, non-authors can't. 
  array('GroupHeader', 'GroupFooter', 'GroupAttributes', 'WikiSandbox',
   'AuthUser', 'RecentDraftChanges'));
SDV($CMSExclARCGroups, // These groups are excluded from public A.R.C page.
  array('Temp', 'Test', 'PmWiki', 'Site', 'SiteAdmin', 'Profiles'));
SDV($CMSExclARCNames, // These pages are excluded from public A.R.C page.
  array('GroupHeader', 'GroupFooter', 'GroupAttributes', 'WikiSandbox',
    'RecentDraftChanges', 'AllRecentChanges'));
SDV($CMSNoNavCSS, TRUE); // Use display:none for .footnav (PmWiki skin)
SDV($CMSExclSearchGroups, '(Temp|Test|PmWiki|Site|SiteAdmin|Profiles)');
SDV($CMSExclSearchNames, '(GroupAttributes|WikiSandbox)');
SDV($CMSModeStyles, // Some CSS for non-authors 
  "  .headnav, #wikicmds, .pagegroup, .headnav { display:none; }
  #wikititle { margin-top:8px; margin-bottom:2px; }
  .lastmod, .footnav a, .footnav a:visited { color:#999999; }\n");
SDV($CMSPmSkinCSS, // CSS for PmWiki Skin Search Link & footer nav links
  "  #wikihead a { text-decoration:underline; color:black; }
  #wikihead a:hover { text-decoration:underline; color:blue; }
  .footnav { display:none; } ");

## Get the group and page names. (PageVar() caused unexpected results.)
$CMSpage = explode(".", $pagename);
$CMSgroup = $CMSpage[0]; // same as {$Group}
$CMSname = $CMSpage[1]; // same as {$Name}

## Customize (All)RecentChanges pages for better web feeds.
if (in_array($group, $CMSExclARCGroups) || in_array($CMSname, $CMSExclARCNames)) {
  $RecentChangesFmt['$Group.RecentChanges'] = '';
  $RecentChangesFmt[$FeedAllRecentChanges] = '';
} else {
  $RecentChangesFmt[$FeedAllRecentChanges] =
    '* [[{$Group}.{$Name}]]  $[was modified] $CurrentTime. [=$ChangeSummary=]';
}

##  Keep a separate RecentDraftChanges page for drafts.
# TODO: Experimental
$DraftRecentChangesFmt['$Group.RecentDraftChanges'] =
  '* [[{$Group}/{$Name}]]  . . . $CurrentTime $[by] $AuthorLink: [=$ChangeSummary=]';
#$DraftRecentChangesFmt['$Group.RecentChanges'] = '';

## Allow the rest of this script to be disabled in config.php or another recipe.
if ($EnableCMSMode == FALSE) return;

## Ignore the rest  for administrators.
if (CondAuth($SiteGroup.'.'.$SiteGroup, 'admin')) return;

## Crate a {$BaseName} page variable for "-Talk" and "-Draft" pages.
## TODO: Move this?
if (preg_match('/-Talk$/', $pagename)) {
  $BaseNamePatterns['/-Talk$/'] = ''; }
if (preg_match('/-Draft$/', $pagename)) {
  $BaseNamePatterns['/-Draft$/'] = ''; }

## For searches and wikiactions we check the Test Page to determine
## author/non-author, not the current page because e.g. Site.Search is read-only
if (! CondAuth($CMSEditTestPage, 'edit')) {
  ## Exclude Certain pages / groups from search results.
  $SearchPatterns['default'][] = '!\\.(All)?Recent(DraftChanges|Changes|Uploads)$!';
  $SearchPatterns['default'][] = '!\\.(Group|Print)(Header|Footer)$!';
  $SearchPatterns['default'][] = '!\\.'.$CMSExclSearchNames.'$!';
  $SearchPatterns['default'][] = '!^'.$CMSExclSearchGroups.'\\.!';
  if (IsEnabled($EnableDraftRedir)) $SearchPatterns['default'][] = '!-Draft$!';
  if (IsEnabled($EnableTalkRedir)) $SearchPatterns['default'][] = '!-Talk$!';
  if ($pagename == $SiteGroup.'.AllRecentChanges') Redirect($FeedAllRecentChanges);
  ## Hide wiki-related page elements.
  SetTmplDisplay('PageActionFmt', 0);
  SDV($HTMLStylesFmt['cmsmode'], $CMSModeStyles);
  ## Improve PmWiki Skin search text
  if ($Skin == 'pmwiki') $HTMLStylesFmt['cms_pmskin'] = $CMSPmSkinCSS;
  ## Format the time string for last-updated notices.
  $TimeFmt = '%B %d, %Y';
}

## Create some special restrictions for read-only pages, which is all or
## nearly all pages if there's a site-wide edit password.
if (! CondAuth($pagename, 'edit')) {
  global $SearchPatterns, $DefaultPage, $EnableDraftRedir, $EnableTalkRedir,
    $UrlLinkFmt, $TimeFmt;
  ##  Allow only essential site-related actions.
  if (! in_array($action, $CMSAllowedActions)) { $action='browse'; }
  ## Deny access to certain groups / pages.
  if (in_array(CMSgroup, $CMSRedirGroups)
    || (preg_match("!^$SiteGroup".'\\.!', $pagename)
      && !preg_match('!\\.(Search|ActionLog|AllRecentChanges)$!', $pagename)) // TODO ActonLog?
    || in_array($CMSname, $CMSRedirNames)) {
    Redirect($DefaultPage);
  }
  ## Stealth draft pages // TODO: $DraftSuffix
  if (IsEnabled($EnableDraftRedir)) {
    $basename = preg_replace("/-.*\$/", '', $pagename);
    if (preg_match('/-Draft$/', $pagename)) Redirect($basename);
  }
  ## Stealth discussion pages
  if (IsEnabled($EnableTalkRedir)) { 
    $basename = preg_replace("/-.*\$/", '', $pagename);
    if (preg_match('/-Talk$/', $pagename)) Redirect($basename);
  }
  ## Lose the rel='nofollow' attribute for external links.
  $UrlLinkFmt =     "<a class='urllink' href='\$LinkUrl'>\$LinkText</a>";
}