<?php
if(!defined('DOKU_INC')) die();
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');

class syntax_plugin_conform extends DokuWiki_Syntax_Plugin 
{
    function getInfo()
    {
        return array(
            'author' => 'William Fletcher',
            'email'  => 'uiriamu.furecchaa@gmail.com',
            'date'   => '2008-09-08',
            'name'   => 'conform',
            'desc'   => 'Creates HTML forms properly',
            'url'    => 'http://thirdforces.internationalconspiracy.org/~ultraviolet/software/conform/',
        );
    }

    function getType()
    {
        return 'substition';
    }

    function getPType()
    {
        return 'block';
    }

    function getSort()
    {
        return 999;
    }

    function connectTo($mode) 
    {
        $this->Lexer->addEntryPattern('<CONFORM.*?>(?=.*?</CONFORM>)',$mode,'plugin_conform');
    }

    function postConnect() 
    {
	$this->Lexer->addExitPattern('</CONFORM>', 'plugin_conform');
    }

    function handle($match, $state, $pos, &$handler) 
    {
	switch ($state) 
	{
	    case DOKU_LEXER_UNMATCHED:
		if ( !$conform =& plugin_load('helper', 'conform') ) return false;
		return $conform->conformExtract($match);
		break;
	}
	return false;
    }

    function conformError(&$renderer, $message)
    {
	$renderer->doc .= '<span style="color:#FF0000;">'.$message.'</span><br>';
    }

    function conformCreateEmailInput($arg)
    {
	switch($arg[0])
	{
	    case 'Checkbox':
		if ( isset($_POST["$arg[1]"]) )
		{
		    return "Yes";
		}
		else
		{
		    return "No";
		}
	    default:
		return htmlspecialchars($_POST["$arg[1]"]);
	}
    }

    function conformCreateInput($arg)
    {
	switch($arg[0])
	{
	    case 'Textbox':
		$textbox  = "<input class=\"edit\" type=\"text\" name=\"$arg[1]\" style=\"width:".$arg[3]."px;\"";
		$textbox .= " value=\"".htmlspecialchars($_POST["$arg[1]"])."\"";
		$textbox .= ">";
		return $textbox; 
	    case 'Textarea': 
		$textarea  = "<textarea class=\"edit\" name=\"$arg[1]\" rows=\"$arg[3]\" style=\"width:".$arg[4]."px;\">";
		$textarea .= htmlspecialchars($_POST["$arg[1]"]);
		$textarea .= "</textarea>";
		return $textarea;
		break;
	    case 'Checkbox':
		$checked = "";
		if ( isset($_POST["id"]) )
		{
		    if ( $_POST["$arg[1]"] == "on" ) $checked = "checked";
		}
		else
		{
		    if ( $arg[3] == 1 ) $checked = "checked";
		}
		$checkbox  = "<input type=\"checkbox\" name=\"$arg[1]\" $checked>";
		return $checkbox;
		break;
	    case 'Radio':
		$radiocount = 0;
		if ( ! isset($_POST["$arg[1]"]) ) $checked = " checked='checked'";
		foreach ( $arg[3] as $value )
		{
		    if ( $value == $_POST["$arg[1]"] ) $checked = " checked='checked'";
		    $radio .= "<input type=\"radio\" name=\"$arg[1]\" value=\"$value\"$checked>$value<br>";
		    $checked = "";
		}
		return $radio; 
		break;
	    case 'Select':
		$select   = "<select name=\"$arg[1]\">";
		$selected = "";
		foreach ( $arg[3] as $value )
		{
		    if ( $value == $_POST["$arg[1]"] ) $selected = "selected";
		    $select  .= "<option $selected>$value</option>";
		    $selected = "";  
		}
		$select .= "</select>";
		return $select;
	    default:
		return "ERROR! ERROR! ERROR! Attempting to create an unsupported input maybe?"; 
	}
    }

