merge master

This commit is contained in:
Christian Weiske 2010-09-30 07:46:51 +02:00
commit 2d31b55b24
12 changed files with 1137 additions and 94 deletions

View file

@ -3,12 +3,21 @@ ChangeLog for SemantiScuttle
0.9X.X - 2010-XX-XX 0.9X.X - 2010-XX-XX
------------------- -------------------
- Fix bug getTagsForBookmarks() that fetched all tags - Fix bug in getTagsForBookmarks() that fetched all tags
- Fix bug #3073215: Updating bookmark time does not work
- Fix bug #3074816: French translation breaks edit javascript
- Show error message on mysqli connection errors - Show error message on mysqli connection errors
- Implement patch #3059829: update FR_CA translation - Implement patch #3059829: update FR_CA translation
- Update php-gettext library to 1.0.10 - Update php-gettext library to 1.0.10
- Fix bug #3073215: Updating bookmark time does not work - api/posts/add respects the "replace" parameter now
- Fix bug #3074816: French translation breaks edit javascript
0.97.1 - 2010-09-30
-------------------
This is a security release! We do highly recommend to update
your SemanticScuttle installations!
- Fix bug #3077187: Permission problem when deleting bookmarks
0.97.0 - 2010-06-09 0.97.0 - 2010-06-09

10
doc/developers/api Normal file
View file

@ -0,0 +1,10 @@
SemanticScuttle API
===================
SemanticScuttle tries to implement the delicious API v1 as closely as sensible.
Where it makes sense and the delicious API just does things plainly wrong
(i.e. when returning a wrong status code on an error), we do it better.
- http://www.delicious.com/help/api
- http://support.delicious.com/forum/comments.php?DiscussionID=5286&page=1

View file

@ -176,7 +176,10 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
* Retrieves a bookmark with the given URL. * Retrieves a bookmark with the given URL.
* DOES NOT RESPECT PRIVACY SETTINGS! * DOES NOT RESPECT PRIVACY SETTINGS!
* *
* @param string $address URL to get bookmarks for * @param string $address URL to get bookmarks for
* @param boolean $all Retrieve from all users (true)
* or only bookmarks owned by the current
* user (false)
* *
* @return mixed Array with bookmark data or false in case * @return mixed Array with bookmark data or false in case
* of an error (i.e. not found). * of an error (i.e. not found).
@ -184,9 +187,9 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
* @uses getBookmarkByHash() * @uses getBookmarkByHash()
* @see getBookmarkByShortname() * @see getBookmarkByShortname()
*/ */
public function getBookmarkByAddress($address) public function getBookmarkByAddress($address, $all = true)
{ {
return $this->getBookmarkByHash($this->getHash($address)); return $this->getBookmarkByHash($this->getHash($address), $all);
} }
@ -195,16 +198,19 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
* Retrieves a bookmark with the given hash. * Retrieves a bookmark with the given hash.
* DOES NOT RESPECT PRIVACY SETTINGS! * DOES NOT RESPECT PRIVACY SETTINGS!
* *
* @param string $hash URL hash * @param string $hash URL hash
* @param boolean $all Retrieve from all users (true)
* or only bookmarks owned by the current
* user (false)
* *
* @return mixed Array with bookmark data or false in case * @return mixed Array with bookmark data or false in case
* of an error (i.e. not found). * of an error (i.e. not found).
* *
* @see getHash() * @see getHash()
*/ */
public function getBookmarkByHash($hash) public function getBookmarkByHash($hash, $all = true)
{ {
return $this->_getbookmark('bHash', $hash, true); return $this->_getbookmark('bHash', $hash, $all);
} }

View file

@ -64,6 +64,10 @@ class AllTests extends PHPUnit_Framework_TestSuite
$suite->addTestFile($tdir . '/TagTest.php'); $suite->addTestFile($tdir . '/TagTest.php');
$suite->addTestFile($tdir . '/VoteTest.php'); $suite->addTestFile($tdir . '/VoteTest.php');
$suite->addTestFile($tdir . '/UserTest.php'); $suite->addTestFile($tdir . '/UserTest.php');
$suite->addTestFile($tdir . '/Api/ExportCsvTest.php');
$suite->addTestFile($tdir . '/Api/PostsAddTest.php');
$suite->addTestFile($tdir . '/Api/PostsDeleteTest.php');
$suite->addTestFile($tdir . '/Api/PostsUpdateTest.php');
return $suite; return $suite;
} }

