From: River Tarnell Date: Sat, 23 Jul 2005 05:47:25 +0000 (+0000) Subject: (bug 796) trackback support X-Git-Tag: 1.5.0beta4~55 X-Git-Url: http://git.cyclocoop.org/?a=commitdiff_plain;h=bc36d810e796739c2bc5e8fec70a5c5bf530b21e;p=lhc%2Fweb%2Fwiklou.git (bug 796) trackback support --- diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 8069d8fd8e..bfa7b44893 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -595,6 +595,7 @@ of MediaWiki:Newpagetext) to &action=edit, if page is new. * (bug 740) Messages from extensions now appear in Special:Allmessages * (bug 2857) fixed parsing of lists in
 sections
 * Now sorting interwiki links by iw_prefix and avoiding duplicates
+* (bug 796) Trackback support
 
 === Caveats ===
 
diff --git a/includes/Article.php b/includes/Article.php
index 3c1c3eb950..75cd20c9a2 100644
--- a/includes/Article.php
+++ b/includes/Article.php
@@ -94,10 +94,10 @@ class Article {
 		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.
@@ -154,7 +154,7 @@ class Article {
 		}
 		return '';
 	}
-	
+
 	/**
 	 * This function returns the text of a section, specified by a number ($section).
 	 * A section is text under a heading like == Heading == or 

Heading

, or @@ -678,7 +678,7 @@ class Article { 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'; @@ -835,6 +835,10 @@ class Article { ); } + # Trackbacks + if ($wgUseTrackbacks) + $this->addTrackbacks(); + # Put link titles into the link cache $wgOut->transformBuffer(); @@ -845,6 +849,30 @@ class Article { 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; @@ -979,7 +1007,7 @@ class Article { $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; @@ -1233,7 +1261,7 @@ class Article { array_push( $wgPostCommitUpdateList, $u ); } - # File cache + # File cache if ( $wgUseFileCache ) { $cm = new CacheManager($this->mTitle); @unlink($cm->fileCacheName()); @@ -2403,9 +2431,6 @@ class Article { $db->freeResult( $res ); return $result; } - - } - ?> diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index c571df2187..cacbf1d487 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1588,4 +1588,10 @@ $wgHTTPProxy = false; */ $wgEnableScaryTranscluding = false; +/** + * Support blog-style "trackbacks" for articles. See + * http://www.sixapart.com/pronet/docs/trackback_spec for details. + */ +$wgUseTrackbacks = false; + ?> diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 36e5871365..8ebde39adf 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -791,7 +791,7 @@ class OutputPage { */ 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 = "\n"; @@ -825,6 +825,9 @@ class OutputPage { $ret .= $this->mScripts; $ret .= $sk->getUserStyles(); + if ($wgUseTrackbacks && $this->isArticleRelated()) + $ret .= $wgTitle->trackbackRDF(); + $ret .= "\n"; return $ret; } diff --git a/includes/Skin.php b/includes/Skin.php index d2de740170..712a216573 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -108,7 +108,7 @@ class Skin extends Linker { 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 @@ -732,7 +732,7 @@ END; } function bottomLinks() { - global $wgOut, $wgUser, $wgTitle; + global $wgOut, $wgUser, $wgTitle, $wgUseTrackbacks; $sep = " |\n"; $s = ''; @@ -746,6 +746,9 @@ END; . $sep . $this->whatLinksHere() . $sep . $this->watchPageLinksLink(); + if ($wgUseTrackbacks) + $s .= $sep . $this->trackbackLink(); + if ( $wgTitle->getNamespace() == NS_USER || $wgTitle->getNamespace() == NS_USER_TALK ) @@ -1113,6 +1116,13 @@ END; } } + function trackbackLink() { + global $wgTitle; + + return "trackbackURL() . "\">" + . wfMsg('trackbacklink') . ""; + } + function otherLanguages() { global $wgOut, $wgContLang, $wgTitle, $wgHideInterlanguageLinks; diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php index 775c7783b1..5ea7c37dfe 100644 --- a/includes/SkinTemplate.php +++ b/includes/SkinTemplate.php @@ -149,6 +149,7 @@ class SkinTemplate extends Skin { global $wgDisableCounters, $wgLogo, $action, $wgFeedClasses, $wgHideInterlanguageLinks; global $wgMaxCredits, $wgShowCreditsIfMax; global $wgPageShowWatchingUsers; + global $wgUseTrackbacks; $fname = 'SkinTemplate::outputPage'; wfProfileIn( $fname ); @@ -217,6 +218,9 @@ class SkinTemplate extends Skin { } 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 ); @@ -721,6 +725,8 @@ class SkinTemplate extends Skin { * @access private */ function buildNavUrls () { + global $wgUseTrackbacks, $wgTitle; + $fname = 'SkinTemplate::buildNavUrls'; wfProfileIn( $fname ); @@ -768,6 +774,10 @@ class SkinTemplate extends Skin { $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 ) { diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php index 64bf918049..869ccafe1a 100644 --- a/includes/SpecialPage.php +++ b/includes/SpecialPage.php @@ -33,7 +33,7 @@ $wgSpecialPages = array( 'Userlogout' => new UnlistedSpecialPage( 'Userlogout' ), 'Preferences' => new SpecialPage( 'Preferences' ), 'Watchlist' => new SpecialPage( 'Watchlist' ), - + 'Recentchanges' => new IncludableSpecialPage( 'Recentchanges' ), 'Upload' => new SpecialPage( 'Upload' ), 'Imagelist' => new SpecialPage( 'Imagelist' ), @@ -134,11 +134,11 @@ class SpecialPage * 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 @@ -173,7 +173,7 @@ class SpecialPage return NULL; } } - + /** * @static * @param string $name @@ -223,7 +223,7 @@ class SpecialPage * 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 @@ -247,7 +247,7 @@ class SpecialPage } else { $redir =& SpecialPage::getRedirect( $name ); if ( isset( $redir ) ) { - if ( isset( $par ) ) + if ( isset( $par ) ) $wgOut->redirect( $redir->getFullURL() . '/' . $par ); else $wgOut->redirect( $redir->getFullURL() ); @@ -288,7 +288,7 @@ class SpecialPage $oldTitle = $wgTitle; $oldOut = $wgOut; $wgOut = new OutputPage; - + $ret = SpecialPage::executePath( $title, true ); if ( $ret === true ) { $ret = $wgOut->getHTML(); @@ -337,7 +337,7 @@ class SpecialPage 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 diff --git a/includes/Title.php b/includes/Title.php index 0eadae64ef..f0a4c9d96f 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -2079,5 +2079,29 @@ class Title { $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 " + + +"; + } } ?> diff --git a/languages/Language.php b/languages/Language.php index bd99de1233..884108335f 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -637,10 +637,10 @@ to confirm that the account is actually yours.", 'emailauthenticated' => 'Your email address was authenticated on $1.', 'emailnotauthenticated' => 'Your email address is not yet authenticated. No email will be sent for any of the following features.', -'noemailprefs' => 'No email address has been specified, the following +'noemailprefs' => 'No email address has been specified, 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 @@ -2121,6 +2121,15 @@ will expire at $4. 'scarytranscludefailed' => '[Template fetch failed for $1; sorry]', 'scarytranscludetoolong' => '[URL is too long; sorry]', +# Trackbacks +'trackbackbox' => "
+Trackbacks for this article:
+$1 +
+", +'trackback' => "; $4 : [$2 $1]\n", +'trackbackexcerpt' => "; $4 : [$2 $1]: $3\n", +'trackbacklink' => 'Trackback', ); /* a fake language converter */ diff --git a/maintenance/archives/patch-trackbacks.sql b/maintenance/archives/patch-trackbacks.sql new file mode 100644 index 0000000000..93e36628f2 --- /dev/null +++ b/maintenance/archives/patch-trackbacks.sql @@ -0,0 +1,9 @@ +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) +); diff --git a/maintenance/tables.sql b/maintenance/tables.sql index dc508b8cc7..fc1753313a 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -829,3 +829,14 @@ CREATE TABLE /*$wgDBprefix*/logging ( -- 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) +); + diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index 82b1301929..c2034ce9a9 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -25,6 +25,7 @@ $wgNewTables = array( array( 'validate', 'patch-validate.sql' ), array( 'user_newtalk', 'patch-usernewtalk2.sql' ), array( 'transcache', 'patch-transcache.sql' ), + array( 'trackbacks', 'patch-trackbacks.sql' ), ); $wgNewFields = array( diff --git a/skins/MonoBook.php b/skins/MonoBook.php index 5d94cff2e0..17a952d106 100644 --- a/skins/MonoBook.php +++ b/skins/MonoBook.php @@ -68,6 +68,7 @@ class MonoBookTemplate extends QuickTemplate { data['usercss' ]) { ?> data['userjs' ]) { ?> data['userjsprev']) { ?> + data['trackbackhtml']) print $this->data['trackbackhtml']; ?> data['body_ondblclick']) { ?>ondblclick="text('body_ondblclick') ?>" data['body_onload' ]) { ?>onload="text('body_onload') ?>" @@ -158,9 +159,14 @@ class MonoBookTemplate extends QuickTemplate { diff --git a/skins/common/common.css b/skins/common/common.css index 71bed995c4..d73d1399a7 100644 --- a/skins/common/common.css +++ b/skins/common/common.css @@ -1,4 +1,4 @@ -/* +/* * common.css * This file contains CSS settings common to Wikistandard, Nostalgia and CologneBlue */ @@ -38,7 +38,7 @@ div.thumb div { text-align: center; overflow: hidden; } -div.thumb div * { +div.thumb div * { border: none; background: none; } @@ -68,13 +68,13 @@ div.tleft { /* 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; } @@ -82,11 +82,11 @@ div.tleft { 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%; } @@ -141,13 +141,13 @@ span.texhtml { font-family: serif; } } /* 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; } @@ -156,12 +156,12 @@ span.texhtml { font-family: serif; } display: block; color: #005189; } -#prefcontrol { +#prefcontrol { clear: left; float: left; margin-top: 1em; } -div.prefsectiontip { +div.prefsectiontip { font-size: 94%; margin-top: 1em; } @@ -194,7 +194,7 @@ div.townBox { } div.townBox dl { padding: 0; - margin: 0 0 0.3em 0; + margin: 0 0 0.3em 0; font-size: 96%; } div.townBox dl dt { @@ -206,7 +206,7 @@ div.townBox dl dd { background-color: #f3f3f3; } /* use this instead of #toc for page content */ -.toccolours { +.toccolours { border:1px solid #aaaaaa; background-color:#f9f9f9; padding:5px; @@ -254,7 +254,7 @@ table.gallery { background-color:#ffffff; } -table.gallery tr { +table.gallery tr { vertical-align:top; } @@ -273,12 +273,12 @@ div.gallerybox div.thumb { text-align: center; border: 1px solid #cccccc; margin: 2px; -} +} div.gallerytext { font-size: 94%; padding: 2px 4px; -} +} span.comment { font-style: italic; @@ -348,3 +348,9 @@ table.exif td.spacer { .visualClear { clear: both; } + +#mw_trackbacks { + border: solid 1px #bbbbff; + background-color: #eeeeff; + padding: 0.2em; +} diff --git a/skins/monobook/main.css b/skins/monobook/main.css index 318b16c097..ff04c7de6e 100644 --- a/skins/monobook/main.css +++ b/skins/monobook/main.css @@ -219,7 +219,7 @@ pre { */ #siteSub { - display: none; + display: none; } #contentSub { font-size: 84%; @@ -1078,7 +1078,7 @@ span.changedby { float: left; font-size: small; text-align: center; -} +} .editExternallyHelp { font-style: italic; color: gray; @@ -1181,3 +1181,9 @@ p.revision_saved { color: green; font-weight:bold; } + +#mw_trackbacks { + border: solid 1px #bbbbff; + background-color: #eeeeff; + padding: 0.2em; +} diff --git a/trackback.php b/trackback.php new file mode 100644 index 0000000000..726cacba41 --- /dev/null +++ b/trackback.php @@ -0,0 +1,75 @@ + + +0 + + "; + exit; +} + +function XMLerror($err = "Invalid request.") { + header("HTTP/1.0 400 Bad Request"); + echo " + + +1 +Invalid request: $err + +"; + 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;