    function conformConstraintArgCheck($constraintname, $postname, $constraints, &$renderer)
    {
	foreach ( $constraints as $constraint ) 
	{
	    if ( $constraintname == $constraint[1] )
	    {
		if ( ! isset($_POST["$postname"]) )
		{ 
		    $this->conformError($renderer, "Constraint $postname checked against a value that wasn't posted!");
		    return false;
		}
		$post = $_POST["$postname"];
		$check = explode("=", $constraint[3], 2);
		if ( ( $check[0] == 'maxLength' && strlen($post) > $check[1] ) ||
                     ( $check[0] == 'minLength' && strlen($post) < $check[1] ) )
		{
		    $this->conformError($renderer, "$constraint[2]");
		    return false;
		}
	    }
	}
	return true;
    }

    function conformConstraintCheck($constraints, $tables, &$renderer)
    {
	foreach ( $tables as $table )
	{
	    $args = &$table['args'];
	    if ( count($args) == 0 ) continue;
	    switch($table['mode'])
	    {
		case 0:
		    foreach ( $args as $arg )
		    {
		    	switch($arg[0])
		    	{
			    case 'Submit':
			    case 'Line':
			    case 'Static':
			    case 'Radio':
			    case 'Checkbox':
			    case 'Select':
				break;
			    default:
				if ( $this->conformConstraintArgCheck($arg[1], "$arg[1]", $constraints, $renderer) == false )
				{
				    $this->conformConstrained = $arg[1];
				    return false;
				}
			}
		    }
		    break;
		case 1:
		    if ( $table['complete'] == 0 ) break;
		    $rows = $table['rows'];
		    for ( $row = 1; $row <= $rows; $row++ )
		    {
			foreach ( $args as $arg )
			{
			    switch($arg[0])
			    {
				case 'Submit':
				case 'Line':
				case 'Static':
				case 'Radio':
				case 'Checkbox':
				case 'Select':
				    break;
				default:
				    if ( $this->conformConstraintArgCheck($arg[1], "$arg[1]_$row", $constraints, $renderer) == false )
				    {
					$this->conformConstrained = $arg[1];
					return false;
				    }
			    }
			}
		    }
		    break;
	    }
	}
	return true; 
    }

    function conformCreateDescription($text, $postname)
    {
	if ( isset($_POST["id"]) && $postname == $this->conformConstrained )
	{
	    return '<span style="color:#FF0000;">'.$text.'</span><br>';
	}
	return $text;
    }

