Difference between revisions of "Extension:EmailPage"

From Organic Design wiki
(include phpmailer class)
m (Method)
 
(100 intermediate revisions by the same user not shown)
Line 1: Line 1:
<?php
+
{{svn|extensions|MediaWiki/EmailPage/}}<br />
# Extension:EmailArticle{{Category:Extensions}}{{php}}
 
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
 
# - Author: [http://www.organicdesign.co.nz/nad User:Nad]{{Category:Extensions created with Template:SpecialPage}}
 
# - See http://www.mediawiki.org/wiki/Extension:EmailArticle for installation and usage details
 
  
$wgShowExceptionDetails = true;
+
== Using an SMW query result as the recipient list ==
 +
The idea here is that we'd like to have a form with an input box that allows us to enter a value to be used for part of a query, and the result of the query will be a list of email addresses. For example we may have a query structure that results in the following query when the term "duck" is entered into the form.
 +
<source>
 +
{{#ask:[[User:+]][[Species::~*{!duck!}*]][[Cur::!N]]
 +
|?Email
 +
}}
 +
</source>
 +
When the form is submitted, this query is executed and we're taken to the EmailPage special page with the recipient list automatically populated with the results from the query.
  
if (!defined('MEDIAWIKI')) die('Not an entry point.');
+
=== Method ===
 +
All of the fields in the EmailPage special page can be populated from the query-string or POST data. The ''ea-title'' variable is set to the page title that will be sent to all the recipients, and the ''ea-to'' variable can be set to the list of recipient's email addresses.
  
define('EMAILARTICLE_VERSION','0.0.0, 2007-05-25');
+
We can have some JavaScript which is executed on the clicking of the form's button that builds the query and then sends it to the wiki's API to be executed, and then the results entered into a hidden ''ea-to'' value in the form and then the form is submitted to the EmailPage special page.
  
$wgEmailArticleGroup      = 'postmaster'; # Users must belong to this group to send emails (empty string means anyone can send)
+
For example, the HTML part of this mechanism might be as follows:
$wgEmailArticleContactsCat = 'Contacts';  # This specifies the name of a category containing categories of contact articles
+
<source lang="html">
$wgPhpMailerClass          = dirname(__FILE__).'/phpmailer/class.phpmailer.php'; # From http://phpmailer.sourceforge.net/
+
<form id="send-email-form">
  
if ($wgEmailArticleGroup) $wgGroupPermissions['sysop'][$wgEmailArticleGroup] = true;
+
<!-- This is the parameter that will be part of the SMW query -->
 +
<input id="send-email-param" />
  
$wgExtensionFunctions[] = 'wfSetupEmailArticle';
+
<!-- This will execute the JavaScript that populates the following two hidden inputs -->
 +
<input type="button" id="send-email-button" value="Send" />
  
$wgExtensionCredits['specialpage'][] = array(
+
<!-- Special:EmailPage will use this as the page to send to the recipients -->
'name'        => 'Special:EmailArticle',
+
<input type="hidden" id="send-email-page" name="ea-title" />
'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
 
'description' => 'Send rendered article to an email address or list of addresses',
 
'url'        => 'http://www.mediawiki.org/wiki/Extension:EmailArticle',
 
'version'    => EMAILARTICLE_VERSION
 
);
 
  
# If form has been posted, include the phpmailer class
+
<!-- Special:EmailPage will use this as the recipient list -->
if (isset($_REQUEST['sf_cat'])) require_once($wgPhpMailerClass);
+
<input type="hidden" id="send-email-to" name="ea-to" />
 +
</form>
 +
</source>
  
