<?php if (!defined('PmWiki')) exit();
/**
* \brief JJSCMS: write a static copy of any page on action=jjscmspublish 
* optionally integrates jjstemplate to allow for dynamic elements in both, public and private version of the site 
* @author Jens Schiffler <jens döt schiffler ät gmx döt de>
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
* @version 1.4beta1
* 
* new in 1.1: added $JJSCMSPrivateSection and $JJSCMSPublicSection to global statement in jjsCmsObCallback
* new in 1.2: compare cache mtime and page time, only write cache file if page is newer
* new in 1.3: remove session_name parameter from urls in cached version, url rewriting bugfixes
* new in 1.4beta1: major refactoring
*             - action jjscmspublish
*             - use jjsEditRev/jjsApprovePageRev PageAttributes if available
*             - use passwd auth with level "jjscmspublish"
*             - prefix JJSCMS for all global identifiers.
*                for example  $PublishDir is now  $JJSCMSPublishDir
*             - renamed
*                $PublishPublicSection   to  $JJSCMSPublicSection
*                $PublishPrivateSection  to  $JJSCMSPrivateSection
*                $PicsUrl                to  $JJSCMSAttachUrl
*             - helpful(?) error messages appended as html-comment
*             - use global $JJSCMSPublishROSPatterns for all replacement patterns
*             - rewriting is only done, if the $JJSCMS... variable is not empty
*             - new configuration variable JJSCMSAction
*/
define(JJSCMS, '1.4beta1');
## Configuration Variables
/**
* $JJSCMSPublishDir: Directory where the static (public) version of the pages will be written to
*/
SDV($JJSCMSPublishDir, '../../pmwiki/published');
/**
* $JJSCMSPublishUrl: URL prefix to be used in all local links in public version of the page.
* Should either point to place where the server is serving $JJSCMSPublishDir, or to a 
* skript that takes <Group>.<Page>.html as parameter
*/
SDV($JJSCMSPublishUrl, 'index.php?showcmspage=');
/**
* $JJSCMSAttachUrl 
*/ 
SDV($JJSCMSAttachUrl,'pmwiki/pics/');
/**
* $JJSCMSPublishAttachUrl: Point to pmwikis shared upload dir
*/
SDV($JJSCMSPublishAttachUrl,'pmwiki/pics/');
/**
* $JJSCMSPublishPubDirUrl: Point to pmwikis shared pub dir
*/
SDV($JJSCMSPublishPubDirUrl, 'pmwiki/pub/');

/**
* Anything enclosed by <!-- $JJSCMSPrivateSection --> <!-- /$JJSCMSPrivateSection -->
* in your template will only show up in the private (editable) version of the page.
*/
SDV($JJSCMSPrivateSection, 'dontpublish');
/**
* Anything enclosed by <!-- $JJSCMSPublicSection --> <!-- /$JJSCMSPublicSection -->
* in your template will only show up in the public (static) version of the page.
*/
SDV($JJSCMSPublicSection, 'dontedit');
##
## 
SDV($jjsUseTemplate, false);
/**
* parameter jjscmsaction selects which pmwiki action is captured 
* default for jjscmsaction is 'browse'
*/	
SDV($JJSCMSAction, 'browse');

