KLEmailForm

Jump to: navigation, search

This MediaWiki extension is used to create an email form in any article. Both the form fields and the response to submittal are formatted using standard wikitext. Upon submittal, the user is returned to the same page and the response is displayed in place of the form.

See Help:KLEmailForm for a discussion of usage.

Installation

To install:

  • Copy the code from the code block at the end of this page to the file $IP/extensions/KLEmailForm.php
  • Add this line to LocalSettings.php: require_once("$IP/extensions/KLEmailForm.php");

Code

<?php
/**
 * KLEmailForm.php
 * This extension inserts a form mailer into a page
 * written by Kennylucius http://kennylucius.com/
 * LocalSettings.php file:
 * require_once("$IP/extensions/KLEmailForm.php");
 */
 
define("EMAILFORM_NAME",  "EmailForm");            // Name of tag
define("EMAILFORM_SUBMIT_BUTTON", "Submit Email"); // Name of POST identifier flag
 
if(! defined( 'MEDIAWIKI' ) ) {
    die("This is not a valid entry point.\n");
}

$wgExtensionCredits['parserhook'][] = array(
	 'name' => 'KLEmailForm',
	 'version' => '0.1',
	 'author' =>'Kenny Lucius', 
	 'url' => 'http://www.kennylucius.com/KLEmailForm',
	 'description' => 'Inserts an email form into a page via <EmailForm>'
	 );
 
# EmailForm MediaWiki extension
$wgExtensionFunctions[] = "wfKLEmailForm_Extension";

function wfKLEmailForm_Extension() {
	global $wgParser;
	// set hook for <EmailForm> ... </EmailForm>
	$wgParser->setHook(EMAILFORM_NAME, 'renderKLEmailForm' );
}

// Callback function for converting wikitext to HTML output
// Normally, a form is returned. If the submit button was pressed
$KLEmailFormObj = null;

function renderKLEmailForm( $text, $argv, &$parser ) {
	global $KLEmailFormObj;
	//it is important to disable the cache for dynamic data
	$parser->disableCache();

	//if the object already exists, then we are processing nested tags
	if(is_object($KLEmailFormObj)) {
		return $KLEmailFormObj->recursive_parsing($text, $argv, $parser);
	}
	//if null object, instantiate it, process the input, then return processed HTML
	else {
		$KLEmailFormObj = new KLEmailFormClass();
		$output = $KLEmailFormObj->get_HTML_for_input($text, $argv, $parser);
		//print_r($KLEmailFormObj);die();
		$KLEmailFormObj = null;
		return $output;
	}
}

class KLEmailFormClass {
	var $sendto;
	var $submitted;
	var $posted;
	var $processing_result;
	var $ispost;
	var $formHTML;
	var $resultHTML;
	var $errors;

