<?php
// PukiWiki - Yet another WikiWikiWeb clone.
// $Id: treeview.inc.php,v 1.0 2010/07/11 00:00:00 acompass.net Exp $
//
// treeview plugin - Construct treeview using JavaScript.
// compass.js is needed.
// License: GPL v2 or (at your option) any later version
// Usage :  #treeview(option1,option2) {{ items }}
//          option1 : none : defined at item
//                    *    : defined at item
//                    +    : all collasped
//                    -    : all expanded
//          option2 : none    : default = count
//                    count   : count
//                    nocount : nocount
//          option3 : none    : default = page
//                    menu    : Menu
//          items   : ****item : collasped
//                    ***+item : collasped
//                    ***-item : expanded
//                    PageName
//          item    : Text, [[Alias>PageName]], [[LinkName:URL]]
function plugin_treeview_convert()
{
	global $vars, $menubar;
	global $_title_invalidwn, $_msg_notfound;
	$option = array();
	$arg_num = func_num_args();
	$args = func_get_args();
	$pre_uri = get_script_uri();
	// Default設定
	$option1 = '';
	$option2 = 'count';
	$option3 = '';
	$html = '';
	$opflg1 = FALSE;
	$opflg2 = FALSE;
	$opflg3 = FALSE;

	// Option Check
	for ( $i = 0; $i < $arg_num; $i++ ) {

		$option = treeview_check_option( $args[$i] );

		switch ( $option['type'] ) {
		case 'text' :
			if ( $i == $arg_num-1) {
				// NOP
			}
			else {
				$html = 'Invalid option [' . $args[$i] . ']';
				return $html;
			}
			break;
		case 'error' :
			$html = 'No menu items are defined.';
			return $html;
			break;
		case 'option1' :
			if ( $opflg1 == TRUE ) {
				$html = 'Redefined option [' . $args[$i] . ']';
				return $html;
			}
			$option1 = $option['value'];
			$opflg1 = TRUE;
			break;
		case 'option2' :
			if ( $opflg2 == TRUE ) {
				$html = 'Redefined option [' . $args[$i] . ']';
				return $html;
			}
			$option2 = $option['value'];
			$opflg2 = TRUE;
			break;
		case 'option3' :
			if ( $opflg3 == TRUE ) {
				$html = 'Redefined option [' . $args[$i] . ']';
				return $html;
			}
			$option3 = $option['value'];
			$opflg3 = TRUE;
			break;
		default :
			$html = 'treeview.inc.php System Error.';
			return $html;
		}
	} // End of for

	$tree_id =  ($option3 == 'menu') ? 'treeview' : 'treeview1';
	$subsp   =  ($option3 == 'menu') ? '' : 't';

	// Create Lines
	$text   = $args[$arg_num -1];
	$lines = mbsplit("\r" ,$text);
	$line_count = count($lines);

	// Check page defined : Not supported
	if ( $line_count == 1 ) {
		$level = count_level( $lines[0] );
		if ( $level == 0 ) {
			$html = 'ページ定義方式は使用できません。 : ' . $lines[0];
			return $html;
		}
	}

	// Create HTML by lines
	$html = '<div class="treeview" id="' . $tree_id . '"><ul align="left">';
	$current_level = 0;
	$li_num = 0;
	for ( $i=0; $i < $line_count; ++$i ) {
		unset($lname);
		unset($href);
		unset($anchor);
		if ( $lines[$i] == "" ) {
			continue;
		}
		$level = count_level( $lines[$i], $type );
		$num = count_child( $lines, $i, $level );
		if ( $option1 != '' ) {
			$type = $option1;
		}

		$lname = link_name( $lines[$i], $level );
		$text = $lname['text'];
		if ( isset( $lname['href'] ) ) {
			$href = $lname['href'];
		}
		if ( isset( $lname['anchor'] ) ) {
			$anchor = $lname['anchor'];
		}
		$mod  = $lname['mod'];

		switch( $mod ) {
		case 0 : // HiperLink. http:....
		case 4 : // Title
			break;
		case 3 : $href = $text; // BracketName
		case 2 :                // Alias
		case 1 :                // Alias #Anchor
			if (! is_pagename($href)) {
				$href = $_title_invalidwn;
				$mod = 0;
				break;
			}
			if (! is_page($href)) {
				$href = $_msg_notfound;
				$mod = 0;
			}
			if ( $mod == 1 ) {
				$href .= $anchor;
			}
			break;
		default :
			$href = 'treeview.inc.php System Error.';
			$mod = 0;
			break;
		}

		if ( $num <= 0 ) {
			if ($href == '' ) {
				$temp = '<li>' . $text . '</li>' . "\n";
			} else {
				if ( $mod == 0 ) {
					$temp = '<li><a href="' . $href . '">' . $text . '</a></li>' ."\n";
				} else {
					$temp = '<li><a href="' . $pre_uri . '?' . $href . '">' . $text . '</a></li>' ."\n";
				}
			}
			if ( $num < 0 ) {
				for ( $j = 0; $num < $j; $j-- ) { 
					$temp = $temp . '</ul></li>';
				}
				$temp = $temp . "\n";
			}
		} else { // Expand
			$li_num = $li_num + 1;
			if ( $type == '-' ) {
					$temp = '<li class="expanded" id="li' . $subsp . $li_num . '">';
			}
			else {
				$temp = '<li class="collapsed" id="li' . $subsp . $li_num . '">';
			}

			$span = '';
			if ( $option2 == 'count' ) {
				$span = '<span class="count">(' . $num . ')</span>';
			}
			if ($href == '' ) {
				$temp = $temp . $text . $span;
			} else {
				if ( $mod == 0 ) {
					$temp = $temp . '<a href="' . $href . '">' . $text . $span . '</a>';
				} else {
					$temp = $temp . '<a href="' . $pre_uri . '?' . $href . '">' . $text . $span . '</a>';
				}
			}

			if ( $type == '-' ) {
				$temp = $temp . '<ul style="display:block">' . "\n";
			}
			else {
				$temp = $temp . '<ul style="display:none">' . "\n";
			}
		}
		$html = $html . $temp;
	} // End of for

	$html = $html . '</ul></div>'. "\n";
	return $html;
}