435
tests/Api/PostsAddTest.php Normal file
View file

@ -0,0 +1,435 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
require_once dirname(__FILE__) . '/../prepare.php';
require_once 'HTTP/Request2.php';
if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Api_PostsAddTest::main');
}
/**
* Unit tests for the SemanticScuttle post addition API.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class Api_PostsAddTest extends TestBaseApi
{
protected $urlPart = 'api/posts/add';
/**
* Used to run this test class standalone
*
* @return void
*/
public static function main()
{
require_once 'PHPUnit/TextUI/TestRunner.php';
PHPUnit_TextUI_TestRunner::run(
new PHPUnit_Framework_TestSuite(__CLASS__)
);
}
/**
* Test if authentication is required when sending no auth data
*/
public function testAuthWithoutAuthData()
{
$req = $this->getRequest(null, false);
$res = $req->send();
$this->assertEquals(401, $res->getStatus());
}
/**
* Test if authentication is required when sending wrong user data
*/
public function testAuthWrongCredentials()
{
$req = $this->getRequest(null, false);
$req->setAuth('user', 'password', HTTP_Request2::AUTH_BASIC);
$res = $req->send();
$this->assertEquals(401, $res->getStatus());
}
/**
* Test if adding a bookmark via POST works.
*/
public function testAddBookmarkPost()
{
$this->bs->deleteAll();
$bmUrl = 'http://example.org/tag-1';
$bmTags = array('foo', 'bar', 'baz');
$bmDatetime = '2010-09-08T03:02:01Z';
$bmTitle = 'This is a foo title';
$bmDescription = <<<TXT
This is the description of
my bookmark with some
newlines and <some>?&\$ÄÖ'"§special"'
characters
TXT;
list($req, $uId) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', $bmUrl);
$req->addPostParameter('description', $bmTitle);
$req->addPostParameter('extended', $bmDescription);
$req->addPostParameter('tags', implode(' ', $bmTags));
$req->addPostParameter('dt', $bmDatetime);
$res = $req->send();
//all should be well
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'done')
),
$res->getBody(),
null, false
);
//user should have one bookmark now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
$bm = $data['bookmarks'][0];
$this->assertEquals($bmUrl, $bm['bAddress']);
$this->assertEquals($bmTitle, $bm['bTitle']);
$this->assertEquals($bmDescription, $bm['bDescription']);
$this->assertEquals($bmTags, $bm['tags']);
$this->assertEquals(
gmdate('Y-m-d H:i:s', strtotime($bmDatetime)),
$bm['bDatetime']
);
}
/**
* Test if adding a bookmark via GET works.
*/
public function testAddBookmarkGet()
{
$this->bs->deleteAll();
$bmUrl = 'http://example.org/tag-1';
$bmTags = array('foo', 'bar', 'baz');
$bmDatetime = '2010-09-08T03:02:01Z';
$bmTitle = 'This is a foo title';
$bmDescription = <<<TXT
This is the description of
my bookmark with some
newlines and <some>?&\$ÄÖ'"§special"'
characters
TXT;
list($req, $uId) = $this->getAuthRequest(
'?url=' . urlencode($bmUrl)
. '&description=' . urlencode($bmTitle)
. '&extended=' . urlencode($bmDescription)
. '&tags=' . urlencode(implode(' ', $bmTags))
. '&dt=' . urlencode($bmDatetime)
);
$res = $req->send();
//all should be well
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'done')
),
$res->getBody(),
null, false
);
//user should have one bookmark now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
$bm = $data['bookmarks'][0];
$this->assertEquals($bmUrl, $bm['bAddress']);
$this->assertEquals($bmTitle, $bm['bTitle']);
$this->assertEquals($bmDescription, $bm['bDescription']);
$this->assertEquals($bmTags, $bm['tags']);
$this->assertEquals(
gmdate('Y-m-d H:i:s', strtotime($bmDatetime)),
$bm['bDatetime']
);
}
/**
* Verify that the URL and description/title are enough parameters
* to add a bookmark.
*/
public function testUrlDescEnough()
{
$this->bs->deleteAll();
list($req, $uId) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', 'http://example.org/tag2');
$req->addPostParameter('description', 'foo bar');
$res = $req->send();
//all should be well
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'done')
),
$res->getBody(),
null, false
);
//user has 1 bookmark now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
}
/**
* Verify that the URL is required
*/
public function testUrlRequired()
{
$this->bs->deleteAll();
list($req, $uId) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
//$req->addPostParameter('url', 'http://example.org/tag2');
$req->addPostParameter('description', 'foo bar');
$res = $req->send();
//all should be well
$this->assertEquals(400, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'URL missing')
),
$res->getBody(),
null, false
);
//user still has 0 bookmarks
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(0, $data['total']);
}
/**
* Verify that the description/title is required
*/
public function testDescriptionRequired()
{
$this->bs->deleteAll();
list($req, $uId) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', 'http://example.org/tag2');
$res = $req->send();
//all should be well
$this->assertEquals(400, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'Description missing')
),
$res->getBody(),
null, false
);
//user still has 0 bookmarks
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(0, $data['total']);
}
/**
* Test that the replace=no parameter prevents the bookmark from being
* overwritten.
*/
public function testReplaceNo()
{
$this->bs->deleteAll();
$url = 'http://example.org/tag2';
$title1 = 'foo bar 1';
$title2 = 'bar 2 foo';
list($req, $uId) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', $url);
$req->addPostParameter('description', $title1);
$res = $req->send();
//all should be well
$this->assertEquals(200, $res->getStatus());
//send it a second time, with different title
list($req, $dummy) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', $url);
$req->addPostParameter('description', $title2);
$req->addPostParameter('replace', 'no');
$res = $req->send();
//this time we should get an error
$this->assertEquals(409, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'bookmark does already exist')
),
$res->getBody(),
null, false
);
//user still has 1 bookmark now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
$this->assertEquals($title1, $data['bookmarks'][0]['bTitle']);
//send it a third time, without the replace parameter
// it defaults to "no", so the bookmark should not get overwritten
list($req, $dummy) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', $url);
$req->addPostParameter('description', $title2);
$res = $req->send();
//this time we should get an error
$this->assertEquals(409, $res->getStatus());
//bookmark should not have changed
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
$this->assertEquals($title1, $data['bookmarks'][0]['bTitle']);
}
/**
* Test that the replace=yes parameter causes the bookmark to be updated.
*/
public function testReplaceYes()
{
$this->bs->deleteAll();
$url = 'http://example.org/tag2';
$title1 = 'foo bar 1';
$title2 = 'bar 2 foo';
list($req, $uId) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', $url);
$req->addPostParameter('description', $title1);
$res = $req->send();
//all should be well
$this->assertEquals(200, $res->getStatus());
//send it a second time, with different title
list($req, $dummy) = $this->getAuthRequest();
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', $url);
$req->addPostParameter('description', $title2);
$req->addPostParameter('replace', 'yes');
$res = $req->send();
//no error
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'done')
),
$res->getBody(),
null, false
);
//user still has 1 bookmark now, but with the new title
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
$this->assertEquals($title2, $data['bookmarks'][0]['bTitle']);
}
}
if (PHPUnit_MAIN_METHOD == 'Api_PostsAddTest::main') {
Api_PostsAddTest::main();
}
?>