	function __construct() {
		$this->sendto = '';
		$this->processing_result = false;
		$this->resultHTML = '';
		$this->formHTML ='';
		$this->posted = array();
		$this->default = array();
		$this->errors = array();
		//process $_POST data		
		if($_POST['submit'] == EMAILFORM_SUBMIT_BUTTON) {
			$this->submitted = true;
			$post=$_POST;
			unset($post['submit']);
			$this->set_posted_name(   $post['name']   ); unset($post['name']);
			$this->set_posted_from(   $post['from']   ); unset($post['from']);
			$this->set_posted_subject($post['subject']); unset($post['subject']);
			$this->set_posted_message($post['message']); unset($post['message']);
			//remainder of fields are added to message
			$this->message_addons = '';
			foreach ($post as $arg => $value) {
				$this->posted['addons'] .= "{$arg}: {$value}\n\n";
			}
		}
		//generate default post data
		else {
			$this->submitted = false;
			$this->set_posted_name(''); 
			$this->set_posted_from(''); 
			//newlines
			$nls = array("\n", "\r", '\n');
			$this->set_posted_subject(str_replace($nls, ' ', $_GET['subject'])); 
			$this->set_posted_message(str_replace($nls, '
', $_GET['message'])); 
		}
    }
	
	function recursive_parsing($text, $argv, &$parser) {
		// recursive function for parsing tags 
		// <emailform name=60 />
		$return = '';
		if(isset($argv['prefill'])) {
			$prefill = $argv['prefill'];
			unset($argv['prefill']);
		}
		else {
			$prefill = '';
		}
		foreach ($argv as $arg => $value) {
			//within <emailform result>, just print the posted value 
			if($arg == 'result') {
				$this->processing_result = true;
				$this->resultHTML = $this->parse_subtext($text);
				$this->processing_result = false;
				return '';
		 	}
			elseif($this->processing_result) {
				 $return = $this->posted[$arg];
			}
			
			//outside <emailform result>, just print an appropriate form field 
			elseif($arg == 'sendto') {
				$s = trim($value);
				//to prevent email harvesting
				//change ' at ' to @, ' dot ' to .
				//and remove all spaces from string
				$s = preg_replace('/ +?at +/', '@', $s);
				$s = preg_replace('/ +?dot +/', '.', $s);
				$s = str_replace(' ', '', $s);
				$this->sendto =  $s;
		 	}
			elseif($arg == 'submit') {
				$return = ' <input type="submit" name="submit" value="' . EMAILFORM_SUBMIT_BUTTON . '"/> ' ;
		 	}
		 	elseif ( $value > 0 ) { // If the argument is numeric, it's a text field size
				$size = explode( 'x', $value );
				if ( $size[1] ) 
					$return = '<textarea name="'.$arg.'" cols="'.$size[0].'" rows="'.$size[1].'" >'.$this->get_posted($arg,$prefill).'</textarea>' ;
				else 
					$return = '<input type="text" name="'. $arg.'" size="'.$value.'" value="'.$this->get_posted($arg,$prefill).'" />' ;
			}
		 	else {
		 		$return = '<input type="hidden" name="'.$arg.'" value="'.$value.'" />';
		 	}
		}
		if($text) $return .= $this->parse_subtext($text);
		return $return;
	}
	/* Returns HTML for:
		The result if the user submitted and email was successful
		The form, otherwise.
	*/
	function get_HTML_for_input($text, $argv, &$parser) {
		global $wgTitle, $wgSitename, $wgUser;
		// this sets up new output for processing the entire <emailform>
		$this->resultHTML = '';
		$this->formHTML ='<form action="'. $wgTitle->getFullURL() . '" method="post">';
		$this->formHTML .= $this->recursive_parsing($text, $argv, $parser);
		$this->formHTML .= '</form>';
		
		//now that all input has been processed, output HTML
		//if no sendto, output an error
		if(! $this->sendto) {
			$this->errors = array('The SendTo email address has not been defined. The form will not function.');
			return $this->error_HTML() . $this->formHTML;

		}

		//if the form was not submitted, just output the form itself
		if(! $this->submitted) {
			return $this->formHTML;
		}
		
		//mail the form and return resultHTML or an error
		if(count($this->errors)) {
			return ($this->error_HTML() . $this->formHTML );
		}


    	$from = "{$this->posted['name']} <{$this->posted['from']}>";
    	
   		if(! mail( $this->sendto, $this->posted['subject'], 
   					"Submitted at {$wgSitename}\nby {$this->posted['name']} <{$this->posted['from']}> \n\n" 
							. $this->posted['message'] ."\n\n"
							. $this->posted['addon'],
   					"From: {$this->posted['name']} <{$this->posted['from']}>") ) {
     		return $this->error_HTML('The email was not sent due to an unknown error. PHP "mail()" returned false.') 
     						. $this->formHTML;
   		}

		return $this->resultHTML;
	}
	
	/* this returns the most appropriate value in this priority:
		1. User-posted or link-prefilled value
		2. Prefill value defined in the form
		3. Default value
	*/
	function get_posted($field, $prefill='') {
		if($this->posted[$field]) 
			return $this->posted[$field];
		if ($prefill) 
			return $prefill;
		if($this->default[$field]) 
			return $this->default[$field];
		return '';
	}
	
	/* FIELD CHECKING FUNCTIONS
		Each of these take a value that is assumed to be a $_POST value
		and examines it, possibly registering an error that may be displayed
		if the user submitted the form. 
		
		Each function also creates default values where possible or advisable.
	*/
	function set_posted_name($value) {
		global $wgUser, $wgSitename;
		//posted
		if($value) {
			$this->posted['name'] = $value;
		}
		else {
			$this->posted['name'] = '';
		}
		//default
		if($wgUser->isLoggedIn()) {
			if(! $this->default['name'] = $wgUser->getRealName() ) {
				$this->default['name'] = $wgUser->getName();
			}
		}
		else {
     		$this->default['name'] = $wgSitename . ' User';
    	} 
	}
	function set_posted_from($value) {
		global $wgUser;
		//posted
		if($value) {
			$this->posted['from'] = $value;
			//validate email
			$pos = strpos( $this->posted['from'], '@' );
			if(! $pos || ($pos+1) >= strlen($this->posted['from']) ) {
				$this->errors[] = 'Your email address appears invalid.';
			}
		}
		else {
			$this->posted['from'] = '';
		}
		//default
		if($wgUser->isLoggedIn() && $this->default['from']=$wgUser->getEmail() ) {
			//its done
		}
		else {
			$this->default['from'] = '';
		}
		//error if posted value is empty
		if(! $this->posted['from']) {
			$this->errors[] = 'Your email address is required.';
		}

	}

	function set_posted_subject($value) {
		global $wgSitename;
		//posted
		if($value) {
			$this->posted['subject'] = str_replace("\n", " ", $value);
		}
		else {
			$this->posted['subject'] = '';
		}
		//default
		$this->default['subject'] = 'Message from ' . $this->get_posted('name');
	}
	
	function set_posted_message($value) {
		//posted
		if($value) {
			$this->posted['message'] = $value;
		}
		else {
			$this->posted['message'] = '';
		}
		$this->default['message'] = '';
		//error if posted message is empty
		if(! $this->posted['message']) {
			$this->errors[] = 'The message is blank.';
		}
	}

	//helper functions
	private function parse_subtext($text) {
		global $wgParser;
		$lparse = clone $wgParser;
		$lparse->disableCache();
		$output = $lparse->parse( $text, $wgParser->mTitle, $wgParser->mOptions, true, false );
		return $output->getText();
	}
	
	private function error_HTML() {
		$ret = "\n".'<center><table style="background:#faa; border:1px solid gray;border-collapse:collapse;">'
				. '<tr><td style="padding:.1em .5em;">'
				. 'Error: ';
		if(count($this->errors)==1) {
			$ret .= $this->errors[0] . ' Message not sent.';
		}
		else {
			$ret .= 'Message not sent because:<br/>• '
				. implode("\n<br/>• ", $this->errors) ;
		}
		return $ret ."</td></tr></table></center>\n" ;
	}
} //end class
 
Personal tools