<?php if (!defined('PmWiki')) exit();

/*	=== EditAttributes ===
 *	Copyright 2009 Eemeli Aro <eemeli@gmail.com>
 *
 *	Edit a page's title, description and other attributes
 *	using separate EditForm fields
 *
 *	Developed and tested using PmWiki 2.2.x,
 *	partly based on Mike Shanley's EditMore
 *
 *	To install, first add the following to your config file,
 *	adjusted for your configuration:

		$EditAttrFields = array(
			'title' => array(
				'attribute' => 1,
				'markup' => '(:title $1:)',
				'filter' => 'EditAttrAutofillTitle' ),
			'description' => array( 'attribute' => 1, 'markup' => '(:description $1:)' ),
			'keywords' => array( 'attribute' => 1, 'markup' => '(:keywords $1:)' )
		);
  		include_once("$FarmD/cookbook/editattr.php");

 *  Next, add the matching input fields to your Site.EditForm,
 *  these are of the form (:input e_FIELDNAME:) -- eg. (:input e_title:)
 *
 *	For more information, please see the online documentation at
 *		http://www.pmwiki.org/wiki/Cookbook/EditAttributes
 *
 *	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['EditAttributes']['Version'] = '2009-07-30';

if (empty( $EditAttrFields )) return;

$EditFields = array_merge( $EditFields, array_keys($EditAttrFields) );
$SaveProperties = array_diff( $SaveProperties, array_keys($EditAttrFields) );

array_unshift($EditFunctions,'EditAttrBeforePost');
array_push($EditFunctions,'EditAttrAfterPost');

function EditAttrAutofillTitle( $pagename, $fn, &$new ) {
	global $SearchPatterns, $EditAttrAutofillTitlePatterns;

	if ( ($fn!='title') || @$new['title'] || isset($_POST['title']) || isset($_REQUEST['template']) ) return;

	SDVA( $EditAttrAutofillTitlePatterns, array(
		'recent' => $SearchPatterns['normal']['recent'],
		'group' => $SearchPatterns['normal']['group'],
		'admin' => '!^(Site|SiteAdmin|PmWiki)\.!',
		'nonbase' => '!\b(SideBar|Draft)$!' ));

	if ( MatchPageNames( $pagename, $EditAttrAutofillTitlePatterns ) )
		$new['title'] = FmtPageName('$Title',$pagename);
}

function EditAttrRequireNotEmpty( $pagename, $fn, &$new ) {
	global $MessagesFmt, $EnablePost;
	if (empty( $new[$fn] )) {
		$MessagesFmt[] = "<h3 class='wikimessage'>$[$fn is required.]</h3>";
		$EnablePost = 0;
	}
}

function EditAttrBeforePost( $pagename, &$page, &$new ) {
	global $EnablePost, $PageAttributes, $HandleAuth, $Now, $EditAttrFields;

	foreach( $EditAttrFields as $fn => $fa ) {
		## require attr level authentication to edit password fields
		if ( isset( $PageAttributes[$fn] ) || !strncmp($fn,'passwd',6) ) $fa['auth'] = 'postattr';

		if ( @$fa['auth'] && ( $fa['auth'] != 'edit' )
			&& !RetrieveAuthPage( $pagename, $HandleAuth[ $fa['auth'] ], FALSE, READPAGE_CURRENT )
		) $new[$fn] = @$page[$fn];

		if ( is_callable(@$fa['filter']) ) $fa['filter']( $pagename, $fn, $new );

		## save history
		if ( (@$fa['attribute'] > 1)
			&& ( ( @$new[$fn] != @$page[$fn] )
				|| ( !empty($new[$fn]) && !preg_grep("/^$fn:/", array_keys($page)) )
			) ) $new["$fn:$Now"] = @$new[$fn];

		## add page text markup
		if ( @$fa['markup'] && !empty( $new[$fn] ) ) {
			$fm = is_array($fa['markup']) ? reset($fa['markup']) : $fa['markup'];
			if ( strlen($fm) > 0 ) {
				$repl = array(
					'$0' => $new[$fn],
					'$1' => str_replace(
						array(  ':)', "\n", "\r", "\x0B" ),
						array( ': )',  ' ',  ' ',    ' ' ), $new[$fn] ) );
				$new['text'] .= "\n" . str_replace( array_keys($repl), array_values($repl), $fm );
			}
		}

		## cache attribute values for page preview
		if ( !$EnablePost && isset($new[$fn]) && @$fa['attribute'] ) PCache( $pagename, array( $fn => $new[$fn] ) );

		## remove blanks & markup-only fields
		if ( ( empty($new[$fn]) || empty($fa['attribute']) ) && ( $fn != 'text' ) ) unset($new[$fn]);
	}
}

function EditAttrKeep($x) {
	global $KeepToken, $KPV, $KPCount;
	$x = preg_replace("/$KeepToken(EA\\d.*?)$KeepToken/e", '$KPV[\'$1\']', $x);
	$KPV['EA'.(++$KPCount)] = $x;
	return $KeepToken.'EA'.$KPCount.$KeepToken;
}

function EditAttrAfterPost( $pagename, &$page, &$new ) {
	global
		$PageAttributes, $HandleAuth, $InputTags, $CondTextPattern, $KPV, $KeepToken,
		$EditAttrPreserve, $EditAttrFields;

	SDVA( $EditAttrPreserve, array( 'if' => $CondTextPattern ) );
	foreach ( $EditAttrPreserve as $p ) if (!empty($p))
		$new['text'] = preg_replace($p, 'EditAttrKeep(\'$0\')', $new['text']);

	foreach( $EditAttrFields as $fn => $fa ) {
		$pat = empty($fa['markup'])
			? FALSE
			: ( is_array($fa['markup'])
				? reset(array_keys( $fa['markup'] ))
				: str_replace( array('\$0','\$1'), '(.*?)', preg_quote($fa['markup'],'/') ) );

		if ( $pat && preg_match("/$pat/i", $new['text'], $matches) ) {
			$new[$fn] = $matches[1];
			$new['text'] = preg_replace("/\\n?$pat/i", '', $new['text']);
		}

		if ( @$fa['auth'] && ( $fa['auth'] != 'edit' )
			&& !RetrieveAuthPage( $pagename, $HandleAuth[ $fa['auth'] ], FALSE, READPAGE_CURRENT )
		) {
			$new[$fn] = '(protected)';
			SDV( $InputTags["e_$fn"]['disabled'], 'disabled' );
		}

		if ( @$fa['input'] && is_array($fa['input']) ) SDVA( $InputTags["e_$fn"], $fa['input'] );

		SDVA( $InputTags["e_$fn"], array(
			':html' => "<input type='text' \$InputFormArgs />",
			'name' => $fn, 'size' => '60', 'title' =>'Title',
			'value' => str_replace('$','&#036;',htmlspecialchars(@$new[$fn],ENT_NOQUOTES)) ));
		if (preg_match('/\stype=([\'"]?)checkbox\1/', $InputTags["e_$fn"][':html'])) {
			$InputTags["e_$fn"]['value'] = '1';
			if (!empty($new[$fn])) $InputTags["e_$fn"]['checked'] = '1';
		}
	}

	$new['text'] = preg_replace("/$KeepToken(EA\\d.*?)$KeepToken/e", 'PSS($KPV[\'$1\'])', $new['text']);
}