View file

@ -0,0 +1,303 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
require_once dirname(__FILE__) . '/../prepare.php';
require_once 'HTTP/Request2.php';
if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Api_PostsDeleteTest::main');
}
/**
* Unit tests for the SemanticScuttle post deletion API.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class Api_PostsDeleteTest extends TestBaseApi
{
protected $urlPart = 'api/posts/delete';
/**
* Used to run this test class standalone
*
* @return void
*/
public static function main()
{
require_once 'PHPUnit/TextUI/TestRunner.php';
PHPUnit_TextUI_TestRunner::run(
new PHPUnit_Framework_TestSuite(__CLASS__)
);
}
/**
* Test if authentication is required when sending no auth data
*/
public function testAuthWithoutAuthData()
{
$req = $this->getRequest(null, false);
$res = $req->send();
$this->assertEquals(401, $res->getStatus());
}
/**
* Test if authentication is required when sending wrong user data
*/
public function testAuthWrongCredentials()
{
$req = $this->getRequest(null, false);
$req->setAuth('user', 'password', HTTP_Request2::AUTH_BASIC);
$res = $req->send();
$this->assertEquals(401, $res->getStatus());
}
/**
* Test if deleting an own bookmark works.
*/
public function testDeleteOwnBookmark()
{
$this->bs->deleteAll();
$bookmarkUrl = 'http://example.org/tag-1';
list($req, $uId) = $this->getAuthRequest(
'?url=' . urlencode($bookmarkUrl)
);
$bId = $this->addBookmark(
$uId, $bookmarkUrl, 0,
array('unittest', 'tag1')
);
//user has one bookmark now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
//send request
$res = $req->send();
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'done')
),
$res->getBody(),
null, false
);
//bookmark should be deleted now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(0, $data['total']);
}
/**
* Test if deleting an own bookmark via POST works.
*/
public function testDeleteOwnBookmarkPost()
{
$this->bs->deleteAll();
$bookmarkUrl = 'http://example.org/tag-1';
list($req, $uId) = $this->getAuthRequest();
$bId = $this->addBookmark(
$uId, $bookmarkUrl, 0,
array('unittest', 'tag1')
);
//user has one bookmark now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
//send request
$req->setMethod(HTTP_Request2::METHOD_POST);
$req->addPostParameter('url', $bookmarkUrl);
$res = $req->send();
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'done')
),
$res->getBody(),
null, false
);
//bookmark should be deleted now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(0, $data['total']);
}
/**
* Verify that deleting a bookmark of a different does not work
*/
public function testDeleteOtherBookmark()
{
$this->bs->deleteAll();
$bookmarkUrl = 'http://example.org/tag-1';
list($req, $uId) = $this->getAuthRequest(
'?url=' . urlencode($bookmarkUrl)
);
$uId2 = $this->addUser();
$bId = $this->addBookmark(
$uId2, $bookmarkUrl, 0,
array('unittest', 'tag1')
);
//user 1 has no bookmarks
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(0, $data['total']);
//user 2 has one bookmark
$data = $this->bs->getBookmarks(0, null, $uId2);
$this->assertEquals(1, $data['total']);
//send request
$res = $req->send();
//404 - user does not have that bookmark
$this->assertEquals(404, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'item not found')
),
$res->getBody(),
'', false
);
//bookmark should still be there
$data = $this->bs->getBookmarks(0, null, $uId2);
$this->assertEquals(1, $data['total']);
}
/**
* Test if deleting a bookmark works that also other users
* bookmarked.
*/
public function testDeleteBookmarkOneOfTwo()
{
$this->bs->deleteAll();
$bookmarkUrl = 'http://example.org/tag-1';
list($req, $uId) = $this->getAuthRequest(
'?url=' . urlencode($bookmarkUrl)
);
$uId2 = $this->addUser();
$uId3 = $this->addUser();
//important: the order of addition is crucial here
$this->addBookmark(
$uId2, $bookmarkUrl, 0,
array('unittest', 'tag1')
);
$bId = $this->addBookmark(
$uId, $bookmarkUrl, 0,
array('unittest', 'tag1')
);
$this->addBookmark(
$uId3, $bookmarkUrl, 0,
array('unittest', 'tag1')
);
//user one and two have a bookmark now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
$data = $this->bs->getBookmarks(0, null, $uId2);
$this->assertEquals(1, $data['total']);
//send request
$res = $req->send();
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'result',
'attributes' => array('code' => 'done')
),
$res->getBody(),
'', false
);
//bookmark should be deleted now
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(0, $data['total']);
//user 2 should still have his
$data = $this->bs->getBookmarks(0, null, $uId2);
$this->assertEquals(1, $data['total']);
//user 3 should still have his, too
$data = $this->bs->getBookmarks(0, null, $uId3);
$this->assertEquals(1, $data['total']);
}
}
if (PHPUnit_MAIN_METHOD == 'Api_PostsDeleteTest::main') {
Api_PostsDeleteTest::main();
}
?>

