ENHANCEMENT: Allow notifying multiple trackback urls per blog entry

APICHANGE: TrackBackDecorator::trackbackNotify() allow one parameter
APICHANGE: remove TrackBackDecorator::ShouldTrackbackNotify()
This commit is contained in:
Saophalkun Ponlu 2010-06-23 05:50:02 +00:00
parent 68df540615
commit 834b6d8f91
4 changed files with 173 additions and 59 deletions

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* TODO: Multiple trackback urls for each blog entry * Add trackback (receive and send) feature blog entry
*/ */
class TrackBackDecorator extends DataObjectDecorator { class TrackBackDecorator extends DataObjectDecorator {
@ -8,11 +8,8 @@ class TrackBackDecorator extends DataObjectDecorator {
function extraStatics() { function extraStatics() {
return array( return array(
'db' => array(
'TrackbackURL' => 'Varchar(2048)',
'PungTrackbackURL' => 'Varchar(2048)'
),
'has_many' => array( 'has_many' => array(
'TrackBackURLs' => 'TrackBackURL',
'TrackBacks' => 'TrackBackPing' 'TrackBacks' => 'TrackBackPing'
) )
); );
@ -21,21 +18,32 @@ class TrackBackDecorator extends DataObjectDecorator {
function updateCMSFields($fields) { function updateCMSFields($fields) {
// Trackback URL field // Trackback URL field
if($this->owner->TrackBacksEnabled()) { if($this->owner->TrackBacksEnabled()) {
$fields->addFieldToTab("Root.Content.Main", new TextField("TrackbackURL", _t("BlogEntry.TRACKBACKURL", "Trackback URL")), "Content"); $trackbackURLTable = new ComplexTableField(
$this,
'TrackBackURLs',
'TrackBackURL',
array(
'URL' => 'URL',
'IsPung' => 'Pung?'
),
'getCMSFields_forPopup',
'',
'ID'
);
$fields->addFieldToTab("Root.Content.Main", $trackbackURLTable);
} }
else { else {
$fields->addFieldToTab("Root.Content.Main", new ReadonlyField("TrackbackURLReadOnly", _t("BlogEntry.TRACKBACKURL", "Trackback URL"), _t("BlogEntry.TRACKBACKURL_DISABLED", "To use this feature, please check 'Enable TrackBacks' check box on the blog holder.")), "Content"); $fields->addFieldToTab("Root.Content.Main", new ReadonlyField("TrackBackURLsReadOnly", _t("BlogEntry.TrackbackURLs", "Trackback URLs"), _t("BlogEntry.TrackbackURLs_DISABLED", "To use this feature, please check 'Enable TrackBacks' check box on the blog holder.")));
} }
} }
function onBeforePublish() { function onBeforePublish() {
$owner = $this->owner; if(!$this->owner->TrackBacksEnabled() && !$this->owner->TrackBackURLs()) return;
if(!empty($owner->TrackbackURL) && $owner->TrackBacksEnabled() && $owner->ShouldTrackbackNotify()) { foreach($this->owner->TrackBackURLs() as $trackBackURL) {
if(!$trackBackURL->Pung && $this->trackbackNotify($trackBackURL->URL)) {
if($this->trackbackNotify()) { $trackBackURL->Pung = true;
$owner->PungTrackbackURL = $owner->TrackbackURL; $trackBackURL->write();
$owner->write();
} }
} }
} }
@ -44,40 +52,33 @@ class TrackBackDecorator extends DataObjectDecorator {
* Trackback notify the specified trackback url * Trackback notify the specified trackback url
* @param boolean | true on success, otherwise false * @param boolean | true on success, otherwise false
*/ */
function trackbackNotify() { function trackbackNotify($url) {
$owner = $this->owner;
$content = new HTMLText('Content'); $content = new HTMLText('Content');
$content->setValue($owner->Content); $content->setValue($this->owner->Content);
$excerpt = $content->FirstParagraph(); $excerpt = $content->FirstParagraph();
if($owner->Parent() && $owner->ParentID > 0) { if($this->owner->Parent() && $this->owner->ParentID > 0) {
$blogName = $owner->Parent()->Title; $blogName = $this->owner->Parent()->Title;
} }
else { else {
$blogName = ""; $blogName = "";
} }
$postData = array( $postData = array(
'url' => $owner->AbsoluteLink(), 'url' => $this->owner->AbsoluteLink(),
'title' => $owner->Title, 'title' => $this->owner->Title,
'excerpt' => $excerpt, 'excerpt' => $excerpt,
'blog_name' => $blogName 'blog_name' => $blogName
); );
$controller = Object::create(self::$trackback_server_class); $controller = Object::create(self::$trackback_server_class);
$response = $controller->request($owner->TrackbackURL, $postData); $response = $controller->request($url, $postData);
if($response->getStatusCode() == '200' && stripos($response->getBody(), "<error>0</error>") !== false) { if($response->getStatusCode() == '200' && stripos($response->getBody(), "<error>0</error>") !== false) {
return true; return true;
} }
return false; return false;
}
function ShouldTrackbackNotify() {
return (trim($this->owner->TrackbackURL) != '' && $this->owner->TrackbackURL != $this->owner->PungTrackbackURL);
} }
function updateMetaTags(&$tags) { function updateMetaTags(&$tags) {
@ -136,6 +137,8 @@ class TrackbackHTTPServer {
*/ */
function request($url, $data) { function request($url, $data) {
$ch = curl_init($url); $ch = curl_init($url);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

54
code/TrackBackURL.php Normal file
View File

@ -0,0 +1,54 @@
<?php
class TrackBackURL extends DataObject {
static $db = array(
'URL' => 'Varchar(2048)',
'Pung' => 'Boolean(0)'
);
static $has_one = array(
'BlogEntry' => 'BlogEntry'
);
function getCMSFields_forPopup() {
return new FieldSet(
new TextField('URL'),
new ReadonlyField('Pung', 'Pung?')
);
}
/**
* Return a human-reable string indicate whether the url has been pung or not
* Also update the url if it's duplicate
* @return string - 'Yes' or 'No'
*/
function IsPung() {
if($this->Pung) return _t('TrackBackULR.YES', 'Yes');
if($this->isDuplicate(true)) {
$this->Pung = true;
$this->write();
return _t('TrackBackULR.YES', 'Yes');
}
return _t('TrackBackULR.NO', 'No');
}
/**
* Check if there is a duplication, based on the associcated blog entry and the url.
* If onPung is set, it returns true only when the duplicated record that has Pung = true
* @param boolean
* @return boolean
*/
function isDuplicate($onPung = false) {
$where = "\"BlogEntryID\" = {$this->BlogEntryID} AND \"URL\" = '{$this->URL}' AND TrackBackURL.ID <> {$this->ID}";
if($onPung) $where .= " AND Pung IS TRUE";
if(DataObject::get_one($this->ClassName, $where)) {
return true;
}
return false;
}
}

View File

@ -4,7 +4,7 @@
* @subpackage tests * @subpackage tests
*/ */
class BlogTrackbackTest extends SapphireTest { class BlogTrackbackTest extends SapphireTest {
static $fixture_file = 'blog/tests/BlogTest.yml'; static $fixture_file = 'blog/tests/BlogTrackbackTest.yml';
function testTrackback() { function testTrackback() {
$blog = $this->objFromFixture('BlogHolder', 'mainblog'); $blog = $this->objFromFixture('BlogHolder', 'mainblog');
@ -33,47 +33,66 @@ class BlogTrackbackTest extends SapphireTest {
unset($_POST); unset($_POST);
} }
function testShouldTrackbackNotify() {
$blog = $this->objFromFixture('BlogHolder', 'mainblog');
$blog->TrackBacksEnabled = true;
$entry = $this->objFromFixture('BlogEntry', 'testpost');
$this->assertFalse($entry->ShouldTrackbackNotify());
$entry = $this->objFromFixture('BlogEntry', 'testpost');
$entry->TrackbackURL = ' ';
$this->assertFalse($entry->ShouldTrackbackNotify());
$entry = $this->objFromFixture('BlogEntry', 'testpost');
$entry->TrackbackURL = 'someurl';
$this->assertTrue($entry->ShouldTrackbackNotify());
}
function testTrackbackNotify() { function testTrackbackNotify() {
$tmpServerClass = TrackBackDecorator::$trackback_server_class; $tmpServerClass = TrackBackDecorator::$trackback_server_class;
TrackBackDecorator::$trackback_server_class = "TestTrackbackHTTPServer"; TrackBackDecorator::$trackback_server_class = "TestTrackbackHTTPServer";
$blog = $this->objFromFixture('BlogHolder', 'mainblog'); $blog = $this->objFromFixture('BlogHolder', 'mainblog');
$blog->TrackBacksEnabled = true; $blog->TrackBacksEnabled = true;
$blog->write();
$entry = $this->objFromFixture('BlogEntry', 'testpost'); $entry = $this->objFromFixture('BlogEntry', 'testpost');
$entry->TrackbackURL = 'testGoodTrackbackURL'; $this->assertTrue($entry->trackbackNotify('testGoodTrackbackURL'));
$this->assertTrue($entry->trackbackNotify()); $this->assertFalse($entry->trackbackNotify('testBadTrackbackURL'));
$this->assertFalse($entry->trackbackNotify('testNonExistingTrackbackURL'));
$entry->TrackbackURL = 'testBadTrackbackURL';
$this->assertFalse($entry->trackbackNotify());
$entry->TrackbackURL = 'testNonExistingTrackbackURL';
$this->assertFalse($entry->trackbackNotify());
TrackBackDecorator::$trackback_server_class = $tmpServerClass; TrackBackDecorator::$trackback_server_class = $tmpServerClass;
} }
function testOnBeforePublish() {
$tmpServerClass = TrackBackDecorator::$trackback_server_class;
TrackBackDecorator::$trackback_server_class = "TestTrackbackHTTPServer";
$blog = $this->objFromFixture('BlogHolder', 'mainblog');
$blog->TrackBacksEnabled = true;
$blog->write();
$entry1 = $this->objFromFixture('BlogEntry', 'testpost');
$entry1->doPublish();
$this->assertEquals(2, $entry1->TrackBackURLs()->Count());
$this->assertEquals(array('testGoodTrackbackURL' => 1), $entry1->TrackBackURLs()->map('URL', 'Pung'));
$entry2 = $this->objFromFixture('BlogEntry', 'testpost2');
$entry2->doPublish();
$this->assertEquals(4, $entry2->TrackBackURLs()->Count());
$this->assertEquals(array('testBadTrackbackURL' => 0, 'testGoodTrackbackURL2' => 1, 'noneExistingURL' => 0, 'testGoodTrackbackURL3' => 1), $entry2->TrackBackURLs()->map('URL', 'Pung'));
TrackBackDecorator::$trackback_server_class = $tmpServerClass;
}
function testDuplicateIsTrackBackURL() {
$url1 = $this->objFromFixture('TrackBackURL', 'goodTrackBackURL1');
$urlDup = $this->objFromFixture('TrackBackURL', 'dupTrackBackURL');
$url2 = $this->objFromFixture('TrackBackURL', 'goodTrackBackURL2');
$this->assertFalse($url2->isDuplicate());
$this->assertFalse($url2->isDuplicate(true));
$this->assertTrue($urlDup->isDuplicate());
$this->assertFalse($urlDup->isDuplicate(true));
$url1->Pung = true;
$url1->write();
$this->assertTrue($urlDup->isDuplicate(true));
}
} }
class TestTrackbackHTTPServer extends TrackbackHTTPServer implements TestOnly { class TestTrackbackHTTPServer extends TrackbackHTTPServer implements TestOnly {
function request($url, $data) { function request($url, $data) {
if($url == 'testGoodTrackbackURL') { if(in_array($url, array('testGoodTrackbackURL', 'testGoodTrackbackURL2', 'testGoodTrackbackURL3'))) {
$response = $this->goodTrackback(); $response = $this->goodTrackback();
$statusCode = '200'; $statusCode = '200';
} }

View File

@ -0,0 +1,38 @@
TrackBackURL:
goodTrackBackURL1:
URL: testGoodTrackbackURL
goodTrackBackURL2:
URL: testGoodTrackbackURL2
goodTrackBackURL3:
URL: testGoodTrackbackURL3
badTrackBackURL:
URL: testBadTrackbackURL
noneTrackBackURL:
URL: noneExistingURL
dupTrackBackURL:
URL: testGoodTrackbackURL
BlogHolder:
mainblog:
Title: Main Blog
BlogEntry:
testpost:
Title: Test Post
URLSegment: test-post
Date: 2007-02-17 18:45:00
Parent: =>BlogHolder.mainblog
Tags: tag1,tag2
TrackBackURLs: =>TrackBackURL.goodTrackBackURL1, =>TrackBackURL.dupTrackBackURL
testpost2:
Title: Test Post 2
URLSegment: test-post-2
Parent: =>BlogHolder.mainblog
TrackBackURLs: =>TrackBackURL.badTrackBackURL,=>TrackBackURL.goodTrackBackURL2,=>TrackBackURL.noneTrackBackURL,=>TrackBackURL.goodTrackBackURL3