    function render($format, &$renderer, $data) 
    {
	global $ID;
	if( $format == 'xhtml' )
	{
	    session_start();
	    $formaction = DOKU_URL . "doku.php";
	    $renderer->info['cache'] = false;
	    if ( $data == false ) return false;
	    if ( ! is_array($data) ) return false;
	    if ( ! in_array($ID,  $data['idallow']) ) 
	    {
		$this->conformError($renderer, "Conform not allowed on this page! Please ask the admin to rectify this!");
		return true;
	    }
	    if ( count($data['errors']) > 0 )
	    {
		foreach ( $data['errors'] as $error )
		{
		    $this->conformError($renderer, $error);
		}
	    }
	    $tables = &$data['tables'];
	    $email = false;
	    if ( isset($_POST["id"]) )
	    {
		if ( $this->conformConstraintCheck($data['constraints'], $tables, $renderer) == true )
		{
		    $email = true;
		}
	    }
	    if ( $email == false )
	    {
		$form .= "<form action=\"$formaction\" method=\"post\" accept-charset=\"utf-8\" enctype=\"multipart/form-data\">\n";
		$_SESSION["conform_emailed"] = false;
	    }
	    $form .= "<table class=\"conform\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n";
	    $maxcolumns = $data['maxcolumns']; 
	    if ( $maxcolumns < 2 )
	    {
		$columns    = 2;
		$maxcolumns = 2;
	    }
	    else
	    {
		$columns = $maxcolumns;
	    }
	    foreach ( $tables as $table ) 
	    {
		$args = &$table['args'];
		if ( count($args) == 0 ) continue;
		switch($table['mode'])
		{
		    case 0:
			foreach ( $args as $arg )
			{
			    switch($arg[0])
			    {
				case 'Submit':
				    $submit = $arg;
				    break;
				case 'Line':
				    $form .= "<tr><td colspan=\"$columns\"><br></td></tr>\n";
				    break;
				case 'Static':
				    $form .= "<tr><td colspan=\"$columns\">$arg[1]</td></tr>\n";
				    break;
				default: 
                                    if ( $email == false )
                                    {
					$input = $this->conformCreateInput($arg);
                                    }
                                    else
                                    {
					$input = $this->conformCreateEmailInput($arg); 
                                    }
				    $form .= "<tr><td colspan=\"".($columns - 1 ).
					              "\">".$this->conformCreateDescription($arg[2], $arg[1])."</td><td>$input<br></td></tr>\n";
			    }
			}
			break;
		    case 1:
			if ( $table['complete'] == 0 ) break;
			$rows       = $table['rows'];
			$argcolumns = $table['columns']; 
			for ( $row = 0; $row <= $rows; $row++ )
			{
			    $form .= "<tr>\n";
			    $argcount = 0;
			    foreach ( $args as $arg )
			    {
				switch($arg[0])
				{
				    case 'Submit':
					$submit = $arg;
					break;
				    case 'Line':
					break;
				    case 'Static':
					break;
				    default:
					$colspan = "";
					if ( $argcount == $argcolumns ) $colspan = " colspan=\"".($maxcolumns - $argcolumns)."\"";
					if ( $row > 0 ) 
					{
					    $arg[1] .= "_$row";
					    if ( $email == false )
					    {
						$input = $this->conformCreateInput($arg);
					    }
					    else
					    {
						$input = $this->conformCreateEmailInput($arg); 
					    }
					    $form .= "<td$colspan>$input<br></td>\n";
					}
					else
					{
					    $form .= "<td$colspan>".$this->conformCreateDescription($arg[2], $arg[1])."</td>\n";
					}
				}
				$argcount++;
			    }
			    $form .= "</tr>\n";
			}
			break;
		}
	    }
	    if ( count($data['errors']) == 0 && $email == false ) 
	    {
		$form .= "<tr><td colspan=\"$maxcolumns\"><input class=\"button\" type=\"submit\" name=\"submit\" value=\"$submit[1]\"";
		$form .= "style=\"width:".$submit[2]."px;\"></td></tr>\n";
		$form .= "<input type=\"hidden\" name=\"id\" value=\"$ID\" />\n";
		$form .= "</form>"; 
	    }
	    $form .= "</table>\n";
	    if ( $email == true )
	    {
		$theboundary = md5(uniqid(""));
		$header = "From: ".$this->getConf('conformFrom');
		$header .= "\r\nMIME-Version: 1.0";
		$header .= "\nContent-Type: text/html";
		$header .= "\r\nX-Priority: 3";
		$header .= "\r\nX-MSMail-Priority: Normal";
		$header .= "\r\n";
		if ( $_SESSION["conform_emailed"] == false ) 
		{
		    $emailform  = "<html><body>";
		    $emailform .= "<style>";
		    $emailform .= "body { padding: 0; border-spacing: 0; border-collapse: collapse; }";
		    $emailform .= "table.conform { border: 1px solid #000000; padding: 0px; margin: 5px; border-spacing: 0; }";
		    $emailform .= "table.conform td { border: 1px solid #000000; padding 0px; margin: 5px; border-spacing: 0; }";
		    $emailform .= "</style>";
		    $emailform .= $form;
		    $emailform .= "</body></html>";
		    mail($data['to'], $data['subject'], $emailform, $header); 
		}
		$_SESSION["conform_emailed"] = true;
	    }
	    $renderer->doc .= $form;
	    return true;
	}
	return false;
    }
}
?>