View file

@ -0,0 +1,135 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
require_once dirname(__FILE__) . '/../prepare.php';
require_once 'HTTP/Request2.php';
if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Api_PostsUpdateTest::main');
}
/**
* Unit tests for the SemanticScuttle last-update time API.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class Api_PostsUpdateTest extends TestBaseApi
{
protected $urlPart = 'api/posts/update';
/**
* Used to run this test class standalone
*
* @return void
*/
public static function main()
{
require_once 'PHPUnit/TextUI/TestRunner.php';
PHPUnit_TextUI_TestRunner::run(
new PHPUnit_Framework_TestSuite(__CLASS__)
);
}
/**
* Test if authentication is required when sending no auth data
*/
public function testAuthWithoutAuthData()
{
$req = $this->getRequest(null, false);
$res = $req->send();
$this->assertEquals(401, $res->getStatus());
}
/**
* Test if authentication is required when sending wrong user data
*/
public function testAuthWrongCredentials()
{
$req = $this->getRequest(null, false);
$req->setAuth('user', 'password', HTTP_Request2::AUTH_BASIC);
$res = $req->send();
$this->assertEquals(401, $res->getStatus());
}
/**
* See if posts/update behaves correct if there is one bookmark
*/
public function testPostUpdateOneBookmark()
{
$this->bs->deleteAll();
list($req, $uId) = $this->getAuthRequest();
$bId = $this->addBookmark(
$uId, 'http://example.org/tag1', 0,
array('unittest', 'tag1')
);
$data = $this->bs->getBookmarks(0, null, $uId);
$this->assertEquals(1, $data['total']);
$bookmark = $data['bookmarks'][0];
//send request
$res = $req->send();
$this->assertEquals(200, $res->getStatus());
//verify MIME content type
$this->assertEquals(
'text/xml; charset=utf-8',
$res->getHeader('content-type')
);
//verify xml
$this->assertTag(
array(
'tag' => 'update',
'attributes' => array(
'inboxnew' => '0'
)
),
$res->getBody(),
'', false
);
//check time
$xml = simplexml_load_string($res->getBody());
$this->assertTrue(isset($xml['time']));
$this->assertEquals(
strtotime($bookmark['bDatetime']),
strtotime(
(string)$xml['time']
)
);
}
}
if (PHPUnit_MAIN_METHOD == 'Api_PostsUpdateTest::main') {
Api_PostsUpdateTest::main();
}
?>