/**
* JJSCMSObCallback
* outpbut buffering callback function to be registered with php
* does preg replacement using rules from $JJSCMSPublishROSPatterns 
* saves output to $JJSCMSPublishDir
* removes $JJSCMSPublishPublicSection before showing the page
*/
function JJSCMSObCallback($buffer) 
{	
  global 
		$pagename,
		$PCache,
		$ScriptUrl, 
		
		$PubDirUrl,
		$JJSCMSAttachUrl,
		$JJSCMSPublishUrl,
		$JJSCMSPublishAttachUrl,
		$JJSCMSPublishPubDirUrl,
		$JJSCMSPublishDir,
		$JJSCMSPrivateSection,
		$JJSCMSPublicSection,
		$JJSCMSPublishROSPatterns;
	
	
	$filename = $JJSCMSPublishDir . '/' . $pagename . '.html';
	
  // setup some regex replacement patterns
  //	
	// remove private sections  
	if (!empty($JJSCMSPrivateSection)) 
	{
		$JJSCMSPublishROSPatterns['/\<\!\-\- ' . $JJSCMSPrivateSection . ' \-\-\>.*\<\!\-\- \/' . $JJSCMSPrivateSection . ' \-\-\>/Us'] = '' ;
	}
	
	// remove trailing PHPSESSID 
	$JJSCMSPublishROSPatterns['/([&\?])' . session_name() . '\=[A-Za-z0-9]+$/'] = '' ;

	// remove PHPSESSID from start or in the middle of the parameter list
	$JJSCMSPublishROSPatterns['/([&\?])' . session_name() . '\=[A-Za-z0-9]+&?/'] = '\1' ;
	
	// rewrite  page links
	$JJSCMSPublishROSPatterns['/([\'"])' . str_replace('/','\/',$ScriptUrl) . '\?n\=([^#&]+)(#|&[^\1]+)?\1/Us'] = 
				'\1' . $JJSCMSPublishUrl . '\2.html\3\1' ;

	// rewrite picture/attachment links
	if (!empty($JJSCMSAttachUrl) && !empty($JJSCMSPublishAttachUrl))
	{
		$JJSCMSPublishROSPatterns['/([\'"])' . str_replace('/','\/', $JJSCMSAttachUrl) . '\/([^\1]+)\1/Us'] = '\1' . $JJSCMSPublishAttachUrl . '\2\1' ;
	}
	
	// rewrite pub links
	if (!empty($PubDirUrl) && !empty($JJSCMSPublishPubDirUrl))
	{
		$JJSCMSPublishROSPatterns['/([\'"])' . str_replace('/','\/', $PubDirUrl) . '\/(.*)[\'"]/Us'] = '\1' . $JJSCMSPublishPubDirUrl . '\2\1' ;
	}
	
	
	// apply $JJSCMSPublishROSPatterns before saving
	//
	$error = '';
	$x = $buffer;
		
	foreach ($JJSCMSPublishROSPatterns as $pattern => $replace)
	{
		$lastgood = $x;
		$x = preg_replace($pattern, $replace, $x);
		if (NULL == $x || '' == $x) 
		{
			$error .= "\n\n" . 'no output from JJSCMSPublishROSPatterns[\'' . $pattern . '\'] = ' . $replace;
			$x = $lastgood;
		}
	}

	$fh = fopen($filename,'w');
	if (!$fh)
	{
		$error .= "\n" . 'JJSCMS failed opening output file. "' . $filename . '"'; 
	}
	else
	{
		$written = fwrite($fh, $x); 
		if (!$written)
		{
			$error .= "\n" . 'JJSCMS failed writing to output file "' . $filename . '"';
		}
	}
	fclose($fh);
	

	// remove public only sections
  $x = preg_replace(
		'/\<\!\-\- ' . $JJSCMSPublicSection . ' \-\-\>.*\<\!\-\- \/' . $JJSCMSPublicSection . ' \-\-\>/Us',
		'', $buffer);

	// append error msg
	if ('' != $error)
	{
		$x .= "\n" . '<!-- ' . $error . ' -->';
	}	
	return $x;
	
} // JJSCMSObCallback
 
/**
*JJSCMSHandlePublish
* install JJSCMSObCallback to capture all output from the "browse" action
*/
function JJSCMSHandlePublish($pagename, $auth='jjscmspublish')
{
	global
		$HandleActions,
		$JJSCMSAction,
		$jjsSession,
		$jjsUseTemplate;
	
			
	
	/** if jjsapprovepage is used don't publish if not approved rev
	*/	
	if (defined('JJSAPPROVEPAGE')) 
	{
		$page = RetrieveAuthPage($pagename, $auth, true);
		if (!$page) { Abort("?unable to read $pagename"); }
		if (@$page['jjsApprovePageRev']) 
		{
			if ('any' == $page['jjsApprovePageRev'])
			{
				$canpublish = true;
			}
			elseif (0 > intval($page['jjsApprovePageRev']))
			{
				$canpublish = false;
			}
			elseif (defined('JJSEDITREV') && @$page['jjsEditRev'])
			{
				$canpublish = intval($page['jjsEditRev']) == intval($page['jjsApprovePageRev']);
			}			
		}
		else
		{
			$canpublish = false;
		}
	}
	else
	{
		$canpublish = true;
	}
	
	if (!$canpublish)
	{
		if (isset($_REQUEST['jjsiterator']))
		{
			// don't stop iteration
			$HandleActions[$JJSCMSAction]($pagename);	
			return;
		}
		else
		{
			$errmsg = FmtPageName('revision mismatch - must approve page before publishing <a href="$PageUrl">$Group.$Name</a> $jjsEditRev != $jjsApprovePageRev ', $pagename);
			Abort($errmsg);
		}
	}
	
	ob_start('JJSCMSObCallback');
	$HandleActions[$JJSCMSAction]($pagename);
	
	if ($jjsUseTemplate)
	{
		$jjsTemplateSrc = ob_get_contents();	
		ob_end_clean();
	
		// post-post-process output 		
		
		$smarty = new c_template();
		
		$smarty->setSrc($jjsTemplateSrc);
		
		if (isset($jjsSession))
		{
			$smarty->assign_by_ref('session', $jjsSession);
		}
		
		$smarty->display('var:smarty_tpl_src');
		#echo $jjsTemplateSrc;
	}
	else
	{
		ob_end_flush();
	}	
} // JJSCMSHandlePublish

$HandleActions['jjscmspublish'] = JJSCMSHandlePublish;
$HandleAuth['jjscmspublish'] = 'jjscmspublish';
$PageAttributes['passwdjjscmspublish'] = '$[set new publish password]';
$DefaultPasswords['jjscmspublish'] = '';
$AuthCascade['jjscmspublish'] = 'edit';