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

/*	=== OpenSearch ===
 *	Copyright 2009 Eemeli Aro <eemeli@gmail.com>
 *
 *	Add OpenSearch autodiscovery & suggestions to PmWiki
 *
 *	Developed and tested using PmWiki 2.2.0,
 *
 *	To install, first add the following to your config file,
 *	adjusted for your configuration:

  		include_once("$FarmD/cookbook/opensearch.php");

 *	For more information, please see the online documentation at
 *		http://www.pmwiki.org/wiki/Cookbook/OpenSearch
 *
 *	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['OpenSearch']['Version'] = '2009-02-20';

SDV( $OpenSearchUrl, $ScriptUrl );

$HTMLHeaderFmt['opensearch'] =
	"\n<link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"$OpenSearchUrl?action=opensearchdescription\" title=\""
	. ( empty($OpenSearchData['ShortName']) ? $WikiTitle : $OpenSearchData['ShortName'] )
	. '" />';

if ( !in_array( $action, array( 'search', 'suggest', 'opensearchdescription' ) ) ) return;

$HandleActions['search'] = 'HandleSuggestedSearch'; // default 'HandleSearchA'
$HandleActions['suggest'] = 'HandleSuggest';
$HandleAuth['suggest'] = 'read';
$HandleActions['opensearchdescription'] = 'HandleOpenSearchDescription';
$HandleAuth['opensearchdescription'] = 'read';

function HandleSuggestedSearch( $pagename, $level = 'read' ) {
	$rq = htmlspecialchars(stripmagic(@$_REQUEST['q']), ENT_NOQUOTES);
	if ( $rq && ( substr_count( $rq, '.' ) == 1 ) && PageExists($rq) ) Redirect($rq);
	HandleSearchA( $pagename, $level );
}

function HandleOpenSearchDescription( $pagename, $level = 'read' ) {
	global $WikiTitle, $Charset, $OpenSearchData, $OpenSearchUrl;

	header("Content-type: application/opensearchdescription+xml; charset=UTF-8");

	// see http://www.opensearch.org/Specifications/OpenSearch/1.1 for all valid elements
	SDVA( $OpenSearchData, array(
		'ShortName' => substr( $WikiTitle, 0, 16 ),
		'Description' => "Search $WikiTitle"
	) );

	echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\" xmlns:ms=\"http://www.mozilla.org/2006/browser/search/\">
	<Url type=\"application/opensearchdescription+xml\" rel=\"self\" template=\"$OpenSearchUrl?action=opensearchdescription\"/>
	<Url type=\"application/x-suggestions+json\" template=\"$OpenSearchUrl?action=suggest&amp;q={searchTerms}\"/>
	<Url type=\"text/html\" template=\"$OpenSearchUrl?action=search&amp;q={searchTerms}\"/>
	<ms:SearchForm>$ScriptUrl</ms:SearchForm>\n";

	foreach( $OpenSearchData as $k => $v ) {
		if ( $Charset != 'UTF-8' ) $v = mb_convert_encoding( $v, 'UTF-8', $Charset );
		if ( ( $k == 'Image' ) && !strcasecmp( substr( $v, -3 ), 'ico' ) )
			echo "\t".'<Image height="16" width="16" type="image/x-icon">'.$v."</Image>\n";
		else echo "\t<$k>$v</$k>\n";
	}

	echo '</OpenSearchDescription>';
}

function HandleSuggest( $pagename, $level = 'read' ) {
	global $Charset, $SearchPatterns, $OpenSearchSuggestMaxResults;

	SDV( $OpenSearchSuggestMaxResults, 10 );

	$rq = htmlspecialchars( stripmagic(@$_REQUEST['q']), ENT_NOQUOTES );

	$json[0] = $rq;
	$json[1] = array();
	if ($rq) {
		$ls = ListPages( "/$rq/i" );
		if ($ls) {
			sort($ls);
			$group_begins = preg_grep( "/^$rq/i", $ls );
			$name_begins = preg_grep( "/\.$rq/i", $ls );
			$casematch = preg_grep( "/^$rq/", $ls );
			$doubles = strlen($rq)>1 ? preg_grep( "/$rq.*$rq/i", $ls ) : array();
			$ls = array_slice(array_unique(array_merge( $group_begins, $name_begins, $casematch, $doubles, $ls )), 0, $OpenSearchSuggestMaxResults );

			$json[1] = $ls;
			foreach ( array( 2=>'$Title', 3=>'$PageUrl' ) as $i => $var ) foreach( $ls as $pn ) {
				$json[$i][] = PageVar( $pagename, $var, $pn );
			}
		}
	}

	header("Content-type: application/x-suggestions+json; charset=$Charset");

	//echo json_encode($json);
	echo '[';
	foreach( $json as $i => $a ) {
		if ($i) echo ',';
		$a = str_replace( array('\\','"'), array('\\\\','\\"'), $a );
		if (is_array($a)) {
			echo '[';
			foreach( $a as $j => $s ) {
				if ($j) echo ',';
				echo '"'.$s.'"';
			}
			echo ']';
		} else echo '"'.$a.'"';
	}
	echo ']';

	exit;
}