View file

@ -29,6 +29,16 @@ class TestBaseApi extends TestBase
protected $url; protected $url;
protected $urlPart = null; protected $urlPart = null;
/**
* @var SemanticScuttle_Service_User
*/
protected $us;
/**
* @var SemanticScuttle_Service_Bookmark
*/
protected $bs;
protected function setUp() protected function setUp()
@ -52,11 +62,14 @@ class TestBaseApi extends TestBase
/** /**
* Gets a HTTP request object * Gets a HTTP request object.
* Uses $this->url plus $urlSuffix as request URL.
* *
* @param string $urlSuffix Suffix for the URL * @param string $urlSuffix Suffix for the URL
* *
* @return HTTP_Request2 HTTP request object * @return HTTP_Request2 HTTP request object
*
* @uses $url
*/ */
protected function getRequest($urlSuffix = null) protected function getRequest($urlSuffix = null)
{ {
@ -71,13 +84,17 @@ class TestBaseApi extends TestBase
/** /**
* Gets a HTTP request object * Creates a user and a HTTP request object and prepares
* the request object with authentication details, so that
* the user is logged in.
* *
* @param string $urlSuffix Suffix for the URL * @param string $urlSuffix Suffix for the URL
* @param mixed $auth If user authentication is needed (true/false) * @param mixed $auth If user authentication is needed (true/false)
* or array with username and password * or array with username and password
* *
* @return array(HTTP_Request2, integer) HTTP request object and user id * @return array(HTTP_Request2, integer) HTTP request object and user id
*
* @uses getRequest()
*/ */
protected function getAuthRequest($urlSuffix = null, $auth = true) protected function getAuthRequest($urlSuffix = null, $auth = true)
{ {

View file

@ -1,10 +1,29 @@
<?php <?php
/**
* Checks if the user is logged on and sends a HTTP basic auth
* request to the browser if not. In that case the script ends.
* If username and password are available, the user service's
* login method is used to log the user in.
*
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
require_once '../www-header.php'; require_once '../www-header.php';
// Provides HTTP Basic authentication of a user /**
// and logs the user in if necessary * Sends HTTP auth headers to the browser
*/
function authenticate() { function authenticate()
{
header('WWW-Authenticate: Basic realm="SemanticScuttle API"'); header('WWW-Authenticate: Basic realm="SemanticScuttle API"');
header('HTTP/1.0 401 Unauthorized'); header('HTTP/1.0 401 Unauthorized');
@ -26,7 +45,9 @@ if (!$userservice->isLoggedOn()) {
if (!isset($_SERVER['PHP_AUTH_USER'])) { if (!isset($_SERVER['PHP_AUTH_USER'])) {
authenticate(); authenticate();
} else { } else {
$login = $userservice->login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); $login = $userservice->login(
$_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']
);
if ($login) { if ($login) {
$currentUser = $userservice->getCurrentObjectUser(); $currentUser = $userservice->getCurrentObjectUser();
} else { } else {

View file

@ -1,67 +1,105 @@
<?php <?php
// Implements the del.icio.us API request to add a new post. /**
// http://delicious.com/help/api#posts_add * API for adding a new bookmark.
*
// del.icio.us behavior: * The following POST and GET parameters are accepted:
// - tags can't have spaces * @param string $url URL of the bookmark (required)
// - address and description are mandatory * @param string $description Bookmark title (required)
* @param string $extended Extended bookmark description (optional)
// Scuttle behavior: * @param string $tags Space-separated list of tags (optional)
// - Additional 'status' variable for privacy * @param string $dt Date and time of bookmark creation (optional)
// - No support for 'replace' variable * Must be of format YYYY-MM-DDTHH:II:SSZ
* @param integer $status Visibility status (optional):
* - 2 or 'private': Bookmark is totally private
* - 1 or 'shared': People on the user's watchlist
* can see it
* - 0 or 'public': Everyone can see the bookmark
* @param string $shared "no" or "yes": Switches between private and
* public (optional)
* @param string $replace "yes" or "no" - replaces a bookmark with the
* same URL (optional)
*
* Notes:
* - tags cannot have spaces
* - URL and description (title) are mandatory
* - delicious "description" is the "title" in SemanticScuttle
* - delicious "extended" is the "description" in SemanticScuttle
* - "status" is a SemanticScuttle addition to this API method
*
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
* @link http://www.delicious.com/help/api
*/
// Force HTTP authentication // Force HTTP authentication
$httpContentType = 'text/xml'; $httpContentType = 'text/xml';
require_once 'httpauth.inc.php'; require_once 'httpauth.inc.php';
/* Service creation: only useful services are created */ $bs = SemanticScuttle_Service_Factory::get('Bookmark');
$bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark');
// Get all the bookmark's passed-in information // Get all the bookmark's passed-in information
if (isset($_REQUEST['url']) && (trim($_REQUEST['url']) != '')) if (isset($_REQUEST['url']) && (trim($_REQUEST['url']) != '')) {
$url = trim(urldecode($_REQUEST['url'])); $url = trim(urldecode($_REQUEST['url']));
else } else {
$url = NULL; $url = null;
}
if (isset($_REQUEST['description']) && (trim($_REQUEST['description']) != '')) if (isset($_REQUEST['description']) && (trim($_REQUEST['description']) != '')) {
$description = trim($_REQUEST['description']); $description = trim($_REQUEST['description']);
else } else {
$description = NULL; $description = null;
}
if (isset($_REQUEST['extended']) && (trim($_REQUEST['extended']) != "")) if (isset($_REQUEST['extended']) && (trim($_REQUEST['extended']) != '')) {
$extended = trim($_REQUEST['extended']); $extended = trim($_REQUEST['extended']);
else } else {
$extended = NULL; $extended = null;
}
if (isset($_REQUEST['tags']) && (trim($_REQUEST['tags']) != '') && (trim($_REQUEST['tags']) != ',')) if (isset($_REQUEST['tags']) && (trim($_REQUEST['tags']) != '')
&& (trim($_REQUEST['tags']) != ',')
) {
$tags = trim($_REQUEST['tags']); $tags = trim($_REQUEST['tags']);
else } else {
$tags = NULL; $tags = null;
}
if (isset($_REQUEST['dt']) && (trim($_REQUEST['dt']) != '')) if (isset($_REQUEST['dt']) && (trim($_REQUEST['dt']) != '')) {
$dt = trim($_REQUEST['dt']); $dt = trim($_REQUEST['dt']);
else } else {
$dt = NULL; $dt = null;
}
$replace = isset($_REQUEST['replace']) && ($_REQUEST['replace'] == 'yes');
$status = 0; $status = 0;
if (isset($_REQUEST['status'])) { if (isset($_REQUEST['status'])) {
$status_str = trim($_REQUEST['status']); $status_str = trim($_REQUEST['status']);
if (is_numeric($status_str)) { if (is_numeric($status_str)) {
$status = intval($status_str); $status = intval($status_str);
if($status < 0 || $status > 2) { if ($status < 0 || $status > 2) {
$status = 0; $status = 0;
} }
} else { } else {
switch ($status_str) { switch ($status_str) {
case 'private': case 'private':
$status = 2; $status = 2;
break; break;
case 'shared': case 'shared':
$status = 1; $status = 1;
break; break;
default: default:
$status = 0; $status = 0;
break; break;
} }
} }
} }
@ -71,17 +109,38 @@ if (isset($_REQUEST['shared']) && (trim($_REQUEST['shared']) == 'no')) {
} }
// Error out if there's no address or description // Error out if there's no address or description
if (is_null($url) || is_null($description)) { if (is_null($url)) {
$added = false; header('HTTP/1.0 400 Bad Request');
$msg = 'URL missing';
} else if (is_null($description)) {
header('HTTP/1.0 400 Bad Request');
$msg = 'Description missing';
} else { } else {
// We're good with info; now insert it! // We're good with info; now insert it!
if ($bookmarkservice->bookmarkExists($url, $userservice->getCurrentUserId())) $exists = $bs->bookmarkExists($url, $userservice->getCurrentUserId());
$added = false; if ($exists) {
else if (!$replace) {
$added = $bookmarkservice->addBookmark($url, $description, $extended, '', $status, $tags, null, $dt, true); header('HTTP/1.0 409 Conflict');
$msg = 'bookmark does already exist';
} else {
//delete it before we re-add it
$bookmark = $bs->getBookmarkByAddress($url, false);
$bId = $bookmark['bId'];
$bs->deleteBookmark($bId);
$exists = false;
}
}
if (!$exists) {
$added = $bs->addBookmark(
$url, $description, $extended, '', $status, $tags, null, $dt, true
);
$msg = 'done';
}
} }
// Set up the XML file and output the result. // Set up the XML file and output the result.
echo '<?xml version="1.0" standalone="yes" ?'.">\r\n"; echo '<?xml version="1.0" standalone="yes" ?' . ">\r\n";
echo '<result code="'. ($added ? 'done' : 'something went wrong') .'" />'; echo '<result code="' . $msg .'" />';
?> ?>

View file

@ -1,33 +1,57 @@
<?php <?php
// Implements the del.icio.us API request to delete a post. /**
* API for deleting a bookmark.
// del.icio.us behavior: * The delicious API is implemented here.
// - returns "done" even if the bookmark doesn't exist; *
// - does NOT allow the hash for the url parameter; * The delicious API behaves like that:
// - doesn't set the Content-Type to text/xml (we do). * - does NOT allow the hash for the url parameter
* - doesn't set the Content-Type to text/xml
* - we do it correctly, too
*
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
* @link http://www.delicious.com/help/api
*/
// Force HTTP authentication first! // Force HTTP authentication first!
$httpContentType = 'text/xml'; $httpContentType = 'text/xml';
require_once 'httpauth.inc.php'; require_once 'httpauth.inc.php';
/* Service creation: only useful services are created */ $bs = SemanticScuttle_Service_Factory::get('Bookmark');
$bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark'); $uId = $userservice->getCurrentUserId();
// Note that del.icio.us only errors out if no URL was passed in; there's no error on attempting
// to delete a bookmark you don't have.
// Error out if there's no address // Error out if there's no address
if (is_null($_REQUEST['url'])) { if (!isset($_REQUEST['url'])
$deleted = false; || $_REQUEST['url'] == ''
) {
$msg = 'something went wrong';
} else if (!$bs->bookmarkExists($_REQUEST['url'], $uId)) {
//the user does not have such a bookmark
header('HTTP/1.0 404 Not Found');
$msg = 'item not found';
} else { } else {
$bookmark = $bookmarkservice->getBookmarkByAddress($_REQUEST['url']); $bookmark = $bs->getBookmarkByAddress($_REQUEST['url'], false);
$bid = $bookmark['bId']; $bId = $bookmark['bId'];
$delete = $bookmarkservice->deleteBookmark($bid); $deleted = $bs->deleteBookmark($bId);
$deleted = true; $msg = 'done';
if (!$deleted) {
//something really went wrong
header('HTTP/1.0 500 Internal Server Error');
$msg = 'something really went wrong';
}
} }
// Set up the XML file and output the result. // Set up the XML file and output the result.
echo '<?xml version="1.0" standalone="yes" ?'.">\r\n"; echo '<?xml version="1.0" standalone="yes" ?' . ">\r\n";
echo '<result code="'. ($deleted ? 'done' : 'something went wrong') .'" />'; echo '<result code="' . $msg . '" />';
?> ?>

View file

@ -1,24 +1,44 @@
<?php <?php
// Implements the del.icio.us API request for a user's last update time and date. /**
* API for retrieving a user's last update time.
// del.icio.us behavior: * That is the time the user changed a bookmark lastly.
// - doesn't set the Content-Type to text/xml (we do). * The delicious API is implemented here.
*
* Delicious also returns "the number of new items in
* the user's inbox since it was last visited." - we do
* that too, so we are as close at the API as possible,
* not breaking delicious clients.
*
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Benjamin Huynh-Kim-Bang <mensonge@users.sourceforge.net>
* @author Christian Weiske <cweiske@cweiske.de>
* @author Eric Dane <ericdane@users.sourceforge.net>
* @license GPL http://www.gnu.org/licenses/gpl.html
* @link http://sourceforge.net/projects/semanticscuttle
* @link http://www.delicious.com/help/api
*/
// Force HTTP authentication first! // Force HTTP authentication first!
$httpContentType = 'text/xml'; $httpContentType = 'text/xml';
require_once 'httpauth.inc.php'; require_once 'httpauth.inc.php';
/* Service creation: only useful services are created */ $bs = SemanticScuttle_Service_Factory::get('Bookmark');
$bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark');
// Get the posts relevant to the passed-in variables.
$bookmarks =& $bookmarkservice->getBookmarks(0, 1, $userservice->getCurrentUserId());
$bookmarks = $bs->getBookmarks(0, 1, $userservice->getCurrentUserId());
// Set up the XML file and output all the tags. // Set up the XML file and output all the tags.
echo '<?xml version="1.0" standalone="yes" ?'.">\r\n"; echo '<?xml version="1.0" standalone="yes" ?' . ">\r\n";
foreach($bookmarks['bookmarks'] as $row) { //foreach is used in case there are no bookmarks
echo '<update time="'. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime'])) .'" />'; foreach ($bookmarks['bookmarks'] as $row) {
echo '<update time="'
. gmdate('Y-m-d\TH:i:s\Z', strtotime($row['bDatetime']))
. '"'
. ' inboxnew="0"'
. ' />';
} }
?> ?>