function treeview_check_option( $parm ) {

	$option = array();

	switch ( $parm ) {
	case '*' :
		$option['type'] = 'option1';
		$option['value'] = '';  // Default. Defined at item.
		break;
	case 'collasped' :
	case '+' :
		$option['type'] = 'option1';
		$option['value'] = '+';  // Collasped
		break;
	case 'expanded' :
	case '-' :
		$option['type'] = 'option1';
		$option['value'] = '-';  // Expanded
		break;
	case 'count' :
		$option['type'] = 'option2';
		$option['value']  = $parm;
		break;
	case 'nocount' :
		$option['type'] = 'option2';
		$option['value'] = $parm;
		break;
	case 'menu' :
		$option['type'] = 'option3';
		$option['value'] = $parm;
		break;
	default :
		if ( 0 < strlen($parm) ) {
			$option['type'] = 'text';
			$option['value'] = $parm;
		}
		else {
			$option['type'] = 'error';
		}
		break;
	}

	return $option;

}

function count_level( $line, & $expand ) {
	$matches = array();
	$level = 0;

	preg_match('/^(\*|\+|\-)+/', $line, $matches);

	$level = strlen($matches[0]);
	$expand = substr($matches[0], $level-1, 1);
	return $level;
}

function count_child( $lines, $start, $level ) {
	$child = 0;
	$line_count = count($lines);
	if ( $start == $line_count ) {
		return  -$level;
	}
	for ( $i = $start+1; $i < $line_count; $i++ ) {
		if ( $lines[$i] == "" ) {
			continue;
		}
		$next_level = count_level( $lines[$i], $expand );
		if ( $level < $next_level ) {
			$child++;
		}
		if ( $level == $next_level ) {
			return $child;
		}
		if ( $next_level < $level ) {
			if ( 0 < $child ) {
				return $child;
			}
			return $next_level - $level;
		}
	}
	return $child;
}

function link_name( $line, $level ) {
	$matches = array();
	$lname = array();
	$work = substr($line, $level);
	$patterns = array();

	$p_txt = '(?P<text>.+)?';
	$p_uri = "(?P<href>(?:(?:https?|ftp):\/\/)[\w\/\@\$()!?&%#:;.,~'=*+-]+)";
	$p_ref = '(?P<href>.+)';
	$p_pre = '(^\[\[)';
	$p_pos = '(\]\])$';
	$p_ank = '(?P<anchor>(\#(?:[a-zA-Z][\w-]*)?))';
	$p_brk = '\>';
	// No.    Type           Example
	//  0 : HiperLink      [[Alias>HiperLink]]
	//  1 : Alias #Anchor  [[Alias>PageName#Anchor]]
	//  2 : Alias          [[Alias>PageName]]
	//  3 : BracketName    [[PageName]]
	//  4 : Title          Title
	$patterns[0]='/'.$p_pre.$p_txt.$p_brk.$p_uri.$p_pos.'/';//[[Alias>HiperLink]]
	$patterns[1]='/'.$p_pre.$p_txt.$p_brk.$p_ref.$p_ank.$p_pos.'/';//[[Alias>PageName#Anchor]]
	$patterns[2]='/'.$p_pre.$p_txt.$p_brk.$p_ref.$p_pos.'/';//[[Alias>PageName]]
	$patterns[3]='/'.$p_pre.$p_txt.$p_pos.'/';//[[PageName]]
	$patterns[4]='/(?P<text>.+)/';//Title

	foreach( $patterns as $mod => $pattern ) {
		preg_match($pattern , $work, $matches);
		if ( isset( $matches['text'] ) ) {
			break;
		}
	}

	$lname['mod'] = $mod;
	if ( isset( $matches['text'] ) ) {
		$lname['text'] = $matches['text'];
	}
	if ( isset( $matches['href'] ) ) {
		$lname['href'] = $matches['href'];
	}
	if ( isset( $matches['anchor'] ) ) {
		$lname['anchor'] = $matches['anchor'];
	}
	return $lname;
}

?>
