* (bug 740) Messages from extensions now appear in Special:Allmessages
* (bug 2857) fixed parsing of lists in <pre> sections
* Now sorting interwiki links by iw_prefix and avoiding duplicates
+* (bug 796) Trackback support
=== Caveats ===
if ( 0 == $this->getID() ) {
if ( 'edit' == $action ) {
wfProfileOut( $fname );
-
+
# If requested, preload some text.
$text=$this->getPreloadedText($preload);
-
+
# We used to put MediaWiki:Newarticletext here if
# $text was empty at this point.
# This is now shown above the edit box instead.
}
return '';
}
-
+
/**
* This function returns the text of a section, specified by a number ($section).
* A section is text under a heading like == Heading == or <h1>Heading</h1>, or
function view() {
global $wgUser, $wgOut, $wgRequest, $wgOnlySysopsCanPatrol, $wgLang;
global $wgLinkCache, $IP, $wgEnableParserCache, $wgStylePath, $wgUseRCPatrol;
- global $wgEnotif, $wgParser, $wgParserCache;
+ global $wgEnotif, $wgParser, $wgParserCache, $wgUseTrackbacks;
$sk = $wgUser->getSkin();
$fname = 'Article::view';
);
}
+ # Trackbacks
+ if ($wgUseTrackbacks)
+ $this->addTrackbacks();
+
# Put link titles into the link cache
$wgOut->transformBuffer();
wfProfileOut( $fname );
}
+ function addTrackbacks() {
+ global $wgOut;
+
+ $dbr = wfGetDB(DB_SLAVE);
+ $tbs = $dbr->select(
+ /* FROM */ 'trackbacks',
+ /* SELECT */ array('tb_title', 'tb_url', 'tb_ex', 'tb_name'),
+ /* WHERE */ array('tb_id' => $this->getID())
+ );
+
+ if (!$dbr->numrows($tbs))
+ return;
+
+ $tbtext = "";
+ while ($o = $dbr->fetchObject($tbs)) {
+ $tbtext .= wfMsg(strlen($o->tb_ex) ? 'trackbackexcerpt' : 'trackback',
+ $o->tb_title,
+ $o->tb_url,
+ $o->tb_ex,
+ $o->tb_name);
+ }
+ $wgOut->addWikitext(wfMsg('trackbackbox', $tbtext));
+ }
+
function render() {
global $wgOut;
$ns = $this->mTitle->getNamespace();
$ttl = $this->mTitle->getDBkey();
-
+
# If this is a comment, add the summary as headline
if($comment && $summary!="") {
$text="== {$summary} ==\n\n".$text;
array_push( $wgPostCommitUpdateList, $u );
}
- # File cache
+ # File cache
if ( $wgUseFileCache ) {
$cm = new CacheManager($this->mTitle);
@unlink($cm->fileCacheName());
$db->freeResult( $res );
return $result;
}
-
-
}
-
?>
*/
$wgEnableScaryTranscluding = false;
+/**
+ * Support blog-style "trackbacks" for articles. See
+ * http://www.sixapart.com/pronet/docs/trackback_spec for details.
+ */
+$wgUseTrackbacks = false;
+
?>
*/
function headElement() {
global $wgDocType, $wgDTD, $wgContLanguageCode, $wgOutputEncoding, $wgMimeType;
- global $wgUser, $wgContLang, $wgRequest;
+ global $wgUser, $wgContLang, $wgRequest, $wgUseTrackbacks, $wgTitle;
if( $wgMimeType == 'text/xml' || $wgMimeType == 'application/xhtml+xml' || $wgMimeType == 'application/xml' ) {
$ret = "<?xml version=\"1.0\" encoding=\"$wgOutputEncoding\" ?>\n";
$ret .= $this->mScripts;
$ret .= $sk->getUserStyles();
+ if ($wgUseTrackbacks && $this->isArticleRelated())
+ $ret .= $wgTitle->trackbackRDF();
+
$ret .= "</head>\n";
return $ret;
}
function addMetadataLinks( &$out ) {
global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
- global $wgRightsPage, $wgRightsUrl;
+ global $wgRightsPage, $wgRightsUrl, $wgUseTrackbacks;
if( $out->isArticleRelated() ) {
# note: buggy CC software only reads first "meta" link
}
function bottomLinks() {
- global $wgOut, $wgUser, $wgTitle;
+ global $wgOut, $wgUser, $wgTitle, $wgUseTrackbacks;
$sep = " |\n";
$s = '';
. $sep . $this->whatLinksHere()
. $sep . $this->watchPageLinksLink();
+ if ($wgUseTrackbacks)
+ $s .= $sep . $this->trackbackLink();
+
if ( $wgTitle->getNamespace() == NS_USER
|| $wgTitle->getNamespace() == NS_USER_TALK )
}
}
+ function trackbackLink() {
+ global $wgTitle;
+
+ return "<a href=\"" . $wgTitle->trackbackURL() . "\">"
+ . wfMsg('trackbacklink') . "</a>";
+ }
+
function otherLanguages() {
global $wgOut, $wgContLang, $wgTitle, $wgHideInterlanguageLinks;
global $wgDisableCounters, $wgLogo, $action, $wgFeedClasses, $wgHideInterlanguageLinks;
global $wgMaxCredits, $wgShowCreditsIfMax;
global $wgPageShowWatchingUsers;
+ global $wgUseTrackbacks;
$fname = 'SkinTemplate::outputPage';
wfProfileIn( $fname );
} else {
$tpl->set( 'feeds', false );
}
+ if ($wgUseTrackbacks && $out->isArticleRelated())
+ $tpl->set( 'trackbackhtml', $wgTitle->trackbackRDF());
+
$tpl->setRef( 'mimetype', $wgMimeType );
$tpl->setRef( 'jsmimetype', $wgJsMimeType );
$tpl->setRef( 'charset', $wgOutputEncoding );
* @access private
*/
function buildNavUrls () {
+ global $wgUseTrackbacks, $wgTitle;
+
$fname = 'SkinTemplate::buildNavUrls';
wfProfileIn( $fname );
$nav_urls['recentchangeslinked'] = array(
'href' => $this->makeSpecialUrl("Recentchangeslinked/$this->thispage")
);
+ if ($wgUseTrackbacks)
+ $nav_urls['trackbacklink'] = array(
+ 'href' => $wgTitle->trackbackURL()
+ );
}
if( $this->mTitle->getNamespace() == NS_USER || $this->mTitle->getNamespace() == NS_USER_TALK ) {
'Userlogout' => new UnlistedSpecialPage( 'Userlogout' ),
'Preferences' => new SpecialPage( 'Preferences' ),
'Watchlist' => new SpecialPage( 'Watchlist' ),
-
+
'Recentchanges' => new IncludableSpecialPage( 'Recentchanges' ),
'Upload' => new SpecialPage( 'Upload' ),
'Imagelist' => new SpecialPage( 'Imagelist' ),
* Whether the special page can be included in an article
*/
var $mIncludable;
-
+
/**#@-*/
-
+
/**
* Add a page to the list of valid special pages
* $obj->execute() must send HTML to $wgOut then return
return NULL;
}
}
-
+
/**
* @static
* @param string $name
* The path may contain parameters, e.g. Special:Name/Params
* Extracts the special page name and call the execute method, passing the parameters
*
- * Returns a title object if the page is redirected, false if there was no such special
+ * Returns a title object if the page is redirected, false if there was no such special
* page, and true if it was successful.
*
* @param $title a title object
} else {
$redir =& SpecialPage::getRedirect( $name );
if ( isset( $redir ) ) {
- if ( isset( $par ) )
+ if ( isset( $par ) )
$wgOut->redirect( $redir->getFullURL() . '/' . $par );
else
$wgOut->redirect( $redir->getFullURL() );
$oldTitle = $wgTitle;
$oldOut = $wgOut;
$wgOut = new OutputPage;
-
+
$ret = SpecialPage::executePath( $title, true );
if ( $ret === true ) {
$ret = $wgOut->getHTML();
function isListed() { return $this->mListed; }
function getFile() { return $this->mFile; }
function including( $x = NULL ) { return wfSetVar( $this->mIncluding, $x ); }
- function includable( $x = NULL ) { return wfSetVar( $this->mIncludable, $x ); }
+ function includable( $x = NULL ) { return wfSetVar( $this->mIncludable, $x ); }
/**
* Checks if the given user (identified by an object) can execute this
$dbw->update( 'page', /* SET */ array( 'page_touched' => $dbw->timestamp() ),
/* WHERE */ array( 'page_id' => $toucharr ),$fname);
}
+
+ function trackbackURL() {
+ global $wgTitle, $wgScriptPath, $wgServer;
+
+ return "$wgServer$wgScriptPath/trackback.php?article="
+ . htmlspecialchars(urlencode($wgTitle->getPrefixedDBkey()));
+ }
+
+ function trackbackRDF() {
+ $url = htmlspecialchars($this->getFullURL());
+ $title = htmlspecialchars($this->getText());
+ $tburl = $this->trackbackURL();
+
+ return "
+<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
+ xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
+ xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">
+<rdf:Description
+ rdf:about=\"$url\"
+ dc:identifier=\"$url\"
+ dc:title=\"$title\"
+ trackback:ping=\"$tburl\" />
+</rdf:RDF>";
+ }
}
?>
'emailauthenticated' => 'Your email address was authenticated on $1.',
'emailnotauthenticated' => 'Your email address is <strong>not yet authenticated</strong>. No email
will be sent for any of the following features.',
-'noemailprefs' => '<strong>No email address has been specified</strong>, the following
+'noemailprefs' => '<strong>No email address has been specified</strong>, the following
features will not work.',
'emailconfirmlink' => 'Confirm your e-mail address',
-'invalidemailaddress' => 'The email address cannot be accepted as it appears to have an invalid
+'invalidemailaddress' => 'The email address cannot be accepted as it appears to have an invalid
format. Please enter a well-formatted address or empty that field.',
# Edit page toolbar
'scarytranscludefailed' => '[Template fetch failed for $1; sorry]',
'scarytranscludetoolong' => '[URL is too long; sorry]',
+# Trackbacks
+'trackbackbox' => "<div id='mw_trackbacks'>
+Trackbacks for this article:<br/>
+$1
+</div>
+",
+'trackback' => "; $4 : [$2 $1]</li>\n",
+'trackbackexcerpt' => "; $4 : [$2 $1]: <nowiki>$3</nowiki></li>\n",
+'trackbacklink' => 'Trackback',
);
/* a fake language converter */
--- /dev/null
+CREATE TABLE /*$wgDBprefix*/trackbacks (
+ tb_id INTEGER REFERENCES page(page_id) ON DELETE CASCADE,
+ tb_title VARCHAR(255) NOT NULL,
+ tb_url VARCHAR(255) NOT NULL,
+ tb_ex TEXT,
+ tb_name VARCHAR(255),
+
+ INDEX (tb_id)
+);
-- PRIMARY KEY (gr_id)
--
--) TYPE=InnoDB;
+
+CREATE TABLE /*$wgDBprefix*/trackbacks (
+ tb_id INTEGER REFERENCES page(page_id) ON DELETE CASCADE,
+ tb_title VARCHAR(255) NOT NULL,
+ tb_url VARCHAR(255) NOT NULL,
+ tb_ex TEXT,
+ tb_name VARCHAR(255),
+
+ INDEX (tb_id)
+);
+
array( 'validate', 'patch-validate.sql' ),
array( 'user_newtalk', 'patch-usernewtalk2.sql' ),
array( 'transcache', 'patch-transcache.sql' ),
+ array( 'trackbacks', 'patch-trackbacks.sql' ),
);
$wgNewFields = array(
<?php if($this->data['usercss' ]) { ?><style type="text/css"><?php $this->html('usercss' ) ?></style><?php } ?>
<?php if($this->data['userjs' ]) { ?><script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('userjs' ) ?>"></script><?php } ?>
<?php if($this->data['userjsprev']) { ?><script type="<?php $this->text('jsmimetype') ?>"><?php $this->html('userjsprev') ?></script><?php } ?>
+ <?php if($this->data['trackbackhtml']) print $this->data['trackbackhtml']; ?>
</head>
<body <?php if($this->data['body_ondblclick']) { ?>ondblclick="<?php $this->text('body_ondblclick') ?>"<?php } ?>
<?php if($this->data['body_onload' ]) { ?>onload="<?php $this->text('body_onload') ?>"<?php } ?>
<ul>
<?php if($this->data['notspecialpage']) { foreach( array( 'whatlinkshere', 'recentchangeslinked' ) as $special ) { ?>
<li id="t-<?php echo $special?>"><a href="<?php
- echo htmlspecialchars($this->data['nav_urls'][$special]['href'])
+ echo htmlspecialchars($this->data['nav_urls'][$special]['href'])
?>"><?php echo $this->msg($special) ?></a></li>
<?php } } ?>
+ <?php if(isset($this->data['nav_urls']['trackbacklink'])) { ?>
+ <li id="t-trackbacklink"><a href="<?php
+ echo htmlspecialchars($this->data['nav_urls']['trackbacklink']['href'])
+ ?>"><?php echo $this->msg('trackbacklink') ?></a></li>
+ <?php } ?>
<?php if($this->data['feeds']) { ?><li id="feedlinks"><?php foreach($this->data['feeds'] as $key => $feed) {
?><span id="feed-<?php echo htmlspecialchars($key) ?>"><a href="<?php
echo htmlspecialchars($feed['href']) ?>"><?php echo htmlspecialchars($feed['text'])?></a> </span>
<?php } ?>
<?php if(!empty($this->data['nav_urls']['print']['href'])) { ?>
<li id="t-print"><a href="<?php
- echo htmlspecialchars($this->data['nav_urls']['print']['href'])
+ echo htmlspecialchars($this->data['nav_urls']['print']['href'])
?>"><?php echo $this->msg('printableversion') ?></a></li>
<?php } ?>
</ul>
-/*
+/*
* common.css
* This file contains CSS settings common to Wikistandard, Nostalgia and CologneBlue
*/
text-align: center;
overflow: hidden;
}
-div.thumb div * {
+div.thumb div * {
border: none;
background: none;
}
/* Page history styling */
/* the auto-generated edit comments */
.autocomment { color: #4b4b4b; }
-#pagehistory span.user {
+#pagehistory span.user {
margin-left: 1.4em;
margin-right: 0.4em;
}
#pagehistory span.minor { font-weight: bold; }
#pagehistory li { border: 1px solid White; }
-#pagehistory li.selected {
+#pagehistory li.selected {
background-color:#f9f9f9;
border:1px dashed #aaaaaa;
}
table.diff { background:white; }
td.diff-otitle { background:#cccccc; }
td.diff-ntitle { background:#cccccc; }
-td.diff-addedline {
+td.diff-addedline {
background:#ccffcc;
font-size: 94%;
}
-td.diff-deletedline {
+td.diff-deletedline {
background:#ffffaa;
font-size: 94%;
}
}
/* preference page with js-genrated toc */
-#preftoc {
+#preftoc {
float: left;
margin: 1em 1em 1em 1em;
width: 13em;
}
#preftoc li { border: 1px solid White; }
-#preftoc li.selected {
+#preftoc li.selected {
background-color:#f9f9f9;
border:1px dashed #aaaaaa;
}
display: block;
color: #005189;
}
-#prefcontrol {
+#prefcontrol {
clear: left;
float: left;
margin-top: 1em;
}
-div.prefsectiontip {
+div.prefsectiontip {
font-size: 94%;
margin-top: 1em;
}
}
div.townBox dl {
padding: 0;
- margin: 0 0 0.3em 0;
+ margin: 0 0 0.3em 0;
font-size: 96%;
}
div.townBox dl dt {
background-color: #f3f3f3;
}
/* use this instead of #toc for page content */
-.toccolours {
+.toccolours {
border:1px solid #aaaaaa;
background-color:#f9f9f9;
padding:5px;
background-color:#ffffff;
}
-table.gallery tr {
+table.gallery tr {
vertical-align:top;
}
text-align: center;
border: 1px solid #cccccc;
margin: 2px;
-}
+}
div.gallerytext {
font-size: 94%;
padding: 2px 4px;
-}
+}
span.comment {
font-style: italic;
.visualClear {
clear: both;
}
+
+#mw_trackbacks {
+ border: solid 1px #bbbbff;
+ background-color: #eeeeff;
+ padding: 0.2em;
+}
*/
#siteSub {
- display: none;
+ display: none;
}
#contentSub {
font-size: 84%;
float: left;
font-size: small;
text-align: center;
-}
+}
.editExternallyHelp {
font-style: italic;
color: gray;
color: green;
font-weight:bold;
}
+
+#mw_trackbacks {
+ border: solid 1px #bbbbff;
+ background-color: #eeeeff;
+ padding: 0.2em;
+}
--- /dev/null
+<?php
+/**
+ * Provide functions to handle article trackbacks.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+unset($IP);
+define('MEDIAWIKI', true);
+require_once('./includes/Defines.php');
+
+if (!file_exists('LocalSettings.php'))
+ exit;
+
+require_once('./LocalSettings.php');
+require_once('includes/Setup.php');
+
+require_once('Title.php');
+require_once('DatabaseFunctions.php');
+
+/**
+ *
+ */
+function XMLsuccess() {
+ echo "
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<response>
+<error>0</error>
+</response>
+ ";
+ exit;
+}
+
+function XMLerror($err = "Invalid request.") {
+ header("HTTP/1.0 400 Bad Request");
+ echo "
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<response>
+<error>1</error>
+<message>Invalid request: $err</message>
+</response>
+";
+ exit;
+}
+
+if (!$wgUseTrackbacks)
+ XMLerror("Trackbacks are disabled.");
+
+if ( !isset($_POST['url'])
+ || !isset($_POST['blog_name'])
+ || !isset($_REQUEST['article']))
+ XMLerror("Required field not specified");
+
+$dbw =& wfGetDB(DB_MASTER);
+
+$tbtitle = $_POST['title'];
+$tbex = $_POST['excerpt'];
+$tburl = $_POST['url'];
+$tbname = $_POST['blog_name'];
+$tbarticle = $_REQUEST['article'];
+
+$title = Title::newFromText($tbarticle);
+if (!$title->exists())
+ XMLerror("Specified article does not exist.");
+
+$dbw->insert('trackbacks', array(
+ 'tb_id' => $title->getArticleID(),
+ 'tb_title' => $tbtitle,
+ 'tb_url' => $tburl,
+ 'tb_ex' => $tbex,
+ 'tb_name' => $tbname
+));
+
+XMLsuccess();
+exit;