# Define a new class based on the SpecialPage class
+
The corresponding JavaScript to match the above HTML and the example SMW query might be as follows.
require_once("$IP/includes/SpecialPage.php");
+
<source lang="js">
class SpecialEmailArticle extends SpecialPage {
+
// When our button is clicked, do the following...
 +
$('#send-email-button').click(function() {
  
# Constructor
+
// Get the parameter from the form input and force to lowercase
function SpecialEmailArticle() {
+
var param = $('#send-email-param').val(){!.toLowerCase()!};
global $wgEmailArticleGroup;
 
SpecialPage::SpecialPage('EmailArticle',$wgEmailArticleGroup);
 
}
 
 
 
# Override SpecialPage::execute($param = '')
 
function execute($param) {
 
global $wgOut,$wgUser,$wgEmailArticleContactsCat;
 
$title = Title::makeTitle(NS_SPECIAL,'EmailArticle');
 
 
 
# If the form has been posted, attempt to send the message
 
if (isset($_REQUEST['sf_cat'])) $this->send($param);
 
elseif ($param == '') return $wgOut->addWikiText(wfMsg('ea_noarticle'));
 
 
 
$wgOut->addWikiText(wfMsg('ea_selectrecipients'));
 
$wgOut->addHTML(wfElement('form',array('action' => $title->getLocalURL('action=submit'),'method' => 'POST'),null));
 
 
 
# If $wgEmailArticleContactsCat is set, create a select list of all categories
 
if ($wgEmailArticleContactsCat) {
 
$db =& wfGetDB(DB_SLAVE);
 
$cl = $db->tableName('categorylinks');
 
$cats = '';
 
$result = $db->query("SELECT cl_from FROM $cl WHERE cl_to = '$wgEmailArticleContactsCat' ORDER BY cl_sortkey");
 
while ($row = mysql_fetch_row($result)) {
 
$t = Title::newFromID($row[0]);
 
if ($t->getNamespace() == NS_CATEGORY) $cats .= "<option>{$t->getText()}</option>";
 
}
 
if ($cats) $wgOut->addHTML("From category: <select name=\"sf_cat\">$cats</select>");
 
}
 
 
 
$wgOut->addHTML(
 
'<textarea name="sf_list" cols=25 rows=10></textarea>'
 
. wfElement('input',array('type' => 'submit'))
 
. '</form>'
 
);
 
}
 
  
# Send the message to the recipients
+
// Construct our SMW query with the parameter in it
function send($title) {
+
var query = '{{#ask:[[User:+]][[Species::~*' + param + '*]][[Cur::!N]]|?Email}}';
global $wgOut,$wgUser,$wgServer;
 
  
# get the info from the posted form
+
// Send the query to the MediaWiki API to be parsed
$subject  = $_REQUEST['sf_subject'];
+
$.ajax({
$header  = $_REQUEST['sf_header'];
+
type: 'post',
$cat      = $_REQUEST['sf_cat'];
+
url: mw.util.wikiScript('api'),
$group    = $_REQUEST['sf_group'];
+
dataType: 'json',
$list    = $_REQUEST['sf_list'];
+
data: {
$textonly = $_REQUEST['sf_textonly'];
+
action: 'parse',
 +
text: query,
 +
contentmodel: 'wikitext',
 +
disablelimitreport: true,
 +
disabletidy: true,
 +
format: 'json'
 +
},
  
# get the wikitext content of the article to send
+
// When the API response arrives...
$title = Title::newFromText($title);
+
success: function(json) {
$article = new Article($title);
 
$message = $article->getContent();
 
  
if ($header) $message = "$header\n\n$message";
+
// Extract the raw email addresses from the parsed result
 +
var result = json.parse.text['*']{!.match(/(\S+@[^,]+)/g).join(';');!}
  
# Convert the message text to html unless textonly
+
// Tell EmailPage to use the query result as the recipient list
if ($textonly == '') {
+
$('#send-email-to').val(result);
  
# Parse the wikitext
+
// Tell EmailPage to use the current page to send
$parser = new Parser;
+
$('#send-email-page').val(mw.config.get('wgPageName'));
$opt = new ParserOptions;
 
$message = $parser->parse($message,$title,$opt,true,true)->getText();
 
 
 
# Add CSS and add margin:8px to body tag
 
xwReplaceTokens($article, true);
 
 
 
# Absoluterise relative urls Absolute url of wiki
 
# str_replace('"/wiki/', '"http://'.$_SERVER['HTTP_HOST'].'/wiki/', $message);
 
}
 
 
# Set up new mailer instance
 
$mail = new PHPMailer();
 
$mail->From = $wgUser->isValidEmailAddr() ? $wgUser->getEmail() : "wiki@$wgServer";
 
$mail->FromName = $GLOBALS['xwUserName'];
 
$mail->IsHTML(!$textonly);
 
foreach ( $GLOBALS['sa-email'] as $i ) $mail->AddAddress( trim($i) );
 
$mail->Subject = $title;
 
$mail->Body = $article;
 
 
# Send message and redirect client back to article or raise error
 
$title = preg_replace('/^(?=Category:)/i',':',$title);
 
if ($mail->Send()) {
 
global $xwUserName;
 
$msg = count($GLOBALS['sa-email']).' recipient(s)';
 
xwLog("[[$title]] sent to $msg by [[$xwUserName]]");
 
} else xwLog($msg = "Error sending [[$title]] for [[$xwUserName]]: ".$mail->ErrorInfo);
 
}
 
  
}
+
// Set the forms submission URL to Special:EmailPage
 +
$('#send-email-form').attr('action', mw.util.wikiScript() + '?title=Special:EmailPage');
  
# Called from $wgExtensionFunctions array when initialising extensions
+
// Best POST it since the email list might be long
function wfSetupEmailArticle() {
+
$('#send-email-form').attr('method', 'post');
global $wgLanguageCode,$wgMessageCache;
 
  
# Add the messages used by the specialpage
+
// Submit the form to Special:EmailPage
if ($wgLanguageCode == 'en') {
+
$('#send-email-form').submit();
$wgMessageCache->addMessages(array(
 
'emailarticle'        => 'EmailArticle',
 
'ea_noarticle'        => "Please specify an article to send, for example [[Special:EmailArticle/Main Page]].",
 
'ea_error'            => "Error: '''$1'''",
 
'ea_ok'              => "Article [[$1]] sent successfully to '''$2''' recipient$3",
 
'ea_selectrecipients' => "Select the recipients"
 
'ea_selectrecipients' => "Select the recipients"
 
));
 
 
}
 
}
 +
});
 +
});
 +
</source>
  
# Add the specialpage to the environment
+
Note that if you don't want to have raw HTML enabled in your wiki, you can use JavaScript to add the form. The code should go '''before''' the click handler code since the click handler refers to the form which needs to already exist. You could add the form to some part of the skin on every page, or you could add it to the content of a specific page. In the following example I'm using a ''jQuery'' CSS-selector (highlighted) to add the form to the "Sandbox" article just after the page heading.
SpecialPage::addPage(new SpecialEmailArticle());
+
<source lang="js">
}
+
$('{!body.page-Sandbox h1.firstHeading!}').after(
?>
+
'<form id="send-email-form">'
 +
+ '<input id="send-email-param" value="JavaScript" />'
 +
+ '<input type="button" id="send-email-button" value="Send" />'
 +
+ '<input type="hidden" id="send-email-page" name="ea-title" />'
 +
+ '<input type="hidden" id="send-email-to" name="ea-to" />'
 +
+ '</form>'
 +
);
 +
</source>
 +
[[Category:Extensions|EmailPage]]

Latest revision as of 20:10, 8 February 2018

Info.svg This code is in our Git repository here.

Note: If there is no information in this page about this code and it's a MediaWiki extension, there may be something at mediawiki.org.


Using an SMW query result as the recipient list

The idea here is that we'd like to have a form with an input box that allows us to enter a value to be used for part of a query, and the result of the query will be a list of email addresses. For example we may have a query structure that results in the following query when the term "duck" is entered into the form.

{{#ask:[[User:+]][[Species::~*duck*]][[Cur::!N]]
|?Email
}}

When the form is submitted, this query is executed and we're taken to the EmailPage special page with the recipient list automatically populated with the results from the query.

Method

All of the fields in the EmailPage special page can be populated from the query-string or POST data. The ea-title variable is set to the page title that will be sent to all the recipients, and the ea-to variable can be set to the list of recipient's email addresses.

We can have some JavaScript which is executed on the clicking of the form's button that builds the query and then sends it to the wiki's API to be executed, and then the results entered into a hidden ea-to value in the form and then the form is submitted to the EmailPage special page.

For example, the HTML part of this mechanism might be as follows:

<form id="send-email-form">

	<!-- This is the parameter that will be part of the SMW query -->
	<input id="send-email-param" />

	<!-- This will execute the JavaScript that populates the following two hidden inputs -->
	<input type="button" id="send-email-button" value="Send" />

	<!-- Special:EmailPage will use this as the page to send to the recipients -->
	<input type="hidden" id="send-email-page" name="ea-title" />

	<!-- Special:EmailPage will use this as the recipient list -->
	<input type="hidden" id="send-email-to" name="ea-to" />
</form>

The corresponding JavaScript to match the above HTML and the example SMW query might be as follows.

// When our button is clicked, do the following...
$('#send-email-button').click(function() {

	// Get the parameter from the form input and force to lowercase
	var param = $('#send-email-param').val().toLowerCase();

	// Construct our SMW query with the parameter in it
	var query = '{{#ask:[[User:+]][[Species::~*' + param + '*]][[Cur::!N]]|?Email}}';

	// Send the query to the MediaWiki API to be parsed
	$.ajax({
		type: 'post',
		url: mw.util.wikiScript('api'),
		dataType: 'json',
		data: {
			action: 'parse',
			text: query,
			contentmodel: 'wikitext',
			disablelimitreport: true,
			disabletidy: true,
			format: 'json'
		},

		// When the API response arrives...
		success: function(json) {

			// Extract the raw email addresses from the parsed result
			var result = json.parse.text['*'].match(/(\S+@[^,]+)/g).join(';');

			// Tell EmailPage to use the query result as the recipient list
			$('#send-email-to').val(result);

			// Tell EmailPage to use the current page to send
			$('#send-email-page').val(mw.config.get('wgPageName'));

			// Set the forms submission URL to Special:EmailPage
			$('#send-email-form').attr('action', mw.util.wikiScript() + '?title=Special:EmailPage');

			// Best POST it since the email list might be long
			$('#send-email-form').attr('method', 'post');

			// Submit the form to Special:EmailPage
			$('#send-email-form').submit();
		}
	});
});

Note that if you don't want to have raw HTML enabled in your wiki, you can use JavaScript to add the form. The code should go before the click handler code since the click handler refers to the form which needs to already exist. You could add the form to some part of the skin on every page, or you could add it to the content of a specific page. In the following example I'm using a jQuery CSS-selector (highlighted) to add the form to the "Sandbox" article just after the page heading.

$('body.page-Sandbox h1.firstHeading').after(
	'<form id="send-email-form">'
	+ '<input id="send-email-param" value="JavaScript" />'
	+ '<input type="button" id="send-email-button" value="Send" />'
	+ '<input type="hidden" id="send-email-page" name="ea-title" />'
	+ '<input type="hidden" id="send-email-to" name="ea-to" />'
	+ '</form>'
);