From 0c930607f0444fef11e2fb7d5c50eadd905cccc7 Mon Sep 17 00:00:00 2001 From: cweiske Date: Tue, 16 Feb 2010 21:50:49 +0000 Subject: [PATCH 01/63] do not return numbers < 0 git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@652 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 0ac1855..3ea5b5c 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -916,9 +916,10 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService message_die(GENERAL_ERROR, 'Could not get vars', '', __LINE__, __FILE__, $sql, $this->db); } - $output = $this->db->sql_fetchfield(0, 0) - 1; + $count = $this->db->sql_fetchfield(0, 0); + $count = ($count > 0) ? $count - 1 : (int)$count; $this->db->sql_freeresult($dbresult); - return $output; + return $count; } From 7f2e3472174354bd3f23875bdbe23914f89269dd Mon Sep 17 00:00:00 2001 From: cweiske Date: Tue, 16 Feb 2010 21:52:45 +0000 Subject: [PATCH 02/63] do not return numbers < 0 git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@653 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 3ea5b5c..c4d198d 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -911,7 +911,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $privacy = ' AND B.bStatus = 0'; } - $sql = 'SELECT COUNT(*) FROM '. $userservice->getTableName() .' AS U, '. $GLOBALS['tableprefix'] .'bookmarks AS B WHERE U.'. $userservice->getFieldName('primary') .' = B.uId AND B.bHash = "'. md5($address) .'"'. $privacy; + $sql = 'SELECT COUNT(*) as "0" FROM '. $userservice->getTableName() .' AS U, '. $GLOBALS['tableprefix'] .'bookmarks AS B WHERE U.'. $userservice->getFieldName('primary') .' = B.uId AND B.bHash = "'. md5($address) .'"'. $privacy; if (!($dbresult = & $this->db->sql_query($sql))) { message_die(GENERAL_ERROR, 'Could not get vars', '', __LINE__, __FILE__, $sql, $this->db); } From e5dab0a740e71384031caadecb9f9e283572e8f2 Mon Sep 17 00:00:00 2001 From: cweiske Date: Tue, 16 Feb 2010 21:54:31 +0000 Subject: [PATCH 03/63] allow adding of certain addresses git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@654 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/TestBase.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/TestBase.php b/tests/TestBase.php index 05988a5..f23f678 100644 --- a/tests/TestBase.php +++ b/tests/TestBase.php @@ -29,11 +29,12 @@ class TestBase extends PHPUnit_Framework_TestCase /** * Create a new bookmark. * - * @param integer $user User ID the bookmark shall belong + * @param integer $user User ID the bookmark shall belong + * @param string $address Bookmark address to use * * @return integer ID of bookmark */ - protected function addBookmark($user = null) + protected function addBookmark($user = null, $address = null) { if ($user === null) { $user = $this->addUser(); @@ -41,8 +42,13 @@ class TestBase extends PHPUnit_Framework_TestCase $bs = SemanticScuttle_Service_Factory::get('Bookmark'); $rand = rand(); + + if ($address === null) { + $address = 'http://example.org/' . $rand; + } + $bid = $bs->addBookmark( - 'http://example.org/' . $rand, + $address, 'unittest bookmark #' . $rand, 'description', null, From 157adfd7eb157917d338571426ad94539c37c3f8 Mon Sep 17 00:00:00 2001 From: cweiske Date: Tue, 16 Feb 2010 21:55:50 +0000 Subject: [PATCH 04/63] multiple tests for SemanticScuttle_Service_Bookmark::countOthers() git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@655 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/BookmarkTest.php | 101 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index 741b6bf..ca4ff3e 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -778,6 +778,107 @@ class BookmarkTest extends TestBase $this->assertEquals('newShortNambb', $bm['bShort']); } + + + /** + * Test what countOther() returns when the address does not exist + * + * @return void + */ + public function testCountOthersAddressDoesNotExist() + { + $this->assertEquals(0, $this->bs->countOthers('http://example.org')); + } + + + + /** + * Test what countOther() returns when nobody else has the same bookmark + * + * @return void + */ + public function testCountOthersNone() + { + $uid = $this->addUser(); + $address = 'http://example.org'; + $this->addBookmark($uid, $address); + $this->assertEquals(0, $this->bs->countOthers($address)); + } + + + + /** + * Test what countOther() returns when the address exists only once + * and multiple bookmarks are in the database. + * + * @return void + */ + public function testCountOthersMultipleNone() + { + $uid = $this->addUser(); + $address = 'http://example.org'; + $this->addBookmark($uid, $address); + $this->addBookmark($uid); + $this->addBookmark($uid); + $this->assertEquals(0, $this->bs->countOthers($address)); + } + + + + /** + * Test what countOther() returns when the address exists only once + * and the same user and other users have other bookmarks + * + * @return void + */ + public function testCountOthersMultipleUsersNone() + { + $uid = $this->addUser(); + $uid2 = $this->addUser(); + $address = 'http://example.org'; + $this->addBookmark($uid, $address); + $this->addBookmark($uid); + $this->addBookmark($uid2); + $this->assertEquals(0, $this->bs->countOthers($address)); + } + + + + /** + * Test what countOther() returns when the address exists two + * times in the database. + * + * @return void + */ + public function testCountOthersOne() + { + $uid = $this->addUser(); + $uid2 = $this->addUser(); + $address = 'http://example.org'; + $this->addBookmark($uid, $address); + $this->addBookmark($uid2, $address); + $this->assertEquals(1, $this->bs->countOthers($address)); + } + + + + /** + * Test what countOther() returns when the address exists four + * times in the database. + * + * @return void + */ + public function testCountOthersThree() + { + $uid = $this->addUser(); + $address = 'http://example.org'; + $this->addBookmark($uid, $address); + $this->addBookmark(null, $address); + $this->addBookmark(null, $address); + $this->addBookmark(null, $address); + $this->assertEquals(3, $this->bs->countOthers($address)); + } + } From 57d4892eb346bf8837416dd4ea3571d87bd0f486 Mon Sep 17 00:00:00 2001 From: cweiske Date: Tue, 16 Feb 2010 21:57:03 +0000 Subject: [PATCH 05/63] allow setting of status during addBookmark in tests git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@656 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/TestBase.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/TestBase.php b/tests/TestBase.php index f23f678..277be02 100644 --- a/tests/TestBase.php +++ b/tests/TestBase.php @@ -31,11 +31,15 @@ class TestBase extends PHPUnit_Framework_TestCase * * @param integer $user User ID the bookmark shall belong * @param string $address Bookmark address to use + * @param integer $status Bookmark visibility * * @return integer ID of bookmark + * + * @see SemanticScuttle_Service_Bookmark::addBookmark() */ - protected function addBookmark($user = null, $address = null) - { + protected function addBookmark( + $user = null, $address = null, $status = 0 + ) { if ($user === null) { $user = $this->addUser(); } @@ -52,7 +56,7 @@ class TestBase extends PHPUnit_Framework_TestCase 'unittest bookmark #' . $rand, 'description', null, - 0, + $status, array('unittest'), null, null, false, false, $user From 2f13a1c81956dba215ae37c7debf58de5e658ad4 Mon Sep 17 00:00:00 2001 From: cweiske Date: Tue, 16 Feb 2010 21:58:00 +0000 Subject: [PATCH 06/63] test complex combination of watches, publics and private bookmarks with countOthers() git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@657 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/BookmarkTest.php | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index ca4ff3e..d791b9e 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -879,6 +879,70 @@ class BookmarkTest extends TestBase $this->assertEquals(3, $this->bs->countOthers($address)); } + + + /** + * Test what countOther() returns when the user is logged in + * and friends (people on the watchlist) have bookmarked + * and shared the same address. + * + * @return void + */ + public function testCountOthersWatchlist() + { + $uid = $this->addUser(); + $address = 'http://example.org'; + //log user in + $this->us->setCurrentUserId($uid); + + //setup users + $otherPublic1 = $this->addUser(); + $otherPublic2 = $this->addUser(); + $otherShared1 = $this->addUser(); + $otherPrivate1 = $this->addUser(); + $friendPublic1 = $this->addUser(); + $friendShared1 = $this->addUser(); + $friendShared2 = $this->addUser(); + $friendPrivate1 = $this->addUser(); + $friendSharing1 = $this->addUser(); + + //setup watchlists + $us = SemanticScuttle_Service_Factory::get('User'); + $this->us->setCurrentUserId($friendPublic1); + $us->setWatchStatus($uid); + $this->us->setCurrentUserId($friendShared1); + $us->setWatchStatus($uid); + $this->us->setCurrentUserId($friendShared2); + $us->setWatchStatus($uid); + $this->us->setCurrentUserId($friendPrivate1); + $us->setWatchStatus($uid); + + //back to login of main user + $this->us->setCurrentUserId($uid); + $us->setWatchStatus($friendSharing1); + + //add bookmarks + $this->addBookmark($uid, $address, 0); + $this->addBookmark($otherPublic1, $address, 0); + $this->addBookmark($otherPublic2, $address, 0); + $this->addBookmark($otherShared1, $address, 1); + $this->addBookmark($otherPrivate1, $address, 2); + $this->addBookmark($friendPublic1, $address, 0); + $this->addBookmark($friendShared1, $address, 1); + $this->addBookmark($friendShared2, $address, 1); + $this->addBookmark($friendPrivate1, $address, 2); + //this user is on our watchlist, but we not on his + $this->addBookmark($friendSharing1, $address, 1); + + //2 public + //1 public (friend) + //2 shared + //-> 5 + $this->assertEquals(5, $this->bs->countOthers($address)); + } + + + } From 91da444e762bd2676e94a19d45401d2e83858202 Mon Sep 17 00:00:00 2001 From: cweiske Date: Tue, 16 Feb 2010 21:59:39 +0000 Subject: [PATCH 07/63] reformat countOthers() git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@658 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 46 +++++++++++++++++------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index c4d198d..05ea060 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -889,31 +889,51 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService - function countOthers($address) + /** + * Counts the number of bookmarks that have the same address + * as the given address + * + * @param string $address Address/URL to look for + * + * @return integer Number of bookmarks minus one that have the address + */ + public function countOthers($address) { if (!$address) { return false; } - $userservice = SemanticScuttle_Service_Factory :: get('User'); - $sId = $userservice->getCurrentUserId(); + $us = SemanticScuttle_Service_Factory::get('User'); + $sId = (int)$us->getCurrentUserId(); - if ($userservice->isLoggedOn()) { - // All public bookmarks, user's own bookmarks and any shared with user - $privacy = ' AND ((B.bStatus = 0) OR (B.uId = '. $sId .')'; - $watchnames = $userservice->getWatchNames($sId, true); - foreach($watchnames as $watchuser) { - $privacy .= ' OR (U.username = "'. $watchuser .'" AND B.bStatus = 1)'; + if ($us->isLoggedOn()) { + //All public bookmarks, user's own bookmarks + // and any shared with our user + $privacy = ' AND ((B.bStatus = 0) OR (B.uId = ' . $sId . ')'; + $watchnames = $us->getWatchNames($sId, true); + foreach ($watchnames as $watchuser) { + $privacy .= ' OR (U.username = "' + . $this->db->sql_escape($watchuser) + . '" AND B.bStatus = 1)'; } $privacy .= ')'; } else { - // Just public bookmarks + //Just public bookmarks $privacy = ' AND B.bStatus = 0'; } - $sql = 'SELECT COUNT(*) as "0" FROM '. $userservice->getTableName() .' AS U, '. $GLOBALS['tableprefix'] .'bookmarks AS B WHERE U.'. $userservice->getFieldName('primary') .' = B.uId AND B.bHash = "'. md5($address) .'"'. $privacy; - if (!($dbresult = & $this->db->sql_query($sql))) { - message_die(GENERAL_ERROR, 'Could not get vars', '', __LINE__, __FILE__, $sql, $this->db); + $sql = 'SELECT COUNT(*) as "0" FROM ' + . $us->getTableName() . ' AS U' + . ', '. $GLOBALS['tableprefix'] . 'bookmarks AS B' + . ' WHERE U.'. $us->getFieldName('primary') .' = B.uId' + . ' AND B.bHash = "'. md5($address) . '"' + . $privacy; + + if (!($dbresult = $this->db->sql_query($sql))) { + message_die( + GENERAL_ERROR, 'Could not get other count', + '', __LINE__, __FILE__, $sql, $this->db + ); } $count = $this->db->sql_fetchfield(0, 0); From 6b7217daf298be65347205aa7a0fee17ff37b87c Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:03:20 +0000 Subject: [PATCH 08/63] make countOthers() accept an array of addresses git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@659 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 53 ++++++++++++---- tests/BookmarkTest.php | 80 ++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 11 deletions(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 05ea060..c7bfb3b 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -891,17 +891,29 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService /** * Counts the number of bookmarks that have the same address - * as the given address + * as the given address. * - * @param string $address Address/URL to look for + * @internal + * We do support fetching counts for multiple addresses at once + * because that allows us to reduce the number of queries + * we need in the web interface when displaying i.e. + * 10 bookmarks - only one SQL query is needed then. * - * @return integer Number of bookmarks minus one that have the address + * @param string|array $addresses Address/URL to look for, string + * of one address or array with + * multiple ones + * + * @return integer Number of bookmarks minus one that have the address. + * In case $addresses was an array, key-value array + * with key being the address, value said number of + * bookmarks */ - public function countOthers($address) + public function countOthers($addresses) { - if (!$address) { + if (!$addresses) { return false; } + $bArray = is_array($addresses); $us = SemanticScuttle_Service_Factory::get('User'); $sId = (int)$us->getCurrentUserId(); @@ -922,12 +934,22 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $privacy = ' AND B.bStatus = 0'; } - $sql = 'SELECT COUNT(*) as "0" FROM ' + $addressesSql = ' AND (0'; + foreach ((array)$addresses as $address) { + $addressesSql .= ' OR B.bHash = "' + . $this->db->sql_escape(md5($address)) + . '"'; + } + $addressesSql .= ')'; + + + $sql = 'SELECT B.bAddress, COUNT(*) as count FROM ' . $us->getTableName() . ' AS U' . ', '. $GLOBALS['tableprefix'] . 'bookmarks AS B' . ' WHERE U.'. $us->getFieldName('primary') .' = B.uId' - . ' AND B.bHash = "'. md5($address) . '"' - . $privacy; + . $addressesSql + . $privacy + . ' GROUP BY B.bHash'; if (!($dbresult = $this->db->sql_query($sql))) { message_die( @@ -936,10 +958,19 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService ); } - $count = $this->db->sql_fetchfield(0, 0); - $count = ($count > 0) ? $count - 1 : (int)$count; + //be sure we also list urls in our array + // that are not found in the database + $counts = array_combine( + (array)$addresses, + array_fill(0, count((array)$addresses), 0) + ); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $counts[$row['bAddress']] + = $row['count'] > 0 ? $row['count'] - 1 : 0; + } $this->db->sql_freeresult($dbresult); - return $count; + + return $bArray ? $counts : reset($counts); } diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index d791b9e..69e6e8a 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -943,6 +943,86 @@ class BookmarkTest extends TestBase + /** + * Test what countOther() returns when multiple addresses are + * passed to it and none of them exists. + * + * @return void + */ + public function testCountOthersArrayNone() + { + $this->assertEquals( + array('1' => 0, '2' => 0, '3' => 0), + $this->bs->countOthers(array('1', '2', '3')) + ); + } + + + + /** + * Test what countOther() returns when multiple addresses are + * passed to it and only one of them exists. + * + * @return void + */ + public function testCountOthersArrayOneNone() + { + $uid = $this->addUser(); + $uid2 = $this->addUser(); + $address1 = 'http://example.org/1'; + $address2 = 'http://example.org/2'; + $this->addBookmark($uid, $address1); + $this->addBookmark($uid, $address2); + $this->addBookmark($uid2, $address1); + $this->assertEquals( + array( + $address1 => 1, + $address2 => 0 + ), + $this->bs->countOthers( + array($address1, $address2) + ) + ); + } + + + + /** + * Test what countOther() returns when multiple addresses are passed + * to it and both of them exist with different numbers for each. + * + * @return void + */ + public function testCountOthersArrayTwoOne() + { + $uid = $this->addUser(); + $uid2 = $this->addUser(); + $uid3 = $this->addUser(); + + $address1 = 'http://example.org/1'; + $address2 = 'http://example.org/2'; + + $this->addBookmark($uid, $address1); + $this->addBookmark($uid, $address2); + + $this->addBookmark($uid2, $address1); + $this->addBookmark($uid2, $address2); + + $this->addBookmark($uid3, $address1); + + $this->assertEquals( + array( + $address1 => 2, + $address2 => 1 + ), + $this->bs->countOthers( + array($address1, $address2) + ) + ); + } + + + } From 05c23695077062ea6948b7c5603848e941c6e9df Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:04:51 +0000 Subject: [PATCH 09/63] replace some strange foreach constructs with the proper variant git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@660 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/templates/bookmarks.tpl.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/data/templates/bookmarks.tpl.php b/data/templates/bookmarks.tpl.php index 0e9ac95..0050ec8 100644 --- a/data/templates/bookmarks.tpl.php +++ b/data/templates/bookmarks.tpl.php @@ -217,8 +217,7 @@ if($currenttag!= '') { id="bookmarks"> &$row) { switch ($row['bStatus']) { case 0: $access = ''; @@ -234,9 +233,7 @@ if($currenttag!= '') { $cats = ''; $tagsForCopy = ''; $tags = $row['tags']; - foreach(array_keys($tags) as $key) { - - $tag =& $tags[$key]; + foreach ($tags as $tkey => &$tag) { $cats .= ', '; $tagsForCopy.= $tag.','; } From fe522e57197133d3a4a09425bf2067418a6f3c7c Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:06:12 +0000 Subject: [PATCH 10/63] first sql optimization: fetch countOthers() for all bookmarks at once instead of each single git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@661 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/templates/bookmarks.tpl.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/data/templates/bookmarks.tpl.php b/data/templates/bookmarks.tpl.php index 0050ec8..b1a6eb0 100644 --- a/data/templates/bookmarks.tpl.php +++ b/data/templates/bookmarks.tpl.php @@ -216,7 +216,13 @@ if($currenttag!= '') {
    0 ? ' start="'. ++$start .'"' : ''); ?> id="bookmarks"> - &$row) { + $addresses[$row['bId']] = $row['bAddress']; + } + $otherCounts = $bookmarkservice->countOthers($addresses); + foreach ($bookmarks as $key => &$row) { switch ($row['bStatus']) { case 0: @@ -261,7 +267,7 @@ if($currenttag!= '') { // Udders! if (!isset($hash)) { - $others = $bookmarkservice->countOthers($row['bAddress']); + $others = $otherCounts[$row['bAddress']]; $ostart = ''; $oend = ''; switch ($others) { From 46b96044fb2375d4b522fa074788199d80b4d243 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:07:37 +0000 Subject: [PATCH 11/63] test getBookmarks() with tag loading functionality git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@662 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/BookmarkTest.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index 69e6e8a..39a9974 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -331,6 +331,40 @@ class BookmarkTest extends TestBase + /** + * Check tag loading functionality of getBookmarks() + * + * @return void + */ + public function testGetBookmarksIncludeTags() + { + $uid = $this->addUser(); + $bid = $this->addBookmark($uid); + $this->b2ts->attachTags($bid, array('foo', 'bar')); + $bid2 = $this->addBookmark($uid); + $this->b2ts->attachTags($bid2, array('fuu', 'baz')); + + $bms = $this->bs->getBookmarks(); + $this->assertEquals(2, count($bms['bookmarks'])); + $this->assertEquals(2, $bms['total']); + + foreach ($bms['bookmarks'] as $bm) { + $this->assertArrayHasKey('tags', $bm); + $this->assertType('array', $bm['tags']); + if ($bm['bId'] == $bid) { + $this->assertContains('foo', $bm['tags']); + $this->assertContains('bar', $bm['tags']); + } else if ($bm['bId'] == $bid2) { + $this->assertContains('fuu', $bm['tags']); + $this->assertContains('baz', $bm['tags']); + } else { + $this->assertTrue(false, 'Unknown bookmark id'); + } + } + } + + + /** * Test if deleting a bookmark works. * From 97c3d1ed636609ef19dd3cc268d0f5923f5257db Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:08:52 +0000 Subject: [PATCH 12/63] add test for Bookmark2Tag::getTagsForBookmark() git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@663 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/Bookmark2TagTest.php | 128 +++++++++++++++++++++++++++++++++++++ tests/TestBase.php | 10 ++- 2 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 tests/Bookmark2TagTest.php diff --git a/tests/Bookmark2TagTest.php b/tests/Bookmark2TagTest.php new file mode 100644 index 0000000..7d003c3 --- /dev/null +++ b/tests/Bookmark2TagTest.php @@ -0,0 +1,128 @@ + + * @author Christian Weiske + * @author Eric Dane + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ + +require_once 'prepare.php'; + +if (!defined('PHPUnit_MAIN_METHOD')) { + define('PHPUnit_MAIN_METHOD', 'Bookmark2TagTest::main'); +} + +/** + * Unit tests for the SemanticScuttle bookmark-tag combination service. + * + * @category Bookmarking + * @package SemanticScuttle + * @author Benjamin Huynh-Kim-Bang + * @author Christian Weiske + * @author Eric Dane + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ +class Bookmark2TagTest extends TestBase +{ + protected $us; + protected $bs; + protected $ts; + protected $tts; + + + + /** + * 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__) + ); + } + + + + protected function setUp() + { + $this->us = SemanticScuttle_Service_Factory::get('User'); + $this->bs = SemanticScuttle_Service_Factory::get('Bookmark'); + $this->bs->deleteAll(); + $this->b2ts= SemanticScuttle_Service_Factory::get('Bookmark2Tag'); + $this->b2ts->deleteAll(); + $this->tts = SemanticScuttle_Service_Factory::get('Tag2Tag'); + $this->tts->deleteAll(); + $this->tsts = SemanticScuttle_Service_Factory::get('TagStat'); + $this->tsts->deleteAll(); + $this->vs = SemanticScuttle_Service_Factory::get('Vote'); + $this->vs->deleteAll(); + } + + + + /** + * Test getTagsForBookmark() when the bookmark has no tags + * + * @return void + */ + public function testGetTagsForBookmarkNone() + { + $bid = $this->addBookmark(null, null, 0, array()); + $this->assertEquals( + array(), + $this->b2ts->getTagsForBookmark($bid) + ); + } + + + + /** + * Test getTagsForBookmark() when the bookmark has one tag + * + * @return void + */ + public function testGetTagsForBookmarkOne() + { + $bid = $this->addBookmark(null, null, 0, array()); + $this->b2ts->attachTags($bid, array('foo')); + $this->assertEquals( + array('foo'), + $this->b2ts->getTagsForBookmark($bid) + ); + } + + + + /** + * Test getTagsForBookmark() when the bookmark has three tags + * + * @return void + */ + public function testGetTagsForBookmarkThree() + { + $bid = $this->addBookmark(null, null, 0, array()); + $this->b2ts->attachTags($bid, array('foo', 'bar', 'fuu')); + + $tags = $this->b2ts->getTagsForBookmark($bid); + $this->assertType('array', $tags); + $this->assertContains('foo', $tags); + $this->assertContains('bar', $tags); + $this->assertContains('fuu', $tags); + } +} + +if (PHPUnit_MAIN_METHOD == 'Bookmark2TagTest::main') { + Bookmark2TagTest::main(); +} +?> \ No newline at end of file diff --git a/tests/TestBase.php b/tests/TestBase.php index 277be02..28bda27 100644 --- a/tests/TestBase.php +++ b/tests/TestBase.php @@ -32,17 +32,23 @@ class TestBase extends PHPUnit_Framework_TestCase * @param integer $user User ID the bookmark shall belong * @param string $address Bookmark address to use * @param integer $status Bookmark visibility + * @param array $tags Array of tags to attach. If "null" is given, + * it will automatically be "unittest" * * @return integer ID of bookmark * * @see SemanticScuttle_Service_Bookmark::addBookmark() */ protected function addBookmark( - $user = null, $address = null, $status = 0 + $user = null, $address = null, $status = 0, + $tags = null ) { if ($user === null) { $user = $this->addUser(); } + if ($tags === null) { + $tags = array('unittest'); + } $bs = SemanticScuttle_Service_Factory::get('Bookmark'); $rand = rand(); @@ -57,7 +63,7 @@ class TestBase extends PHPUnit_Framework_TestCase 'description', null, $status, - array('unittest'), + $tags, null, null, false, false, $user ); From 512e3a681179c99925121c4f192d8775011909bd Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:10:08 +0000 Subject: [PATCH 13/63] add bookmark2tagtest to alltests git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@664 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/AllTests.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/AllTests.php b/tests/AllTests.php index 23ad25e..d29de7f 100644 --- a/tests/AllTests.php +++ b/tests/AllTests.php @@ -56,6 +56,7 @@ class AllTests extends PHPUnit_Framework_TestSuite $suite = new AllTests(); $tdir = dirname(__FILE__); $suite->addTestFile($tdir . '/BookmarkTest.php'); + $suite->addTestFile($tdir . '/Bookmark2TagTest.php'); $suite->addTestFile($tdir . '/Tag2TagTest.php'); $suite->addTestFile($tdir . '/TagsCacheTest.php'); $suite->addTestFile($tdir . '/CommonDescriptionTest.php'); From 0685081d462c0c17fa11e06dd382ba082c2322fd Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:11:26 +0000 Subject: [PATCH 14/63] make tests better git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@665 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/Bookmark2TagTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Bookmark2TagTest.php b/tests/Bookmark2TagTest.php index 7d003c3..d75afd8 100644 --- a/tests/Bookmark2TagTest.php +++ b/tests/Bookmark2TagTest.php @@ -78,6 +78,8 @@ class Bookmark2TagTest extends TestBase */ public function testGetTagsForBookmarkNone() { + $this->addBookmark(null, null, 0, array('forz', 'barz')); + $bid = $this->addBookmark(null, null, 0, array()); $this->assertEquals( array(), @@ -94,6 +96,8 @@ class Bookmark2TagTest extends TestBase */ public function testGetTagsForBookmarkOne() { + $this->addBookmark(null, null, 0, array('forz', 'barz')); + $bid = $this->addBookmark(null, null, 0, array()); $this->b2ts->attachTags($bid, array('foo')); $this->assertEquals( @@ -111,6 +115,8 @@ class Bookmark2TagTest extends TestBase */ public function testGetTagsForBookmarkThree() { + $this->addBookmark(null, null, 0, array('forz', 'barz')); + $bid = $this->addBookmark(null, null, 0, array()); $this->b2ts->attachTags($bid, array('foo', 'bar', 'fuu')); From c4b8719b5b0b61d5fc4c7c4691f23d6635ef8f4d Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:12:51 +0000 Subject: [PATCH 15/63] reformat and CS git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@666 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark2Tag.php | 30 ++++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/SemanticScuttle/Service/Bookmark2Tag.php b/src/SemanticScuttle/Service/Bookmark2Tag.php index 8e5cb22..e0f831e 100644 --- a/src/SemanticScuttle/Service/Bookmark2Tag.php +++ b/src/SemanticScuttle/Service/Bookmark2Tag.php @@ -266,21 +266,39 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService return true; } - function &getTagsForBookmark($bookmarkid) { + + /** + * Retrieves all tags for a given bookmark except system tags. + * + * @param integer $bookmarkid ID of the bookmark + * + * @return array Array of tags + */ + public function getTagsForBookmark($bookmarkid) + { if (!is_numeric($bookmarkid)) { - message_die(GENERAL_ERROR, 'Could not get tags (invalid bookmarkid)', '', __LINE__, __FILE__, $query); + message_die( + GENERAL_ERROR, 'Could not get tags (invalid bookmarkid)', + '', __LINE__, __FILE__, $query + ); return false; } - $query = 'SELECT tag FROM '. $this->getTableName() .' WHERE bId = '. intval($bookmarkid) .' AND LEFT(tag, 7) <> "system:" ORDER BY id ASC'; + $query = 'SELECT tag FROM ' . $this->getTableName() + . ' WHERE bId = ' . intval($bookmarkid) + . ' AND LEFT(tag, 7) <> "system:"' + . ' ORDER BY id ASC'; - if (!($dbresult =& $this->db->sql_query($query))) { - message_die(GENERAL_ERROR, 'Could not get tags', '', __LINE__, __FILE__, $query, $this->db); + if (!($dbresult = $this->db->sql_query($query))) { + message_die( + GENERAL_ERROR, 'Could not get tags', + '', __LINE__, __FILE__, $query, $this->db + ); return false; } $tags = array(); - while ($row =& $this->db->sql_fetchrow($dbresult)) { + while ($row = $this->db->sql_fetchrow($dbresult)) { $tags[] = $row['tag']; } $this->db->sql_freeresult($dbresult); From 3e9c2cd0a57d798bb7cbcf89575cbc0199e0d2e5 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:14:39 +0000 Subject: [PATCH 16/63] add new method for better sql performance: Bookmark2Tag::getTagsForBookmarks() git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@667 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark2Tag.php | 48 +++++++++++++ tests/Bookmark2TagTest.php | 73 ++++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/src/SemanticScuttle/Service/Bookmark2Tag.php b/src/SemanticScuttle/Service/Bookmark2Tag.php index e0f831e..770b1d9 100644 --- a/src/SemanticScuttle/Service/Bookmark2Tag.php +++ b/src/SemanticScuttle/Service/Bookmark2Tag.php @@ -305,6 +305,54 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService return $tags; } + + /** + * Retrieves all tags for an array of bookmark IDs + * + * @param array $bookmarkids Array of bookmark IDs + * + * @return array Array of tag arrays. Key is bookmark ID. + */ + public function getTagsForBookmarks($bookmarkids) + { + if (!is_array($bookmarkids)) { + message_die( + GENERAL_ERROR, 'Could not get tags (invalid bookmarkids)', + '', __LINE__, __FILE__, $query + ); + return false; + } + + $sql = ''; + foreach ($bookmarkids as $bookmarkid) { + $sql .= ' OR bId = ' . intval($bookmarkid); + } + + $query = 'SELECT tag, bId FROM ' . $this->getTableName() + . ' WHERE (1' . $sql . ')' + . ' AND LEFT(tag, 7) <> "system:"' + . ' ORDER BY id, bId ASC'; + + if (!($dbresult = $this->db->sql_query($query))) { + message_die( + GENERAL_ERROR, 'Could not get tags', + '', __LINE__, __FILE__, $query, $this->db + ); + return false; + } + + $tags = array_combine( + $bookmarkids, + array_fill(0, count($bookmarkids), array()) + ); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $tags[$row['bId']][] = $row['tag']; + } + $this->db->sql_freeresult($dbresult); + return $tags; + } + + function &getTags($userid = NULL) { $userservice =SemanticScuttle_Service_Factory::get('User'); $logged_on_user = $userservice->getCurrentUserId(); diff --git a/tests/Bookmark2TagTest.php b/tests/Bookmark2TagTest.php index d75afd8..0afaaf8 100644 --- a/tests/Bookmark2TagTest.php +++ b/tests/Bookmark2TagTest.php @@ -126,6 +126,79 @@ class Bookmark2TagTest extends TestBase $this->assertContains('bar', $tags); $this->assertContains('fuu', $tags); } + + + + /** + * Test getTagsForBookmarks() when no bookmarks have tags. + * + * @return void + */ + public function testGetTagsForBookmarksNone() + { + $bid1 = $this->addBookmark(null, null, 0, array()); + $bid2 = $this->addBookmark(null, null, 0, array()); + + $alltags = $this->b2ts->getTagsForBookmarks( + array($bid1, $bid2) + ); + $this->assertType('array', $alltags); + $this->assertEquals(2, count($alltags)); + $this->assertType('array', $alltags[$bid1]); + $this->assertType('array', $alltags[$bid2]); + $this->assertEquals(0, count($alltags[$bid1])); + $this->assertEquals(0, count($alltags[$bid2])); + } + + + + /** + * Test getTagsForBookmarks() when most bookmarks have tags. + * + * @return void + */ + public function testGetTagsForBookmarksMost() + { + $bid1 = $this->addBookmark(null, null, 0, array()); + $this->b2ts->attachTags($bid1, array('foo', 'bar', 'fuu')); + + $bid2 = $this->addBookmark(null, null, 0, array()); + $this->b2ts->attachTags($bid2, array('foo', 'bar2', 'fuu2')); + + $bid3 = $this->addBookmark(null, null, 0, array()); + $this->b2ts->attachTags($bid3, array('foo', 'bar2', 'fuu3')); + + $bid4 = $this->addBookmark(null, null, 0, array()); + //no tags + + $alltags = $this->b2ts->getTagsForBookmarks( + array($bid1, $bid2, $bid3, $bid4) + ); + $this->assertType('array', $alltags); + foreach ($alltags as $bid => $btags) { + $this->assertType('array', $btags); + if ($bid == $bid1) { + $this->assertEquals(3, count($btags)); + $this->assertContains('foo', $btags); + $this->assertContains('bar', $btags); + $this->assertContains('fuu', $btags); + } else if ($bid == $bid2) { + $this->assertEquals(3, count($btags)); + $this->assertContains('foo', $btags); + $this->assertContains('bar2', $btags); + $this->assertContains('fuu2', $btags); + } else if ($bid == $bid3) { + $this->assertEquals(3, count($btags)); + $this->assertContains('foo', $btags); + $this->assertContains('bar2', $btags); + $this->assertContains('fuu3', $btags); + } else if ($bid == $bid4) { + $this->assertEquals(0, count($btags)); + } else { + $this->assertTrue(false, 'Unknown bookmark id'); + } + } + } } if (PHPUnit_MAIN_METHOD == 'Bookmark2TagTest::main') { From 6a6cba1a4d61d42bd93fb385f576d299bd99cc59 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:16:34 +0000 Subject: [PATCH 17/63] sql optimization: fetch all tags at once git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@668 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 15 +++++++++++---- src/SemanticScuttle/Service/Bookmark2Tag.php | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index c7bfb3b..9d72023 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -804,10 +804,17 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $total = $row['total']; $this->db->sql_freeresult($totalresult); - $bookmarks = array(); - while ($row = & $this->db->sql_fetchrow($dbresult)) { - $row['tags'] = $b2tservice->getTagsForBookmark(intval($row['bId'])); - $bookmarks[] = $row; + $bookmarks = array(); + $bookmarkids = array(); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $bookmarks[] = $row; + $bookmarkids[] = $row['bId']; + } + if (count($bookmarkids)) { + $tags = $b2tservice->getTagsForBookmarks($bookmarkids); + foreach ($bookmarks as &$bookmark) { + $bookmark['tags'] = $tags[$bookmark['bId']]; + } } $this->db->sql_freeresult($dbresult); diff --git a/src/SemanticScuttle/Service/Bookmark2Tag.php b/src/SemanticScuttle/Service/Bookmark2Tag.php index 770b1d9..d6c0e58 100644 --- a/src/SemanticScuttle/Service/Bookmark2Tag.php +++ b/src/SemanticScuttle/Service/Bookmark2Tag.php @@ -321,6 +321,8 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService '', __LINE__, __FILE__, $query ); return false; + } else if (count($bookmarkids) == 0) { + return array(); } $sql = ''; From 6c9542f24b630f60490949f4e77bcb0cf1bf7377 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:18:49 +0000 Subject: [PATCH 18/63] make isAdmin accept a user name, too git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@669 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/User.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/SemanticScuttle/Service/User.php b/src/SemanticScuttle/Service/User.php index cedde92..0b28663 100644 --- a/src/SemanticScuttle/Service/User.php +++ b/src/SemanticScuttle/Service/User.php @@ -305,9 +305,14 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService /** * Checks if the given user is an administrator. * Uses global admin_users property containing admin - * user names + * user names. * - * @param integer|array $user User ID or user row from DB + * Passing the user id makes this function load the user + * from database. For efficiency reasons, try to pass + * the user name or database row. + * + * @param integer|array|string $user User ID or user row from DB + * or user name * * @return boolean True if the user is admin */ @@ -315,10 +320,13 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService { if (is_numeric($user)) { $user = $this->getUser($user); + $user = $user['username']; + } else if (is_array($user)) { + $user = $user['username']; } if (isset($GLOBALS['admin_users']) - && in_array($user['username'], $GLOBALS['admin_users']) + && in_array($user, $GLOBALS['admin_users']) ) { return true; } else { From 40ca013e42ff64f5c88e31077e9e816cc3b7e581 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:20:32 +0000 Subject: [PATCH 19/63] sql optimization: 9 queries less! git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@670 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/templates/bookmarks.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/templates/bookmarks.tpl.php b/data/templates/bookmarks.tpl.php index b1a6eb0..8f502d3 100644 --- a/data/templates/bookmarks.tpl.php +++ b/data/templates/bookmarks.tpl.php @@ -307,7 +307,7 @@ if($currenttag!= '') { } // Admin specific design - if($userservice->isAdmin($row['uId'])) { + if ($userservice->isAdmin($row['username'])) { $adminBgClass = 'class="adminBackground"'; $adminStar = ' '; } else { From 01c792a78969dcfa3e9dd99a4491ccb6836ca8c1 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:23:07 +0000 Subject: [PATCH 20/63] new config option to disable "SET NAMES UTF8" sql call git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@671 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/config.default.php | 9 +++++++++ doc/ChangeLog | 7 +++++++ src/SemanticScuttle/Service/Factory.php | 6 ++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/data/config.default.php b/data/config.default.php index 1b040c0..fdbdaee 100644 --- a/data/config.default.php +++ b/data/config.default.php @@ -180,6 +180,15 @@ $dbname = 'scuttle'; */ $tableprefix = 'sc_'; +/* + * If the database needs to be switched to UTF8 + * manually or not. If true, a "SET NAMES UTF8" query + * will be sent at the beginning. If you need performance, + * save this query and set it in your mysql server options. + * + * @var boolean + */ +$dbneedssetnames = true; /*************************************************** diff --git a/doc/ChangeLog b/doc/ChangeLog index c797f56..05757ac 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,10 +1,17 @@ ChangeLog for SemantiScuttle ============================ +0.97.0 - 2010-????? +------------------- +- Many SQL optimizations +- New config option to skip "SET NAMES UTF8" call: $dbneedssetnames + + 0.96.1 - 2010-02-09 ------------------- - Fix bug #2948410: API is broken in 0.96.0 + 0.96.0 - 2010-02-08 ------------------- - Fix bug #2843523: ArtViper thumbnail license change diff --git a/src/SemanticScuttle/Service/Factory.php b/src/SemanticScuttle/Service/Factory.php index 9b79e6c..d7ff1d4 100644 --- a/src/SemanticScuttle/Service/Factory.php +++ b/src/SemanticScuttle/Service/Factory.php @@ -113,7 +113,7 @@ class SemanticScuttle_Service_Factory protected static function loadDb() { global $dbhost, $dbuser, $dbpass, $dbname, - $dbport, $dbpersist, $dbtype; + $dbport, $dbpersist, $dbtype, $dbneedssetnames; if (self::$db !== null) { return; @@ -130,7 +130,9 @@ class SemanticScuttle_Service_Factory self::$db ); } - $db->sql_query('SET NAMES UTF8'); + + $dbneedssetnames && $db->sql_query('SET NAMES UTF8'); + self::$db = $db; } From edfd04698a935f8c3a3441ae92a5cd9807705641 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:24:47 +0000 Subject: [PATCH 21/63] remove end date condition since it seems unneccessary to me git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@672 b3834d28-1941-0410-a4f8-b48e95affb8f --- www/index.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/www/index.php b/www/index.php index 0ba4afa..f6704ae 100644 --- a/www/index.php +++ b/www/index.php @@ -67,19 +67,16 @@ if (intval(GET_PAGE) > 1) { $start = 0; } -$dtend = date('Y-m-d H:i:s', strtotime('tomorrow')); -/*$dtstart = date('Y-m-d H:i:s', strtotime($dtend .' -'. $defaultRecentDays .' days'));*/ - -$tplVars['page'] = $page; -$tplVars['start'] = $start; +$tplVars['page'] = $page; +$tplVars['start'] = $start; $tplVars['popCount'] = 30; $tplVars['sidebar_blocks'] = $GLOBALS["index_sidebar_blocks"]; -$tplVars['range'] = 'all'; +$tplVars['range'] = 'all'; $tplVars['pagetitle'] = T_('Store, share and tag your favourite links'); -$tplVars['subtitle'] = T_('All Bookmarks'); +$tplVars['subtitle'] = T_('All Bookmarks'); $tplVars['bookmarkCount'] = $start + 1; -$bookmarks =& $bookmarkservice->getBookmarks($start, $perpage, NULL, NULL, NULL, getSortOrder(), NULL, 0, $dtend); +$bookmarks = $bookmarkservice->getBookmarks($start, $perpage, NULL, NULL, NULL, getSortOrder(), NULL, 0, NULL); $tplVars['total'] = $bookmarks['total']; $tplVars['bookmarks'] =& $bookmarks['bookmarks']; From ab75c7ff445bb8659293af3a39a355185221cb37 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:26:16 +0000 Subject: [PATCH 22/63] docblock git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@673 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/functions.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/SemanticScuttle/functions.php b/src/SemanticScuttle/functions.php index d21a094..15db022 100644 --- a/src/SemanticScuttle/functions.php +++ b/src/SemanticScuttle/functions.php @@ -35,10 +35,23 @@ function filter($data, $type = NULL) { return $data; } -function getPerPageCount($userObject = null) { +/** + * Returns the number of bookmarks that shall be displayed on one page. + * + * @param SemanticScuttle_Model_User $userObject Object of the current user + * + * @return integer Number of bookmarks per page + * + * @uses $defaultPerPage + * @uses $defaultPerPageForAdmins + */ +function getPerPageCount($userObject = null) +{ global $defaultPerPage, $defaultPerPageForAdmins; - if(isset($defaultPerPageForAdmins) && $userObject != null && $userObject->isAdmin()) { + if (isset($defaultPerPageForAdmins) + && $userObject != null && $userObject->isAdmin() + ) { return $defaultPerPageForAdmins; } else { return $defaultPerPage; From 74614e0f99221f1b137d9d9aedd3f38570430981 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:27:57 +0000 Subject: [PATCH 23/63] header docblock git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@674 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/functions.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/SemanticScuttle/functions.php b/src/SemanticScuttle/functions.php index 15db022..84e9c5f 100644 --- a/src/SemanticScuttle/functions.php +++ b/src/SemanticScuttle/functions.php @@ -1,6 +1,19 @@ + * @author Christian Weiske + * @author Eric Dane + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ // Converts tags: // - direction = out: convert spaces to underscores; @@ -48,7 +61,7 @@ function filter($data, $type = NULL) { function getPerPageCount($userObject = null) { global $defaultPerPage, $defaultPerPageForAdmins; - + if (isset($defaultPerPageForAdmins) && $userObject != null && $userObject->isAdmin() ) { From 35058ddd07266a70611b055b7e66c4cdd13d47e7 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:29:31 +0000 Subject: [PATCH 24/63] reformat _getuser and add docblock git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@675 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/User.php | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/SemanticScuttle/Service/User.php b/src/SemanticScuttle/Service/User.php index 0b28663..7b03dd2 100644 --- a/src/SemanticScuttle/Service/User.php +++ b/src/SemanticScuttle/Service/User.php @@ -76,15 +76,28 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService $this->updateSessionStability(); } - function _getuser($fieldname, $value) { - $query = 'SELECT * FROM '. $this->getTableName() .' WHERE '. $fieldname .' = "'. $this->db->sql_escape($value) .'"'; + /** + * Fetches the desired user row from database, specified by column and value + * + * @param string $fieldname Name of database column to identify user + * @param string $value Value of $fieldname + * + * @return array Database row or boolean false + */ + protected function _getuser($fieldname, $value) + { + $query = 'SELECT * FROM '. $this->getTableName() + . ' WHERE ' . $fieldname . ' = "' . $this->db->sql_escape($value) . '"'; - if (! ($dbresult =& $this->db->sql_query($query)) ) { - message_die(GENERAL_ERROR, 'Could not get user', '', __LINE__, __FILE__, $query, $this->db); + if (!($dbresult = $this->db->sql_query($query)) ) { + message_die( + GENERAL_ERROR, 'Could not get user', + '', __LINE__, __FILE__, $query, $this->db + ); return false; } - $row =& $this->db->sql_fetchrow($dbresult); + $row = $this->db->sql_fetchrow($dbresult); $this->db->sql_freeresult($dbresult); if ($row) { return $row; From 51e844e17e7adaa3a1d34cd85b29d3cbcd8eb8f3 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:31:18 +0000 Subject: [PATCH 25/63] save another query git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@676 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Model/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SemanticScuttle/Model/User.php b/src/SemanticScuttle/Model/User.php index 03af5c7..ed9f454 100644 --- a/src/SemanticScuttle/Model/User.php +++ b/src/SemanticScuttle/Model/User.php @@ -158,7 +158,7 @@ class SemanticScuttle_Model_User // Look for value only if not already set if(!isset($this->isAdmin)) { $us = SemanticScuttle_Service_Factory::get('User'); - $this->isAdmin = $us->isAdmin($this->id); + $this->isAdmin = $us->isAdmin($this->username); } return $this->isAdmin; } From 41a29f49ee4446b1e743356a837a96ca29118f78 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:33:11 +0000 Subject: [PATCH 26/63] save another query git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@677 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 9d72023..37a6a5e 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -284,7 +284,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService } $userservice = SemanticScuttle_Service_Factory::get('User'); - $user = $userservice->getCurrentUser(); + $user = $userservice->getCurrentObjectUser(); //user has to be either admin, or owner if ($GLOBALS['adminsCanModifyBookmarksFromOtherUsers'] @@ -292,7 +292,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService ) { return true; } else { - return ($bookmark['uId'] == $user['uId']); + return ($bookmark['uId'] == $user->id); } } From cae9f4de38376974b805dab6b7a95105dc61dfd9 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:35:16 +0000 Subject: [PATCH 27/63] fix tests after last commit git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@678 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 5 ++++- src/SemanticScuttle/Service/User.php | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 37a6a5e..87d9e02 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -285,10 +285,13 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $userservice = SemanticScuttle_Service_Factory::get('User'); $user = $userservice->getCurrentObjectUser(); + if ($user === null) { + return false; + } //user has to be either admin, or owner if ($GLOBALS['adminsCanModifyBookmarksFromOtherUsers'] - && $userservice->isAdmin($user) + && $userservice->isAdmin($user->id) ) { return true; } else { diff --git a/src/SemanticScuttle/Service/User.php b/src/SemanticScuttle/Service/User.php index 7b03dd2..281c18c 100644 --- a/src/SemanticScuttle/Service/User.php +++ b/src/SemanticScuttle/Service/User.php @@ -407,6 +407,7 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService } //reload user object $this->getCurrentUser(true); + $this->getCurrentObjectUser(true); } From 6a2f1f4f573613400479d427c32b083a7274158b Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:37:03 +0000 Subject: [PATCH 28/63] reformat query git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@679 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 87d9e02..10b0b8b 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -325,7 +325,9 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $crit['uId'] = $uid; } - $sql = 'SELECT COUNT(*) as "0" FROM '. $GLOBALS['tableprefix'] .'bookmarks WHERE '. $this->db->sql_build_array('SELECT', $crit); + $sql = 'SELECT COUNT(*) as "0" FROM ' + . $GLOBALS['tableprefix'] . 'bookmarks' + . ' WHERE '. $this->db->sql_build_array('SELECT', $crit); if (!($dbresult = $this->db->sql_query($sql))) { message_die( From 17374001b8ccfe806851862c91b29671ba998828 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:39:03 +0000 Subject: [PATCH 29/63] add SemanticScuttle_Service_Bookmark::bookmarksExist() method to check for existance of multiple bookmarks at once for future sql optimization git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@680 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 56 ++++++++++- tests/BookmarkTest.php | 122 +++++++++++++++++++++++ 2 files changed, 177 insertions(+), 1 deletion(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 10b0b8b..a1bb1a5 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -312,7 +312,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService * @return boolean True when the bookmark with the given URL * exists for the user, false if not. */ - function bookmarkExists($address = false, $uid = null) + public function bookmarkExists($address = false, $uid = null) { if (!$address) { return false; @@ -346,6 +346,60 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService + /** + * Checks if the given addresses exist + * + * @param array $addresses Array of addresses + * @param integer $uid User ID the addresses shall belong to + * + * @return array Array with addresses as keys, true/false for existence + * as value + */ + public function bookmarksExist($addresses, $uid = null) + { + if (count($addresses) == 0) { + return array(); + } + + $hashes = array(); + $sql = '(1'; + foreach ($addresses as $key => $address) { + $hash = md5($this->normalize($address)); + $hashes[$hash] = $address; + $sql .= ' OR bHash = "' + . $this->db->sql_escape($hash) + . '"'; + } + $sql .= ')'; + if ($uid !== null) { + $sql .= ' AND uId = ' . intval($uid); + } + + $sql = 'SELECT bHash, COUNT(*) as "count" FROM ' + . $this->getTableName() + . ' WHERE ' . $sql + . ' GROUP BY bHash'; + + if (!($dbresult = $this->db->sql_query($sql))) { + message_die( + GENERAL_ERROR, 'Could not get bookmark counts', '', + __LINE__, __FILE__, $sql, $this->db + ); + } + + $existence = array_combine( + $addresses, + array_fill(0, count($addresses), false) + ); + while ($row = $this->db->sql_fetchrow($dbresult)) { + $existence[$hashes[$row['bHash']]] = $row['count'] > 0; + } + + return $existence; + } + + + /** * Adds a bookmark to the database. * diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index 39a9974..74685c4 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -252,6 +252,128 @@ class BookmarkTest extends TestBase + /** + * Tests if bookmarksExist() returns true when a bookmark + * exists + * + * @return void + */ + public function testBookmarksExistTrueSingle() + { + $bid = $this->addBookmark(); + $bookmark = $this->bs->getBookmark($bid); + + $ret = $this->bs->bookmarksExist(array($bookmark['bAddress'])); + $this->assertType('array', $ret); + $this->assertEquals(1, count($ret)); + $this->assertTrue($ret[$bookmark['bAddress']]); + } + + + + /** + * Tests if bookmarksExist() returns true when all bookmarks + * exist + * + * @return void + */ + public function testBookmarksExistTrueMultiple() + { + $bid = $this->addBookmark(); + $bookmark = $this->bs->getBookmark($bid); + + $bid2 = $this->addBookmark(); + $bookmark2 = $this->bs->getBookmark($bid2); + + + $ret = $this->bs->bookmarksExist( + array( + $bookmark['bAddress'], + $bookmark2['bAddress'] + ) + ); + $this->assertType('array', $ret); + $this->assertEquals(2, count($ret)); + $this->assertTrue($ret[$bookmark['bAddress']]); + $this->assertTrue($ret[$bookmark2['bAddress']]); + } + + + + /** + * Tests if bookmarksExist() returns false when a bookmark + * does not exist + * + * @return void + */ + public function testBookmarksExistFalseSingle() + { + $ret = $this->bs->bookmarksExist(array('does-not-exist')); + $this->assertType('array', $ret); + $this->assertEquals(1, count($ret)); + $this->assertFalse($ret['does-not-exist']); + } + + + + /** + * Tests if bookmarksExist() returns false when all bookmarks + * do not exist + * + * @return void + */ + public function testBookmarksExistFalseMultiple() + { + $bms = array( + 'does-not-exist', + 'does-not-exist-2', + 'does-not-exist-3', + ); + $ret = $this->bs->bookmarksExist($bms); + $this->assertType('array', $ret); + $this->assertEquals(3, count($ret)); + $this->assertFalse($ret['does-not-exist']); + $this->assertFalse($ret['does-not-exist-2']); + $this->assertFalse($ret['does-not-exist-3']); + } + + + + /** + * Tests if bookmarksExist() returns true when some bookmarks + * exist. + * + * @return void + */ + public function testBookmarksExistSome() + { + $bid = $this->addBookmark(); + $bookmark = $this->bs->getBookmark($bid); + + $bid2 = $this->addBookmark(); + $bookmark2 = $this->bs->getBookmark($bid2); + + + $ret = $this->bs->bookmarksExist( + array( + $bookmark['bAddress'], + 'does-not-exist', + $bookmark2['bAddress'], + 'does-not-exist-2', + 'does-not-exist-3' + ) + ); + $this->assertType('array', $ret); + $this->assertEquals(5, count($ret)); + $this->assertTrue($ret[$bookmark['bAddress']]); + $this->assertTrue($ret[$bookmark2['bAddress']]); + $this->assertFalse($ret['does-not-exist']); + $this->assertFalse($ret['does-not-exist-2']); + $this->assertFalse($ret['does-not-exist-3']); + } + + + /** * Test if countBookmarks() works with no bookmarks * From 53f0a57de09b8a2b0155042eaa433afd06ac682e Mon Sep 17 00:00:00 2001 From: cweiske Date: Sat, 20 Feb 2010 11:41:01 +0000 Subject: [PATCH 30/63] sql optimization: reduce by 9 sql queries when logged in and looking at bookmarks git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@681 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/templates/bookmarks.tpl.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/data/templates/bookmarks.tpl.php b/data/templates/bookmarks.tpl.php index 8f502d3..ad2ecd3 100644 --- a/data/templates/bookmarks.tpl.php +++ b/data/templates/bookmarks.tpl.php @@ -222,6 +222,11 @@ if($currenttag!= '') { $addresses[$row['bId']] = $row['bAddress']; } $otherCounts = $bookmarkservice->countOthers($addresses); + if ($userservice->isLoggedOn()) { + $existence = $bookmarkservice->bookmarksExist( + $addresses, $currentUser->getId() + ); + } foreach ($bookmarks as $key => &$row) { switch ($row['bStatus']) { @@ -284,7 +289,7 @@ if($currenttag!= '') { // Copy link if ($userservice->isLoggedOn() && ($currentUser->getId() != $row['uId']) - && !$bookmarkservice->bookmarkExists($row['bAddress'], $currentUser->getId()) + && !$existence[$row['bAddress']] ) { $copy .= ' - '; } else { diff --git a/doc/ChangeLog b/doc/ChangeLog index 05757ac..65ed2e2 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -5,6 +5,7 @@ ChangeLog for SemantiScuttle ------------------- - Many SQL optimizations - New config option to skip "SET NAMES UTF8" call: $dbneedssetnames +- Do not highlight admin bookmarks when $enableAdminColors is disabled 0.96.1 - 2010-02-09 From 46c13c46f2c742d75f959845fa6f1b139aa7ff3c Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 17 Mar 2010 20:03:49 +0000 Subject: [PATCH 34/63] remove unneeded ampersand git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@685 b3834d28-1941-0410-a4f8-b48e95affb8f --- www/bookmarks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/bookmarks.php b/www/bookmarks.php index e356750..0c9bfa4 100644 --- a/www/bookmarks.php +++ b/www/bookmarks.php @@ -134,7 +134,7 @@ if ($userservice->isLoggedOn() && POST_SUBMITTED != '') { $address = trim(POST_ADDRESS); // If the bookmark exists already, edit the original if ($bookmarkservice->bookmarkExists($address, $currentUserID)) { - $bookmark =& $bookmarkservice->getBookmarkByAddress($address); + $bookmark = $bookmarkservice->getBookmarkByAddress($address); header('Location: '. createURL('edit', $bookmark['bId'])); exit(); // If it's new, save it From e0dff57cbb4d2093ef58b3da7654d1305beb043f Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 17 Mar 2010 20:04:47 +0000 Subject: [PATCH 35/63] remove part of broken merge :/ git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@686 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/BookmarkTest.php | 165 ----------------------------------------- 1 file changed, 165 deletions(-) diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index 0b4f01d..74685c4 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -1179,171 +1179,6 @@ class BookmarkTest extends TestBase - - - /** - * Test what countOther() returns when the address does not exist - * - * @return void - */ - public function testCountOthersAddressDoesNotExist() - { - $this->assertEquals(0, $this->bs->countOthers('http://example.org')); - } - - - - /** - * Test what countOther() returns when nobody else has the same bookmark - * - * @return void - */ - public function testCountOthersNone() - { - $uid = $this->addUser(); - $address = 'http://example.org'; - $this->addBookmark($uid, $address); - $this->assertEquals(0, $this->bs->countOthers($address)); - } - - - - /** - * Test what countOther() returns when the address exists only once - * and multiple bookmarks are in the database. - * - * @return void - */ - public function testCountOthersMultipleNone() - { - $uid = $this->addUser(); - $address = 'http://example.org'; - $this->addBookmark($uid, $address); - $this->addBookmark($uid); - $this->addBookmark($uid); - $this->assertEquals(0, $this->bs->countOthers($address)); - } - - - - /** - * Test what countOther() returns when the address exists only once - * and the same user and other users have other bookmarks - * - * @return void - */ - public function testCountOthersMultipleUsersNone() - { - $uid = $this->addUser(); - $uid2 = $this->addUser(); - $address = 'http://example.org'; - $this->addBookmark($uid, $address); - $this->addBookmark($uid); - $this->addBookmark($uid2); - $this->assertEquals(0, $this->bs->countOthers($address)); - } - - - - /** - * Test what countOther() returns when the address exists two - * times in the database. - * - * @return void - */ - public function testCountOthersOne() - { - $uid = $this->addUser(); - $uid2 = $this->addUser(); - $address = 'http://example.org'; - $this->addBookmark($uid, $address); - $this->addBookmark($uid2, $address); - $this->assertEquals(1, $this->bs->countOthers($address)); - } - - - - /** - * Test what countOther() returns when the address exists four - * times in the database. - * - * @return void - */ - public function testCountOthersThree() - { - $uid = $this->addUser(); - $address = 'http://example.org'; - $this->addBookmark($uid, $address); - $this->addBookmark(null, $address); - $this->addBookmark(null, $address); - $this->addBookmark(null, $address); - $this->assertEquals(3, $this->bs->countOthers($address)); - } - - - - /** - * Test what countOther() returns when the user is logged in - * and friends (people on the watchlist) have bookmarked - * and shared the same address. - * - * @return void - */ - public function testCountOthersWatchlist() - { - $uid = $this->addUser(); - $address = 'http://example.org'; - //log user in - $this->us->setCurrentUserId($uid); - - //setup users - $otherPublic1 = $this->addUser(); - $otherPublic2 = $this->addUser(); - $otherShared1 = $this->addUser(); - $otherPrivate1 = $this->addUser(); - $friendPublic1 = $this->addUser(); - $friendShared1 = $this->addUser(); - $friendShared2 = $this->addUser(); - $friendPrivate1 = $this->addUser(); - $friendSharing1 = $this->addUser(); - - //setup watchlists - $us = SemanticScuttle_Service_Factory::get('User'); - $this->us->setCurrentUserId($friendPublic1); - $us->setWatchStatus($uid); - $this->us->setCurrentUserId($friendShared1); - $us->setWatchStatus($uid); - $this->us->setCurrentUserId($friendShared2); - $us->setWatchStatus($uid); - $this->us->setCurrentUserId($friendPrivate1); - $us->setWatchStatus($uid); - - //back to login of main user - $this->us->setCurrentUserId($uid); - $us->setWatchStatus($friendSharing1); - - //add bookmarks - $this->addBookmark($uid, $address, 0); - $this->addBookmark($otherPublic1, $address, 0); - $this->addBookmark($otherPublic2, $address, 0); - $this->addBookmark($otherShared1, $address, 1); - $this->addBookmark($otherPrivate1, $address, 2); - $this->addBookmark($friendPublic1, $address, 0); - $this->addBookmark($friendShared1, $address, 1); - $this->addBookmark($friendShared2, $address, 1); - $this->addBookmark($friendPrivate1, $address, 2); - //this user is on our watchlist, but we not on his - $this->addBookmark($friendSharing1, $address, 1); - - //2 public - //1 public (friend) - //2 shared - //-> 5 - $this->assertEquals(5, $this->bs->countOthers($address)); - } - - - } From f9e0714350cbb8efdfeac632fe2211c6c59bdbae Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 17 Mar 2010 20:05:43 +0000 Subject: [PATCH 36/63] write failing test for bug #2953732 git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@687 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/BookmarkTest.php | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index 74685c4..7885876 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -859,6 +859,50 @@ class BookmarkTest extends TestBase + /** + * Tests if getBookmarkByAddress() works correctly. + * + * @return void + */ + public function testGetBookmarkByAddress() + { + $url = 'http://example.org'; + $uid = $this->addUser(); + $bid = $this->addBookmark($uid, $url); + + $bm = $this->bs->getBookmarkByAddress($url); + $this->assertType('array', $bm); + $this->assertEquals($url, $bm['bAddress']); + } + + + + /** + * Tests if getBookmarkByAddress() works correctly with aliases. + * When passing an incomplete address i.e. without protocol, + * the full URL needs to be searched for. + * + * The failure of this test lead to #2953732. + * + * @return void + * + * @link https://sourceforge.net/tracker/?func=detail&atid=1017430&aid=2953732&group_id=211356 + */ + public function testGetBookmarkByAddressAlias() + { + $url = 'http://example.org'; + $incomplete = 'example.org'; + + $uid = $this->addUser(); + $bid = $this->addBookmark($uid, $url); + + $bm = $this->bs->getBookmarkByAddress($incomplete); + $this->assertType('array', $bm); + $this->assertEquals($url, $bm['bAddress']); + } + + + public function testNormalize() { $this->assertEquals( From 5a93096431eebb4cb458351ce5f8d1b836328ca0 Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 17 Mar 2010 20:07:04 +0000 Subject: [PATCH 37/63] fix bug #2953732 and make corresponding test work. git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@688 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 88a9055..3cdec72 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -178,7 +178,8 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService */ public function getBookmarkByAddress($address) { - $hash = md5($address); + $address = $this->normalize($address); + $hash = md5($address); return $this->getBookmarkByHash($hash); } From db7a46b23530724cf1a8d356de3ac4f1fe0d5ac7 Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 17 Mar 2010 20:08:20 +0000 Subject: [PATCH 38/63] note fixing of bug #2953732 in the changelog git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@689 b3834d28-1941-0410-a4f8-b48e95affb8f --- doc/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 65ed2e2..d9cdb6e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -6,6 +6,7 @@ ChangeLog for SemantiScuttle - Many SQL optimizations - New config option to skip "SET NAMES UTF8" call: $dbneedssetnames - Do not highlight admin bookmarks when $enableAdminColors is disabled +- Fix bug #2953732: faulty error message for duplicate bookmarks 0.96.1 - 2010-02-09 From 4d3d00ade282e27b765a64c86f6607f1a92af2c0 Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 17 Mar 2010 20:11:21 +0000 Subject: [PATCH 39/63] Fix bug #2960663: do not send content-type headers twice for ajax/api scripts git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@690 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/header.php | 8 +++++++- www/ajax/getadminlinkedtags.php | 2 +- www/ajax/getadmintags.php | 2 +- www/ajax/getcontacttags.php | 2 +- www/ajax/getlinkedtags.php | 2 +- www/ajax/gettags.php | 2 +- www/ajaxDelete.php | 2 +- www/ajaxGetTitle.php | 2 +- www/ajaxIsAvailable.php | 2 +- www/ajaxVote.php | 2 +- www/api/export_csv.php | 8 +++----- www/api/export_gcs.php | 5 +++-- www/api/export_sioc.php | 2 +- www/api/opensearch.php | 2 +- www/api/posts_add.php | 5 ++--- www/api/posts_all.php | 5 ++--- www/api/posts_dates.php | 2 +- www/api/posts_delete.php | 5 ++--- www/api/posts_get.php | 2 +- www/api/posts_public.php | 2 +- www/api/posts_recent.php | 2 +- www/api/posts_update.php | 5 ++--- www/api/tags_get.php | 5 ++--- www/api/tags_rename.php | 5 ++--- www/go.php | 1 + www/jsScuttle.php | 2 +- www/rss.php | 3 +-- 27 files changed, 43 insertions(+), 44 deletions(-) diff --git a/src/SemanticScuttle/header.php b/src/SemanticScuttle/header.php index 12c1f72..ef36e83 100644 --- a/src/SemanticScuttle/header.php +++ b/src/SemanticScuttle/header.php @@ -107,6 +107,12 @@ $tplVars['userservice'] = $userservice; // 6 // Force UTF-8 behaviour for server (cannot be moved into top.inc.php which is not included into every file) if (!defined('UNIT_TEST_MODE')) { - header('Content-Type: text/html; charset=utf-8'); + //API files define that, so we need a way to support both of them + if (!isset($httpContentType)) { + $httpContentType = 'text/html'; + } + if ($httpContentType !== false) { + header('Content-Type: ' . $httpContentType . '; charset=utf-8'); + } } ?> diff --git a/www/ajax/getadminlinkedtags.php b/www/ajax/getadminlinkedtags.php index 6abc067..6646c50 100644 --- a/www/ajax/getadminlinkedtags.php +++ b/www/ajax/getadminlinkedtags.php @@ -20,7 +20,7 @@ ***************************************************************************/ /* Return a json file with list of linked tags */ - +$httpContentType = 'application/json'; require_once '../www-header.php'; /* Service creation: only useful services are created */ diff --git a/www/ajax/getadmintags.php b/www/ajax/getadmintags.php index db62fc7..ffd20bb 100644 --- a/www/ajax/getadmintags.php +++ b/www/ajax/getadmintags.php @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ /* Return a json file with list of tags according to current user and sort by popularity*/ - +$httpContentType = 'application/json'; require_once '../www-header.php'; /* Service creation: only useful services are created */ diff --git a/www/ajax/getcontacttags.php b/www/ajax/getcontacttags.php index 85ef1ae..89d6a3a 100644 --- a/www/ajax/getcontacttags.php +++ b/www/ajax/getcontacttags.php @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ /* Return a json file with list of tags according to current user and sort by popularity*/ - +$httpContentType = 'application/json'; require_once '../www-header.php'; /* Service creation: only useful services are created */ diff --git a/www/ajax/getlinkedtags.php b/www/ajax/getlinkedtags.php index 6de272b..f412998 100644 --- a/www/ajax/getlinkedtags.php +++ b/www/ajax/getlinkedtags.php @@ -20,7 +20,7 @@ ***************************************************************************/ /* Return a json file with list of linked tags */ - +$httpContentType = 'application/json'; require_once '../www-header.php'; /* Service creation: only useful services are created */ diff --git a/www/ajax/gettags.php b/www/ajax/gettags.php index 3672832..cb73720 100644 --- a/www/ajax/gettags.php +++ b/www/ajax/gettags.php @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ /* Return a json file with list of tags according to current user and sort by popularity*/ - +$httpContentType = 'application/json'; require_once '../www-header.php'; /* Service creation: only useful services are created */ diff --git a/www/ajaxDelete.php b/www/ajaxDelete.php index 467e20e..2812612 100644 --- a/www/ajaxDelete.php +++ b/www/ajaxDelete.php @@ -19,9 +19,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ -header('Content-Type: text/xml; charset=UTF-8'); header('Last-Modified: '. gmdate("D, d M Y H:i:s") .' GMT'); header('Cache-Control: no-cache, must-revalidate'); +$httpContentType = 'text/xml'; require_once 'www-header.php'; /* Service creation: only useful services are created */ diff --git a/www/ajaxGetTitle.php b/www/ajaxGetTitle.php index 6caa742..b4f44ca 100644 --- a/www/ajaxGetTitle.php +++ b/www/ajaxGetTitle.php @@ -19,10 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ -header('Content-Type: text/xml; charset=UTF-8'); header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT"); header("Cache-Control: no-cache, must-revalidate"); +$httpContentType = 'text/xml'; require_once 'www-header.php'; /* Managing all possible inputs */ diff --git a/www/ajaxIsAvailable.php b/www/ajaxIsAvailable.php index 3390569..41e825e 100644 --- a/www/ajaxIsAvailable.php +++ b/www/ajaxIsAvailable.php @@ -19,10 +19,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ -header('Content-Type: text/xml; charset=UTF-8'); header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT"); header("Cache-Control: no-cache, must-revalidate"); +$httpContentType = 'text/xml'; require_once 'www-header.php'; /* Service creation: only useful services are created */ diff --git a/www/ajaxVote.php b/www/ajaxVote.php index 3e603da..f2572fb 100644 --- a/www/ajaxVote.php +++ b/www/ajaxVote.php @@ -2,6 +2,7 @@ /** * We re-use vote.php but set the ajax flag */ +$httpContentType = 'text/xml'; $GLOBALS['ajaxRequest'] = true; require 'vote.php'; @@ -17,7 +18,6 @@ default: $template = 'bookmarks-vote.inc.tpl.php'; } -header('Content-Type: text/xml; charset=utf-8'); echo '' . $bookmark . '' . ''; $ts->loadTemplate( diff --git a/www/api/export_csv.php b/www/api/export_csv.php index 3f63692..b9cf497 100644 --- a/www/api/export_csv.php +++ b/www/api/export_csv.php @@ -2,8 +2,9 @@ // Export in CSV format in order to allow the import into a spreadsheet tool like Excel // Force HTTP authentication first! -require_once('httpauth.inc.php'); -require_once '../www-header.php'; +$httpContentType = 'application/csv-tab-delimited-table'; +require_once 'httpauth.inc.php'; +header("Content-disposition: filename=exportBookmarks.csv"); /* Service creation: only useful services are created */ $bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark'); @@ -17,9 +18,6 @@ else // Get the posts relevant to the passed-in variables. $bookmarks =& $bookmarkservice->getBookmarks(0, NULL, $userservice->getCurrentUserId(), $tag, NULL, getSortOrder()); -header("Content-Type: application/csv-tab-delimited-table;charset=UTF-8"); -header("Content-disposition: filename=exportBookmarks.csv"); - //columns titles echo 'url;title;tags;description'; echo "\n"; diff --git a/www/api/export_gcs.php b/www/api/export_gcs.php index 07bc726..9c0d85c 100644 --- a/www/api/export_gcs.php +++ b/www/api/export_gcs.php @@ -5,6 +5,7 @@ // Force HTTP authentication first! //require_once('httpauth.inc.php'); +$httpContentType = false; require_once '../www-header.php'; if($GLOBALS['enableGoogleCustomSearch'] == false) { @@ -39,7 +40,7 @@ $bookmarks =& $bookmarkservice->getBookmarks(0, NULL, NULL, $tag, NULL, getSortO // Set up the plain file and output all the posts. -header('Content-Type: text/plain'); +header('Content-Type: text/plain; charset=utf-8'); if(!$xml) { header('Content-Type: text/plain'); foreach($bookmarks['bookmarks'] as $row) { @@ -48,7 +49,7 @@ if(!$xml) { } } } else { - header('Content-Type: application/xml'); + header('Content-Type: text/xml'); echo ''."\n"; echo ' '."\n"; foreach($bookmarks['bookmarks'] as $row) { diff --git a/www/api/export_sioc.php b/www/api/export_sioc.php index ff1d1c0..8bdfd70 100644 --- a/www/api/export_sioc.php +++ b/www/api/export_sioc.php @@ -1,8 +1,8 @@ diff --git a/www/api/posts_add.php b/www/api/posts_add.php index c919ee7..59f7dce 100644 --- a/www/api/posts_add.php +++ b/www/api/posts_add.php @@ -11,8 +11,8 @@ // - No support for 'replace' variable // Force HTTP authentication -require_once('httpauth.inc.php'); -require_once '../www-header.php'; +$httpContentType = 'text/xml'; +require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ $bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark'); @@ -82,7 +82,6 @@ if (is_null($url) || is_null($description)) { } // Set up the XML file and output the result. -header('Content-Type: text/xml'); echo '\r\n"; echo ''; ?> \ No newline at end of file diff --git a/www/api/posts_all.php b/www/api/posts_all.php index f53f363..2d274f4 100644 --- a/www/api/posts_all.php +++ b/www/api/posts_all.php @@ -5,8 +5,8 @@ // - doesn't include the filtered tag as an attribute on the root element (we do) // Force HTTP authentication first! -require_once('httpauth.inc.php'); -require_once '../www-header.php'; +$httpContentType = 'text/xml'; +require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ $bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark'); @@ -22,7 +22,6 @@ else $bookmarks =& $bookmarkservice->getBookmarks(0, NULL, $userservice->getCurrentUserId(), $tag); // Set up the XML file and output all the posts. -header('Content-Type: text/xml'); echo '\r\n"; echo '\r\n"; diff --git a/www/api/posts_dates.php b/www/api/posts_dates.php index 7b1240f..508c46a 100644 --- a/www/api/posts_dates.php +++ b/www/api/posts_dates.php @@ -17,6 +17,7 @@ */ // Force HTTP authentication first! +$httpContentType = 'text/xml'; require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ @@ -36,7 +37,6 @@ $bookmarks = $bookmarkservice->getBookmarks( ); // Set up the XML file and output all the tags. -header('Content-Type: text/xml'); echo '\r\n"; echo '\r\n"; diff --git a/www/api/posts_delete.php b/www/api/posts_delete.php index 88e2584..a63cc62 100644 --- a/www/api/posts_delete.php +++ b/www/api/posts_delete.php @@ -7,8 +7,8 @@ // - doesn't set the Content-Type to text/xml (we do). // Force HTTP authentication first! -require_once('httpauth.inc.php'); -require_once '../www-header.php'; +$httpContentType = 'text/xml'; +require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ $bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark'); @@ -28,7 +28,6 @@ if (is_null($_REQUEST['url'])) { } // Set up the XML file and output the result. -header('Content-Type: text/xml'); echo '\r\n"; echo ''; ?> \ No newline at end of file diff --git a/www/api/posts_get.php b/www/api/posts_get.php index b020f51..c20f904 100644 --- a/www/api/posts_get.php +++ b/www/api/posts_get.php @@ -25,6 +25,7 @@ */ // Force HTTP authentication first! +$httpContentType = 'text/xml'; require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ @@ -54,7 +55,6 @@ $bookmarks = $bookmarkservice->getBookmarks( // Set up the XML file and output all the tags. -header('Content-Type: text/xml'); echo '\r\n"; echo '\r\n"; diff --git a/www/api/posts_public.php b/www/api/posts_public.php index 0c93ca2..4258550 100644 --- a/www/api/posts_public.php +++ b/www/api/posts_public.php @@ -6,6 +6,7 @@ // Force HTTP authentication first! //require_once('httpauth.inc.php'); +$httpContentType = 'text/xml'; require_once '../www-header.php'; /* Service creation: only useful services are created */ @@ -22,7 +23,6 @@ else $bookmarks =& $bookmarkservice->getBookmarks(0, NULL, NULL, $tag); // Set up the XML file and output all the posts. -header('Content-Type: text/xml'); echo '\r\n"; echo '\r\n"; diff --git a/www/api/posts_recent.php b/www/api/posts_recent.php index 46e46f1..6c71e22 100644 --- a/www/api/posts_recent.php +++ b/www/api/posts_recent.php @@ -22,6 +22,7 @@ $countDefault = 15; $countMax = 100; // Force HTTP authentication first! +$httpContentType = 'text/xml'; require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ @@ -54,7 +55,6 @@ $bookmarks = $bookmarkservice->getBookmarks( // Set up the XML file and output all the tags. -header('Content-Type: text/xml'); echo '\r\n"; echo '\r\n"; diff --git a/www/api/posts_update.php b/www/api/posts_update.php index 9152f26..4aeedc3 100644 --- a/www/api/posts_update.php +++ b/www/api/posts_update.php @@ -5,8 +5,8 @@ // - doesn't set the Content-Type to text/xml (we do). // Force HTTP authentication first! -require_once('httpauth.inc.php'); -require_once '../www-header.php'; +$httpContentType = 'text/xml'; +require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ $bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark'); @@ -17,7 +17,6 @@ $bookmarks =& $bookmarkservice->getBookmarks(0, 1, $userservice->getCurrentUserI // Set up the XML file and output all the tags. -header('Content-Type: text/xml'); echo '\r\n"; foreach($bookmarks['bookmarks'] as $row) { echo ''; diff --git a/www/api/tags_get.php b/www/api/tags_get.php index 85684d4..06a40d9 100644 --- a/www/api/tags_get.php +++ b/www/api/tags_get.php @@ -5,8 +5,8 @@ // - tags can't have spaces // Force HTTP authentication first! -require_once('httpauth.inc.php'); -require_once '../www-header.php'; +$httpContentType = 'text/xml'; +require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ $b2tservice =SemanticScuttle_Service_Factory::get('Bookmark2Tag'); @@ -16,7 +16,6 @@ $b2tservice =SemanticScuttle_Service_Factory::get('Bookmark2Tag'); $tags =& $b2tservice->getTags($userservice->getCurrentUserId()); // Set up the XML file and output all the tags. -header('Content-Type: text/xml'); echo '\r\n"; echo "\r\n"; foreach($tags as $row) { diff --git a/www/api/tags_rename.php b/www/api/tags_rename.php index 59ba8a4..cf56c83 100644 --- a/www/api/tags_rename.php +++ b/www/api/tags_rename.php @@ -5,8 +5,8 @@ // - oddly, returns an entirely different result () than the other API calls. // Force HTTP authentication first! -require_once('httpauth.inc.php'); -require_once '../www-header.php'; +$httpContentType = 'text/xml'; +require_once 'httpauth.inc.php'; /* Service creation: only useful services are created */ $b2tservice =SemanticScuttle_Service_Factory::get('Bookmark2Tag'); @@ -31,7 +31,6 @@ if (is_null($old) || is_null($new)) { } // Set up the XML file and output the result. -header('Content-Type: text/xml'); echo '\r\n"; echo ''. ($renamed ? 'done' : 'something went wrong') .''; ?> diff --git a/www/go.php b/www/go.php index 3d271c4..6a36ba9 100644 --- a/www/go.php +++ b/www/go.php @@ -15,6 +15,7 @@ * @license GPL http://www.gnu.org/licenses/gpl.html * @link http://sourceforge.net/projects/semanticscuttle */ +$httpContentType = false; require_once 'www-header.php'; if (!$GLOBALS['shorturl']) { diff --git a/www/jsScuttle.php b/www/jsScuttle.php index cc4e16d..f37da78 100644 --- a/www/jsScuttle.php +++ b/www/jsScuttle.php @@ -1,6 +1,6 @@ 1) { list($url, $user, $cat) = explode('/', $_SERVER['PATH_INFO']); } else { From 8c213f0e6e97351a64168aab18d69324a90e7b83 Mon Sep 17 00:00:00 2001 From: cweiske Date: Thu, 18 Mar 2010 19:22:26 +0000 Subject: [PATCH 40/63] fix typo git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@691 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/LAUNCH_TESTS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/LAUNCH_TESTS b/tests/LAUNCH_TESTS index 7d6ddc0..7ee9227 100644 --- a/tests/LAUNCH_TESTS +++ b/tests/LAUNCH_TESTS @@ -12,7 +12,7 @@ Warning The unit tests are DESTRUCTIBLE! Never ever run them on your normal SemanticScuttle database! Always use a different database for testing - whole tables are emptied and re-filled during the -tests, and you will definitely loose all data in there. +tests, and you will definitely lose all data in there. Running the tests From 602ec95bbb91400b6ef2647df55e83e68f4223b5 Mon Sep 17 00:00:00 2001 From: cweiske Date: Thu, 18 Mar 2010 19:24:21 +0000 Subject: [PATCH 41/63] unify hashing code in a separate method git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@692 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 65 +++++++++++++++--------- www/bookmarks.php | 2 +- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 3cdec72..2258625 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -178,9 +178,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService */ public function getBookmarkByAddress($address) { - $address = $this->normalize($address); - $hash = md5($address); - return $this->getBookmarkByHash($hash); + return $this->getBookmarkByHash($this->getHash($address)); } @@ -189,10 +187,12 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService * Retrieves a bookmark with the given hash. * DOES NOT RESPECT PRIVACY SETTINGS! * - * @param string $hash URL hash (MD5) + * @param string $hash URL hash * * @return mixed Array with bookmark data or false in case * of an error (i.e. not found). + * + * @see getHash() */ public function getBookmarkByHash($hash) { @@ -201,6 +201,25 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService + /** + * Returns the hash value of a given address. + * + * @param string $address URL to hash + * @param boolean $bNormalize If the address shall be normalized before + * being hashed + * + * @return string Hash value + */ + public function getHash($address, $bNormalize = true) + { + if ($bNormalize) { + $address = $this->normalize($address); + } + return md5($address); + } + + + /** * Retrieves a bookmark that has a given short * name. @@ -319,9 +338,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService return false; } - $address = $this->normalize($address); - - $crit = array('bHash' => md5($address)); + $crit = array('bHash' => $this->getHash($address)); if (isset ($uid)) { $crit['uId'] = $uid; } @@ -365,7 +382,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $hashes = array(); $sql = '(1'; foreach ($addresses as $key => $address) { - $hash = md5($this->normalize($address)); + $hash = $this->getHash($address); $hashes[$hash] = $address; $sql .= ' OR bHash = "' . $this->db->sql_escape($hash) @@ -462,17 +479,17 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService // Set up the SQL insert statement and execute it. $values = array( - 'uId' => intval($sId), - 'bIp' => $ip, - 'bDatetime' => $datetime, - 'bModified' => $datetime, - 'bTitle' => $title, - 'bAddress' => $address, + 'uId' => intval($sId), + 'bIp' => $ip, + 'bDatetime' => $datetime, + 'bModified' => $datetime, + 'bTitle' => $title, + 'bAddress' => $address, 'bDescription' => $description, 'bPrivateNote' => $privateNote, - 'bStatus' => intval($status), - 'bHash' => md5($address), - 'bShort' => $short + 'bStatus' => intval($status), + 'bHash' => $this->getHash($address), + 'bShort' => $short ); $sql = 'INSERT INTO '. $this->getTableName() @@ -582,14 +599,14 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService // Set up the SQL update statement and execute it. $updates = array( - 'bModified' => $moddatetime, - 'bTitle' => $title, - 'bAddress' => $address, + 'bModified' => $moddatetime, + 'bTitle' => $title, + 'bAddress' => $address, 'bDescription' => $description, 'bPrivateNote' => $privateNote, - 'bStatus' => $status, - 'bHash' => md5($address), - 'bShort' => $short + 'bStatus' => $status, + 'bHash' => $this->getHash($address, false), + 'bShort' => $short ); if (!is_null($date)) { @@ -1004,7 +1021,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService $addressesSql = ' AND (0'; foreach ((array)$addresses as $address) { $addressesSql .= ' OR B.bHash = "' - . $this->db->sql_escape(md5($address)) + . $this->db->sql_escape($this->getHash($address)) . '"'; } $addressesSql .= ')'; diff --git a/www/bookmarks.php b/www/bookmarks.php index 0c9bfa4..5241481 100644 --- a/www/bookmarks.php +++ b/www/bookmarks.php @@ -167,7 +167,7 @@ if ($userservice->isLoggedOn() && POST_SUBMITTED != '') { if (GET_ACTION == "add") { // If the bookmark exists already, edit the original if ($bookmarkservice->bookmarkExists(stripslashes(GET_ADDRESS), $currentUserID)) { - $bookmark =& $bookmarkservice->getBookmarks(0, NULL, $currentUserID, NULL, NULL, NULL, NULL, NULL, NULL, md5($bookmarkservice->normalize(stripslashes(GET_ADDRESS)))); + $bookmark =& $bookmarkservice->getBookmarks(0, NULL, $currentUserID, NULL, NULL, NULL, NULL, NULL, NULL, $bookmarkservice->getHash(stripslashes(GET_ADDRESS))); $popup = (GET_POPUP!='') ? '?popup=1' : ''; header('Location: '. createURL('edit', $bookmark['bookmarks'][0]['bId'] . $popup)); exit(); From d249a8ad19514e0c386391ae37081445ee6c23c7 Mon Sep 17 00:00:00 2001 From: cweiske Date: Thu, 18 Mar 2010 19:26:09 +0000 Subject: [PATCH 42/63] fix bad bug that was introduced due to performance optimizations git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@693 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/Service/Bookmark.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 2258625..364b1a0 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -380,7 +380,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService } $hashes = array(); - $sql = '(1'; + $sql = '(0'; foreach ($addresses as $key => $address) { $hash = $this->getHash($address); $hashes[$hash] = $address; From a42a6eb2ba7aab80b50cf641d643a911e5f032ca Mon Sep 17 00:00:00 2001 From: cweiske Date: Thu, 18 Mar 2010 19:28:42 +0000 Subject: [PATCH 43/63] test for the failure we fixed one commit ago git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@694 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/BookmarkTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index 7885876..40869b2 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -353,6 +353,10 @@ class BookmarkTest extends TestBase $bid2 = $this->addBookmark(); $bookmark2 = $this->bs->getBookmark($bid2); + //do not search for this one + $bid3 = $this->addBookmark(); + $bookmark3 = $this->bs->getBookmark($bid3); + $ret = $this->bs->bookmarksExist( array( From 0f3c51ef7ebb18919a65ccdc25782f9550a1c680 Mon Sep 17 00:00:00 2001 From: cweiske Date: Fri, 19 Mar 2010 07:43:21 +0000 Subject: [PATCH 44/63] fix notice git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@695 b3834d28-1941-0410-a4f8-b48e95affb8f --- src/SemanticScuttle/db/mysqli.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SemanticScuttle/db/mysqli.php b/src/SemanticScuttle/db/mysqli.php index 27814a7..03b36ea 100644 --- a/src/SemanticScuttle/db/mysqli.php +++ b/src/SemanticScuttle/db/mysqli.php @@ -440,7 +440,7 @@ class sql_db echo '' . $msg_title . ''; + echo 'DB query explanation'; echo '
    phpBB LogoSQL Report      

    Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries} queries" . (($cache_num_queries) ? " + $cache_num_queries " . (($cache_num_queries == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '
    Time spent on MySQL queries: ' . round($this->sql_time, 5) . 's | Time spent on PHP: ' . round($totaltime - $this->sql_time, 5) . 's
    '; echo $sql_report; echo '

    '; From b18869f6d769c18d19fd937683352e0ea7a54939 Mon Sep 17 00:00:00 2001 From: cweiske Date: Fri, 19 Mar 2010 07:43:42 +0000 Subject: [PATCH 45/63] remove another 9 queries for logged in users! git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@696 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/templates/bookmarks.tpl.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/data/templates/bookmarks.tpl.php b/data/templates/bookmarks.tpl.php index 1caf0e7..a8299fd 100644 --- a/data/templates/bookmarks.tpl.php +++ b/data/templates/bookmarks.tpl.php @@ -228,6 +228,14 @@ if($currenttag!= '') { ); } + if ($userservice->isLoggedOn()) { + $watchedNames = $userservice->getWatchNames( + $currentUser->getId(), true + ); + } else { + $watchedNames = null; + } + foreach ($bookmarks as $key => &$row) { switch ($row['bStatus']) { case 0: @@ -321,7 +329,11 @@ if($currenttag!= '') { } // Private Note (just visible by the owner and his/her contacts) - if($userservice->isLoggedOn() && ($currentUser->getId() == $row['uId'] || in_array($row['username'], $userservice->getWatchNames($currentUser->getId(), true)))) { + if ($watchedNames !== null + && ($currentUser->getId() == $row['uId'] + || in_array($row['username'], $watchedNames) + ) + ) { $privateNoteField = $row['bPrivateNote']; } else { $privateNoteField = ''; From 39812084054ec9d4119e53f188406bb5d2c3705e Mon Sep 17 00:00:00 2001 From: cweiske Date: Fri, 19 Mar 2010 07:44:21 +0000 Subject: [PATCH 46/63] note fixation of bug #2960663 in changelog git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@697 b3834d28-1941-0410-a4f8-b48e95affb8f --- doc/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index d9cdb6e..9af38d5 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -7,6 +7,7 @@ ChangeLog for SemantiScuttle - New config option to skip "SET NAMES UTF8" call: $dbneedssetnames - Do not highlight admin bookmarks when $enableAdminColors is disabled - Fix bug #2953732: faulty error message for duplicate bookmarks +- Fix bug #2960663: do not send content-type headers twice for ajax/api scripts 0.96.1 - 2010-02-09 From 78bac4580c25ad0f39d6e83aa3470f3d2d64806a Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:03:52 +0000 Subject: [PATCH 47/63] add unittest url parameter git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@698 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/config.default.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/data/config.default.php b/data/config.default.php index fdbdaee..4f45eac 100644 --- a/data/config.default.php +++ b/data/config.default.php @@ -723,4 +723,16 @@ $authDebug = false; * @var string */ $authEmailSuffix = null; + + + + +/** + * URL unittests are being run against + * Has to have a trailing slash + * + * @var string + */ +$unittestUrl = null; + ?> From ccabc1cdfa6605f4454653360ec00dc171368556 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:04:53 +0000 Subject: [PATCH 48/63] support username and password change git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@699 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/TestBase.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/TestBase.php b/tests/TestBase.php index 28bda27..aad772f 100644 --- a/tests/TestBase.php +++ b/tests/TestBase.php @@ -75,15 +75,26 @@ class TestBase extends PHPUnit_Framework_TestCase /** * Creates a new user in the database. * + * @param string $username Username + * @param string $password Password + * * @return integer ID of user */ - protected function addUser() + protected function addUser($username = null, $password = null) { $us = SemanticScuttle_Service_Factory::get('User'); $rand = rand(); + + if ($username === null) { + $username = 'unittestuser-' . $rand; + } + if ($password === null) { + $password = $rand; + } + $uid = $us->addUser( - 'unittestuser-' . $rand, - $rand, + $username, + $password, 'unittest-' . $rand . '@example.org' ); return $uid; From a518928796f87ff61e7fcb34d69b374378fdadf6 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:06:07 +0000 Subject: [PATCH 49/63] add test for api/export_csv.php git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@700 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/Api/ExportCsvTest.php | 104 ++++++++++++++++++++++++++++++++++++ tests/TestBaseApi.php | 78 +++++++++++++++++++++++++++ tests/prepare.php | 1 + 3 files changed, 183 insertions(+) create mode 100644 tests/Api/ExportCsvTest.php create mode 100644 tests/TestBaseApi.php diff --git a/tests/Api/ExportCsvTest.php b/tests/Api/ExportCsvTest.php new file mode 100644 index 0000000..438df7f --- /dev/null +++ b/tests/Api/ExportCsvTest.php @@ -0,0 +1,104 @@ + + * @author Christian Weiske + * @author Eric Dane + * @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_ExportCsvTest::main'); +} + +/** + * Unit tests for the SemanticScuttle csv export API + * + * @category Bookmarking + * @package SemanticScuttle + * @author Benjamin Huynh-Kim-Bang + * @author Christian Weiske + * @author Eric Dane + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ +class Api_ExportCsvTest extends TestBaseApi +{ + protected $us; + protected $bs; + protected $urlPart = 'api/export_csv.php'; + + + + /** + * 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 MIME content type and filename header fields + */ + public function testMimeTypeFilename() + { + $res = $this->getRequest()->send(); + + $this->assertEquals(200, $res->getStatus()); + //verify MIME content type + $this->assertEquals( + 'application/csv-tab-delimited-table; charset=utf-8', + $res->getHeader('content-type') + ); + //we need a file name + $this->assertNotNull($res->getHeader('content-disposition')); + } +} + +if (PHPUnit_MAIN_METHOD == 'Api_ExportCsvTest::main') { + Api_ExportCsvTest::main(); +} +?> \ No newline at end of file diff --git a/tests/TestBaseApi.php b/tests/TestBaseApi.php new file mode 100644 index 0000000..03ca016 --- /dev/null +++ b/tests/TestBaseApi.php @@ -0,0 +1,78 @@ + + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ + +require_once 'PHPUnit/Framework.php'; + +PHPUnit_Util_Filter::addFileToFilter(__FILE__); + +/** + * Base unittest class for web API tests. + * + * @category Bookmarking + * @package SemanticScuttle + * @author Christian Weiske + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ +class TestBaseApi extends TestBase +{ + protected $url; + protected $urlPart = null; + + + + protected function setUp() + { + if ($GLOBALS['unittestUrl'] === null) { + $this->assertTrue(false, 'Unittest URL not set in config'); + } + if ($this->urlPart === null) { + $this->assertTrue(false, 'Set the urlPart variable'); + } + $this->url = $GLOBALS['unittestUrl'] . $this->urlPart; + + $this->us = SemanticScuttle_Service_Factory::get('User'); + $this->bs = SemanticScuttle_Service_Factory::get('Bookmark'); + $this->bs->deleteAll(); + } + + + + /** + * Gets a HTTP request object + * + * @param string $urlSuffix Suffix for the URL + * @param boolean $auth If user authentication is needed + * + * @return HTTP_Request2 HTTP request object + */ + protected function getRequest($urlSuffix = null, $auth = true) + { + $req = new HTTP_Request2( + $this->url . $urlSuffix, + HTTP_Request2::METHOD_GET + ); + + if ($auth) { + $this->addUser('testuser', 'testpassword'); + $req->setAuth( + 'testuser', 'testpassword', + HTTP_Request2::AUTH_BASIC + ); + } + + return $req; + } + +} +?> \ No newline at end of file diff --git a/tests/prepare.php b/tests/prepare.php index 835810e..ce9cd1c 100644 --- a/tests/prepare.php +++ b/tests/prepare.php @@ -21,6 +21,7 @@ define('UNIT_TEST_MODE', true); require_once dirname(__FILE__) . '/../src/SemanticScuttle/header.php'; require_once dirname(__FILE__) . '/TestBase.php'; +require_once dirname(__FILE__) . '/TestBaseApi.php'; if ($GLOBALS['debugMode'] == true && $GLOBALS['dbtype'] == 'mysql4' From 90f7d528d3f34a57d517cca268766bdbae161585 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:07:18 +0000 Subject: [PATCH 50/63] more tests for csv export api git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@701 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/Api/ExportCsvTest.php | 119 +++++++++++++++++++++++++++++++++++- tests/TestBase.php | 8 ++- tests/TestBaseApi.php | 44 +++++++++---- 3 files changed, 157 insertions(+), 14 deletions(-) diff --git a/tests/Api/ExportCsvTest.php b/tests/Api/ExportCsvTest.php index 438df7f..ee7db4b 100644 --- a/tests/Api/ExportCsvTest.php +++ b/tests/Api/ExportCsvTest.php @@ -85,7 +85,7 @@ class Api_ExportCsvTest extends TestBaseApi */ public function testMimeTypeFilename() { - $res = $this->getRequest()->send(); + $res = reset($this->getAuthRequest())->send(); $this->assertEquals(200, $res->getStatus()); //verify MIME content type @@ -96,6 +96,123 @@ class Api_ExportCsvTest extends TestBaseApi //we need a file name $this->assertNotNull($res->getHeader('content-disposition')); } + + + + /** + * Test CSV export without bookmarks + */ + public function testNoBookmarks() + { + list($req, $uid) = $this->getAuthRequest(); + $body = $req->send()->getBody(); + $csv = $this->getCsvArray($body); + + $this->assertEquals(1, count($csv)); + $this->assertCsvHeader($csv); + } + + + + /** + * Test CSV export with some bookmarks + */ + public function testBookmarks() + { + list($req, $uid) = $this->getAuthRequest(); + //public + $this->addBookmark( + $uid, 'http://example.org/testBookmarks', 0, + array('unittest', 'testBookmarks'), 'mytitle' + ); + //shared + $this->addBookmark( + $uid, 'http://example.org/testBookmarks-shared', 1, + array('unittest', 'testBookmarks'), 'mytitle-shared' + ); + //private + $this->addBookmark( + $uid, 'http://example.org/testBookmarks-private', 2, + array('unittest', 'testBookmarks'), 'mytitle-private' + ); + + //private other that should not in the export + $this->addBookmark( + null, 'http://example.org/testBookmarks-private2', 2 + ); + + $body = $req->send()->getBody(); + $csv = $this->getCsvArray($body); + + $this->assertEquals(4, count($csv)); + $this->assertCsvHeader($csv); + + $this->assertEquals('http://example.org/testBookmarks', $csv[1][0]); + $this->assertEquals('mytitle', $csv[1][1]); + $this->assertEquals('unittest,testbookmarks', $csv[1][2]); + + $this->assertEquals('http://example.org/testBookmarks-shared', $csv[2][0]); + $this->assertEquals('mytitle-shared', $csv[2][1]); + $this->assertEquals('unittest,testbookmarks', $csv[2][2]); + + $this->assertEquals('http://example.org/testBookmarks-private', $csv[3][0]); + $this->assertEquals('mytitle-private', $csv[3][1]); + $this->assertEquals('unittest,testbookmarks', $csv[3][2]); + } + + + + /** + * Asserts that the CSV array contains the correct header + * + * @param array $csv CSV array from getCsvArray() + * + * @return void + */ + protected function assertCsvHeader($csv) + { + $this->assertEquals( + array('url', 'title', 'tags', 'description'), + $csv[0] + ); + } + + + + /** + * Converts a string of CSV data to an array + * + * @param string $body String containing the full CSV file + * + * @return array Array of CSV data + */ + protected function getCsvArray($body) + { + $v53 = (version_compare(PHP_VERSION, '5.3.0') === 1); + + //dead simple implementation that does not work with + // advanced CSV files + $ar = array(); + foreach (explode("\n", $body) as $line) { + if ($v53) { + $ar[] = str_getcsv($line, ';'); + } else { + $arl = explode(';', $line); + foreach ($arl as &$str) { + if (substr($str, 0, 1) == '"' + && substr($str, -1) == '"' + ) { + $str = substr($str, 1, -1); + } + } + $ar[] = $arl; + } + } + if (count(end($ar)) == 1 && reset(end($ar)) == '') { + unset($ar[key($ar)]); + } + return $ar; + } } if (PHPUnit_MAIN_METHOD == 'Api_ExportCsvTest::main') { diff --git a/tests/TestBase.php b/tests/TestBase.php index aad772f..402330b 100644 --- a/tests/TestBase.php +++ b/tests/TestBase.php @@ -34,6 +34,7 @@ class TestBase extends PHPUnit_Framework_TestCase * @param integer $status Bookmark visibility * @param array $tags Array of tags to attach. If "null" is given, * it will automatically be "unittest" + * @param string $title Bookmark title * * @return integer ID of bookmark * @@ -41,7 +42,7 @@ class TestBase extends PHPUnit_Framework_TestCase */ protected function addBookmark( $user = null, $address = null, $status = 0, - $tags = null + $tags = null, $title = null ) { if ($user === null) { $user = $this->addUser(); @@ -56,10 +57,13 @@ class TestBase extends PHPUnit_Framework_TestCase if ($address === null) { $address = 'http://example.org/' . $rand; } + if ($title === null) { + $title = 'unittest bookmark #' . $rand; + } $bid = $bs->addBookmark( $address, - 'unittest bookmark #' . $rand, + $title, 'description', null, $status, diff --git a/tests/TestBaseApi.php b/tests/TestBaseApi.php index 03ca016..645ead9 100644 --- a/tests/TestBaseApi.php +++ b/tests/TestBaseApi.php @@ -42,8 +42,11 @@ class TestBaseApi extends TestBase $this->url = $GLOBALS['unittestUrl'] . $this->urlPart; $this->us = SemanticScuttle_Service_Factory::get('User'); + $this->us->deleteAll(); $this->bs = SemanticScuttle_Service_Factory::get('Bookmark'); $this->bs->deleteAll(); + $this->b2t = SemanticScuttle_Service_Factory::get('Bookmark2Tag'); + $this->b2t->deleteAll(); } @@ -51,28 +54,47 @@ class TestBaseApi extends TestBase /** * Gets a HTTP request object * - * @param string $urlSuffix Suffix for the URL - * @param boolean $auth If user authentication is needed + * @param string $urlSuffix Suffix for the URL * * @return HTTP_Request2 HTTP request object */ - protected function getRequest($urlSuffix = null, $auth = true) + protected function getRequest($urlSuffix = null) { $req = new HTTP_Request2( $this->url . $urlSuffix, HTTP_Request2::METHOD_GET ); - if ($auth) { - $this->addUser('testuser', 'testpassword'); - $req->setAuth( - 'testuser', 'testpassword', - HTTP_Request2::AUTH_BASIC - ); - } - return $req; } + + + /** + * Gets a HTTP request object + * + * @param string $urlSuffix Suffix for the URL + * @param mixed $auth If user authentication is needed (true/false) + * or array with username and password + * + * @return array(HTTP_Request2, integer) HTTP request object and user id + */ + protected function getAuthRequest($urlSuffix = null, $auth = true) + { + $req = $this->getRequest($urlSuffix); + if (is_array($auth)) { + list($username, $password) = $auth; + } else { + $username = 'testuser'; + $password = 'testpassword'; + } + $uid = $this->addUser($username, $password); + $req->setAuth( + $username, $password, + HTTP_Request2::AUTH_BASIC + ); + return array($req, $uid); + } + } ?> \ No newline at end of file From 74dc9ea6a4e553f38a97928617074fd76793c783 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:08:38 +0000 Subject: [PATCH 51/63] make export_csv support filtering to multiple tags git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@702 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/Api/ExportCsvTest.php | 61 +++++++++++++++++++++++++++++++++++++ www/api/export_csv.php | 15 ++++++--- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/tests/Api/ExportCsvTest.php b/tests/Api/ExportCsvTest.php index ee7db4b..18008e1 100644 --- a/tests/Api/ExportCsvTest.php +++ b/tests/Api/ExportCsvTest.php @@ -162,6 +162,67 @@ class Api_ExportCsvTest extends TestBaseApi + /** + * Test CSV export with tag filter + */ + public function testTagFilter() + { + list($req, $uid) = $this->getAuthRequest('?tag=tag1'); + $this->addBookmark( + $uid, 'http://example.org/tag-1', 0, + array('unittest', 'tag1') + ); + $this->addBookmark( + $uid, 'http://example.org/tag-2', 0, + array('unittest', 'tag2') + ); + $this->addBookmark( + $uid, 'http://example.org/tag-3', 0, + array('unittest', 'tag1', 'tag2') + ); + + $body = $req->send()->getBody(); + $csv = $this->getCsvArray($body); + + $this->assertEquals(3, count($csv)); + $this->assertCsvHeader($csv); + + $this->assertEquals('http://example.org/tag-1', $csv[1][0]); + $this->assertEquals('http://example.org/tag-3', $csv[2][0]); + } + + + + /** + * Test CSV export with tag filter for multiple tags + */ + public function testTagFilterMultiple() + { + list($req, $uid) = $this->getAuthRequest('?tag=tag1+tag2'); + $this->addBookmark( + $uid, 'http://example.org/tag-1', 0, + array('unittest', 'tag1') + ); + $this->addBookmark( + $uid, 'http://example.org/tag-2', 0, + array('unittest', 'tag2') + ); + $this->addBookmark( + $uid, 'http://example.org/tag-3', 0, + array('unittest', 'tag1', 'tag2') + ); + + $body = $req->send()->getBody(); + $csv = $this->getCsvArray($body); + + $this->assertEquals(2, count($csv)); + $this->assertCsvHeader($csv); + + $this->assertEquals('http://example.org/tag-3', $csv[1][0]); + } + + + /** * Asserts that the CSV array contains the correct header * diff --git a/www/api/export_csv.php b/www/api/export_csv.php index b9cf497..43951ec 100644 --- a/www/api/export_csv.php +++ b/www/api/export_csv.php @@ -10,13 +10,18 @@ header("Content-disposition: filename=exportBookmarks.csv"); $bookmarkservice =SemanticScuttle_Service_Factory::get('Bookmark'); // Check to see if a tag was specified. -if (isset($_REQUEST['tag']) && (trim($_REQUEST['tag']) != '')) - $tag = trim($_REQUEST['tag']); -else - $tag = NULL; +if (isset($_REQUEST['tag']) && (trim($_REQUEST['tag']) != '')) { + //$_GET vars have + replaced to " " automatically + $tag = str_replace(' ', '+', trim($_REQUEST['tag'])); +} else { + $tag = null; +} // Get the posts relevant to the passed-in variables. -$bookmarks =& $bookmarkservice->getBookmarks(0, NULL, $userservice->getCurrentUserId(), $tag, NULL, getSortOrder()); +$bookmarks = $bookmarkservice->getBookmarks( + 0, null, $userservice->getCurrentUserId(), + $tag, null, getSortOrder() +); //columns titles echo 'url;title;tags;description'; From ccbc63aec4869f64fb68706a6d687aa665a60c9c Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:09:59 +0000 Subject: [PATCH 52/63] test that public bookmarks of other people are not exported via csv git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@703 b3834d28-1941-0410-a4f8-b48e95affb8f --- tests/Api/ExportCsvTest.php | 5 +++++ www/api/export_csv.php | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/Api/ExportCsvTest.php b/tests/Api/ExportCsvTest.php index 18008e1..2bff8a5 100644 --- a/tests/Api/ExportCsvTest.php +++ b/tests/Api/ExportCsvTest.php @@ -140,6 +140,11 @@ class Api_ExportCsvTest extends TestBaseApi $this->addBookmark( null, 'http://example.org/testBookmarks-private2', 2 ); + //public bookmark from other people that should not be + // exported, too + $this->addBookmark( + null, 'http://example.org/testBookmarks-other', 0 + ); $body = $req->send()->getBody(); $csv = $this->getCsvArray($body); diff --git a/www/api/export_csv.php b/www/api/export_csv.php index 43951ec..bb469b1 100644 --- a/www/api/export_csv.php +++ b/www/api/export_csv.php @@ -1,5 +1,18 @@ + * @author Christian Weiske + * @author Eric Dane + * @license GPL http://www.gnu.org/licenses/gpl.html + * @link http://sourceforge.net/projects/semanticscuttle + */ // Force HTTP authentication first! $httpContentType = 'application/csv-tab-delimited-table'; From 7e6de50232ed7ba74ff7ea33f5fd5c838921bb1f Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:10:57 +0000 Subject: [PATCH 53/63] fix multiple tags in html export git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@704 b3834d28-1941-0410-a4f8-b48e95affb8f --- www/api/export_html.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/api/export_html.php b/www/api/export_html.php index 8d70927..731b7fb 100644 --- a/www/api/export_html.php +++ b/www/api/export_html.php @@ -27,7 +27,8 @@ $bookmarkservice = SemanticScuttle_Service_Factory::get('Bookmark'); // Check to see if a tag was specified. if (isset($_REQUEST['tag']) && (trim($_REQUEST['tag']) != '')) { - $tag = trim($_REQUEST['tag']); + //$_GET vars have + replaced to " " automatically + $tag = str_replace(' ', '+', trim($_REQUEST['tag'])); } else { $tag = null; } From ea0527fc83fbb04f89104836af8334e5476e04c4 Mon Sep 17 00:00:00 2001 From: cweiske Date: Sun, 28 Mar 2010 18:11:56 +0000 Subject: [PATCH 54/63] make export_html follow the "specs" a bit more and add format documentation url git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@705 b3834d28-1941-0410-a4f8-b48e95affb8f --- www/api/export_html.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/www/api/export_html.php b/www/api/export_html.php index 731b7fb..c7c8cf4 100644 --- a/www/api/export_html.php +++ b/www/api/export_html.php @@ -3,6 +3,9 @@ * Implements the del.icio.us API request for all a user's posts, * optionally filtered by tag. * + * Netscape bookmark file format is documented at + * http://msdn.microsoft.com/en-us/library/aa753582(VS.85).aspx + * * SemanticScuttle - your social bookmark manager. * * PHP version 5. @@ -46,7 +49,7 @@ echo ''; echo ''."\r\n"; echo 'Bookmarks'."\r\n"; echo '

    Bookmarks for '. htmlspecialchars($currentUser->getUsername()) .''. (is_null($tag) ? '' : ' tag="'. htmlspecialchars($tag) .'"') ." from " . $sitename ."

    \r\n"; -echo '

    '."\r\n"; +echo '

    '."\r\n"; @@ -68,9 +71,9 @@ foreach ($bookmarks['bookmarks'] as $row) { $taglist = 'system:unfiled'; } - echo "\t
    " . filter($row['bTitle'], 'xml') ."\r\n"; + echo "\t
    " . filter($row['bTitle'], 'xml') ."\r\n"; } -echo '

    '; +echo '

    '; ?> From 1ccb37387196aa17052a0a1d9ea770e955f5dac7 Mon Sep 17 00:00:00 2001 From: cweiske Date: Mon, 3 May 2010 06:24:38 +0000 Subject: [PATCH 55/63] add russian translation, thanks to Serge git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@706 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/locales/ru_RU/LC_MESSAGES/messages.po | 1416 ++++++++++++++++++++ 1 file changed, 1416 insertions(+) create mode 100644 data/locales/ru_RU/LC_MESSAGES/messages.po diff --git a/data/locales/ru_RU/LC_MESSAGES/messages.po b/data/locales/ru_RU/LC_MESSAGES/messages.po new file mode 100644 index 0000000..5a2607a --- /dev/null +++ b/data/locales/ru_RU/LC_MESSAGES/messages.po @@ -0,0 +1,1416 @@ +# SemanticScuttle ru_RU Translation +# Copyright (C) 2005 - 2009 SemanticScuttle project +# This file is distributed under the same license as the SemanticScuttle package. +# webii.ru +# +msgid "" +msgstr "" +"Project-Id-Version: Semantic Scuttle\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-04 11:33+0200\n" +"PO-Revision-Date: 2010-04-30 02:35+0400\n" +"Last-Translator: webii.ru \n" +"Language-Team: webii.ru \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Language: English\n" +"X-Poedit-Country: UNITED KINGDOM\n" +"X-Poedit-SourceCharset: utf-8\n" + +#: ../../../about.php:23 +#: ../../../about.php:24 +#: ../../../templates/bottom.inc.php:5 +#: ../../../templates/toolbar.inc.php:15 +#: ../../../templates/toolbar.inc.php:28 +msgid "About" +msgstr "О сайте" + +#: ../../../admin.php:32 +msgid "Manage users" +msgstr "Управление пользователями" + +#: ../../../admin.php:68 +#, php-format +msgid "%s and all his bookmarks and tags were deleted." +msgstr "%s и всего закладки и тэги удалены." + +#: ../../../admin.php:75 +msgid "Problem with " +msgstr "Возникла проблема с" + +#: ../../../ajaxDelete.php:37 +msgid "You are not allowed to delete this bookmark" +msgstr "У Вас нет прав на удаление этой закладки" + +#: ../../../ajaxDelete.php:41 +#: ../../../edit.php:103 +msgid "Failed to delete bookmark" +msgstr "Ошибка при удалении закладки" + +#: ../../../alltags.php:49 +msgid "All Tags" +msgstr "Все тэги" + +#: ../../../alltags.php:55 +#: ../../../bookmarks.php:96 +#: ../../../populartags.php:52 +#: ../../../profile.php:51 +#: ../../../rss.php:67 +#: ../../../search.php:101 +#: ../../../watch.php:45 +#: ../../../watchlist.php:61 +#, php-format +msgid "User with username %s was not found" +msgstr "Пользователь с именем %s не найден" + +#: ../../../bookmarkcommondescriptionedit.php:51 +#: ../../../tag2tagadd.php:37 +#: ../../../tag2tagdelete.php:41 +#: ../../../tag2tagedit.php:33 +#: ../../../tagcommondescriptionedit.php:43 +#: ../../../tagedit.php:43 +msgid "Permission denied." +msgstr "Доступ запрещен." + +#: ../../../bookmarkcommondescriptionedit.php:60 +msgid "Bookmark common description updated" +msgstr "Описание закладки обновлено" + +#: ../../../bookmarkcommondescriptionedit.php:63 +msgid "Failed to update the bookmark common description" +msgstr "Ошибка при изменении описания закладки" + +#: ../../../bookmarkcommondescriptionedit.php:71 +msgid "Edit Bookmark Common Description" +msgstr "Изменить описание закладки" + +#: ../../../bookmarks.php:111 +#: ../../../tags.php:47 +msgid "Remove the tag from the selection" +msgstr "Remove the tag from the selection" + +#: ../../../bookmarks.php:131 +#: ../../../edit.php:65 +msgid "Your bookmark must have a title and an address" +msgstr "Закладка должна иметь название и адрес" + +#: ../../../bookmarks.php:152 +#: ../../../edit.php:83 +#: ../../../edit.php:86 +msgid "Bookmark saved" +msgstr "Закладка сохранена" + +#: ../../../bookmarks.php:152 +msgid "(Come back to previous page.)" +msgstr "(Вернуться на предыдущую страницу.)" + +#: ../../../bookmarks.php:159 +#: ../../../import.php:106 +#: ../../../importNetscape.php:108 +msgid "There was an error saving your bookmark. Please try again or contact the administrator." +msgstr "Произошла ошибка при сохранении закладки. Попробуйте еще раз или свяжитесь с администрацией." + +#: ../../../bookmarks.php:209 +#: ../../../templates/toolbar.inc.php:13 +msgid "Add a Bookmark" +msgstr "Добавить закладку" + +#: ../../../bookmarks.php:213 +msgid "Add Bookmark" +msgstr "Добавить закладку" + +#: ../../../bookmarks.php:216 +msgid "You must be logged in before you can add bookmarks." +msgstr "Вы должны войти в систему, прежде чем добавлять закладки." + +#: ../../../bookmarks.php:270 +#: ../../../bookmarks.php:271 +msgid "My Bookmarks" +msgstr "Мои закладки" + +#: ../../../edit.php:44 +#: ../../../edit.php:45 +msgid "Edit Bookmark" +msgstr "Изменить закладку" + +#: ../../../edit.php:51 +#, php-format +msgid "Bookmark with id %s not was not found" +msgstr "Закладка # %s не найдена" + +#: ../../../edit.php:57 +msgid "You are not allowed to edit this bookmark" +msgstr "У Вас нет доступа для редактирования этой закладки" + +#: ../../../edit.php:77 +msgid "Error while saving your bookmark" +msgstr "Ошибка во время сохранения Вашей закладки" + +#: ../../../edit.php:113 +#: ../../../templates/editprofile.tpl.php:52 +msgid "Save Changes" +msgstr "Сохранить изменения" + +#: ../../../functions.inc.php:144 +msgid "message_die() was called multiple times." +msgstr "message_die() было вызвано несколько раз." + +#: ../../../functions.inc.php:156 +msgid "SQL Error" +msgstr "Ошибка SQL" + +#: ../../../functions.inc.php:162 +msgid "Line" +msgstr "Line" + +#: ../../../functions.inc.php:162 +#: ../../../templates/importDelicious.tpl.php:8 +#: ../../../templates/importNetscape.tpl.php:9 +#: ../../../templates/importStructure.tpl.php:10 +msgid "File" +msgstr "Файл" + +#: ../../../functions.inc.php:168 +msgid "Information" +msgstr "Информация" + +#: ../../../functions.inc.php:173 +msgid "Critical Information" +msgstr "Важная информация" + +#: ../../../functions.inc.php:178 +msgid "An error occured" +msgstr "Произошла ошибка" + +#: ../../../functions.inc.php:181 +msgid "General Error" +msgstr "Общая ошибка" + +#: ../../../functions.inc.php:189 +msgid "An critical error occured" +msgstr "Произошла критическая ошибка" + +#: ../../../functions.inc.php:192 +msgid "Critical Error" +msgstr "Критическая ошибка" + +#: ../../../functions.inc.php:201 +msgid "DEBUG MODE" +msgstr "Режим DEBUG" + +#: ../../../history.php:61 +msgid "History" +msgstr "История" + +#: ../../../history.php:62 +#, php-format +msgid "History for %s" +msgstr "История для %s" + +#: ../../../history.php:84 +msgid "Address was not found" +msgstr "Адрес не найден" + +#: ../../../import.php:47 +msgid "Could not open XML input" +msgstr "Невозможно открыть XML" + +#: ../../../import.php:51 +#, php-format +msgid "XML error: %s at line %d" +msgstr "Ошибка XML: %s в строке %d" + +#: ../../../import.php:60 +msgid "Import Bookmarks from del.icio.us" +msgstr "Импортировать закладки из del.icio.us" + +#: ../../../import.php:93 +msgid "You have already submitted this bookmark." +msgstr "Вы уже добавили эту закладку." + +#: ../../../import.php:104 +msgid "Bookmark imported." +msgstr "Закладка импортирована." + +#: ../../../importNetscape.php:95 +msgid "You have already submitted some of these bookmarks." +msgstr "Вы уже сохранили некоторые из этих закладок." + +#: ../../../importNetscape.php:115 +msgid "Bookmarks found: " +msgstr "Найденные закладки: " + +#: ../../../importNetscape.php:116 +msgid "Bookmarks imported: " +msgstr "Закладки загружены: " + +#: ../../../importNetscape.php:117 +#: ../../../importNetscape.php:122 +msgid "Import Bookmarks from Browser File" +msgstr "Импортировать закладки из файла" + +#: ../../../importStructure.php:61 +msgid "Bad indentation" +msgstr "Ошибка в отступе" + +#: ../../../importStructure.php:67 +msgid "New links between tags: " +msgstr "Новые ссылки между тэгов: " + +#: ../../../importStructure.php:72 +msgid "Import Structure" +msgstr "Импорт структуры" + +#: ../../../index.php:38 +msgid "You have now logged out" +msgstr "Вы вышли" + +#: ../../../index.php:45 +#, php-format +msgid "%s: Recent bookmarks" +msgstr "%s: Недавно добавленные закладки" + +#: ../../../index.php:78 +msgid "Store, share and tag your favourite links" +msgstr "Сохраняйте, делитесь и отмечайте Ваши любимые ссылки" + +#: ../../../index.php:79 +msgid "All Bookmarks" +msgstr "Все закладки" + +#: ../../../jsScuttle.php:22 +#: ../../../templates/admin.tpl.php:19 +#: ../../../templates/tag2tagadd.tpl.php:21 +#: ../../../templates/tag2tagdelete.tpl.php:13 +#: ../../../templates/tag2tagedit.tpl.php:14 +#: ../../../templates/tag2tagedit.tpl.php:35 +#: ../../../templates/tagdelete.tpl.php:6 +msgid "Are you sure?" +msgstr "Вы уверены?" + +#: ../../../jsScuttle.php:22 +#: ../../../templates/tag2tagdelete.tpl.php:15 +#: ../../../templates/tag2tagedit.tpl.php:16 +#: ../../../templates/tagdelete.tpl.php:8 +msgid "Yes" +msgstr "Да" + +#: ../../../jsScuttle.php:22 +#: ../../../templates/tag2tagdelete.tpl.php:16 +#: ../../../templates/tag2tagedit.tpl.php:17 +#: ../../../templates/tagdelete.tpl.php:9 +msgid "No" +msgstr "Нет" + +#: ../../../jsScuttle.php:69 +msgid "Available" +msgstr "Доступно" + +#: ../../../jsScuttle.php:72 +msgid "Not Available" +msgstr "Недоступно" + +#: ../../../login.php:48 +msgid "The details you have entered are incorrect. Please try again." +msgstr "Вы ввели некорректные данные. Попробуйте еще раз." + +#: ../../../login.php:57 +#: ../../../templates/login.tpl.php:26 +#: ../../../templates/toolbar.inc.php:29 +msgid "Log In" +msgstr "Вход" + +#: ../../../password.php:36 +msgid "You must enter your username." +msgstr "Вы должны ввести имя пользователя." + +#: ../../../password.php:40 +msgid "You must enter your e-mail address." +msgstr "Вы должны ввести e-mail." + +#: ../../../password.php:48 +msgid "No matches found for that username." +msgstr "Для этого пользователя ничего не найдено." + +#: ../../../password.php:51 +msgid "No matches found for that combination of username and e-mail address." +msgstr "Ничего не найдено для этого имени пользователя и адреса e-mail." + +#: ../../../password.php:59 +msgid "There was an error while generating your new password. Please try again." +msgstr "Произошла ошибка во время генерации имени пользователя. Попробуйте еще раз." + +#: ../../../password.php:63 +msgid "Your new password is:" +msgstr "Ваш новый пароль:" + +#: ../../../password.php:63 +msgid "To keep your bookmarks secure, you should change this password in your profile the next time you log in." +msgstr "Для обеспечения безопасности, Вы должны изменить пароль в профиле, следующий раз когда войдете в систему." + +#: ../../../password.php:66 +#, php-format +msgid "%s Account Information" +msgstr "%s просмотр информации об аккаунте" + +#: ../../../password.php:68 +#, php-format +msgid "New password generated and sent to %s" +msgstr "Новый пароль отправлен по адресу %s" + +#: ../../../password.php:75 +msgid "Forgotten Password" +msgstr "Забытый пароль" + +#: ../../../populartags.php:46 +#: ../../../templates/dynamictags.inc.php:128 +#: ../../../templates/sidebar.block.common.php:9 +#: ../../../templates/sidebar.block.menu.php:74 +#: ../../../templates/sidebar.block.popular.php:23 +#: ../../../templates/sidebar.block.recent.php:34 +#: ../../../templates/toolbar.inc.php:27 +msgid "Popular Tags" +msgstr "Популярные тэги" + +#: ../../../profile.php:59 +#: ../../../watchlist.php:119 +msgid "Username was not specified" +msgstr "Имя пользователя не введено" + +#: ../../../profile.php:65 +msgid "My Profile" +msgstr "Мой профиль" + +#: ../../../profile.php:67 +#: ../../../templates/toolbar.inc.php:12 +msgid "Profile" +msgstr "Профиль" + +#: ../../../profile.php:89 +msgid "Invalid Token" +msgstr "Неверный символ" + +#: ../../../profile.php:94 +msgid "Password and confirmation do not match." +msgstr "Пароль и подтверждение пароля не совпадают." + +#: ../../../profile.php:98 +msgid "Password must be at least 6 characters long." +msgstr "Пароль должен быть минимум 6 символов длиной." + +#: ../../../profile.php:102 +msgid "E-mail address is not valid." +msgstr "Некорректный адрес E-mail." + +#: ../../../profile.php:106 +msgid "An error occurred while saving your changes." +msgstr "Ошибка при сохранении изменений." + +#: ../../../profile.php:108 +msgid "Changes saved." +msgstr "Изменения сохранены." + +#: ../../../register.php:40 +msgid "You must enter a username, password and e-mail address." +msgstr "Вы должны ввести имя пользователя, пароль и адрес e-mail." + +#: ../../../register.php:44 +msgid "This username has been reserved, please make another choice." +msgstr "Это имя пользователя занято, пожалуйста выберете другое." + +#: ../../../register.php:48 +msgid "This username already exists, please make another choice." +msgstr "Это имя пользоватея уже существует, пожалуйста выберете другое." + +#: ../../../register.php:52 +msgid "This username is not valid (too short, too long, forbidden characters...), please make another choice." +msgstr "Некорректное имя пользователя (слишком короткое, слишком длинное или запрещенные символы...), пожалуйста выберете другое." + +#: ../../../register.php:56 +msgid "E-mail address is not valid. Please try again." +msgstr "Некорректный адрес e-mail. Попробуйте еще раз." + +#: ../../../register.php:60 +msgid "Antispam answer is not valid. Please try again." +msgstr "Ответ на вопрос спам-фильтра не верен. Попробуйте еще раз." + +#: ../../../register.php:69 +msgid "You have successfully registered. Enjoy!" +msgstr "Поздравляем! Вы успешно зарегистрировались!" + +#: ../../../register.php:71 +msgid "Registration failed. Please try again." +msgstr "Ошибка регистрации. Пожалуйста попробуйте еще раз." + +#: ../../../register.php:77 +#: ../../../templates/register.tpl.php:41 +#: ../../../templates/toolbar.inc.php:30 +msgid "Register" +msgstr "Регистрация" + +#: ../../../rss.php:84 +#, php-format +msgid "Recent bookmarks posted to %s" +msgstr "Последние закладки добавленные в %s" + +#: ../../../search.inc.php:23 +msgid "Search..." +msgstr "Поиск..." + +#: ../../../search.inc.php:24 +msgid "in" +msgstr "в" + +#: ../../../search.inc.php:30 +msgid "this user's bookmarks" +msgstr "закладки этого пользователя" + +#: ../../../search.inc.php:35 +msgid "my bookmarks" +msgstr "мои закладки" + +#: ../../../search.inc.php:36 +msgid "my watchlist" +msgstr "мой лист наблюдения" + +#: ../../../search.inc.php:40 +msgid "all bookmarks" +msgstr "все закладки" + +#: ../../../search.inc.php:50 +msgid "Search" +msgstr "Поиск" + +#: ../../../search.php:73 +#: ../../../search.php:123 +msgid "Search Bookmarks" +msgstr "Поиск закладок" + +#: ../../../search.php:79 +msgid "Search Results" +msgstr "Результаты поиска" + +#: ../../../search.php:114 +msgid "Unsatisfied? You can also try our " +msgstr "Неудовлетворены? Вы еще можете поробовать наш " + +#: ../../../tag2tagadd.php:50 +msgid "Tag link created" +msgstr "Tag link created" + +#: ../../../tag2tagadd.php:53 +msgid "Failed to create the link" +msgstr "Ошибка создания ссылки" + +#: ../../../tag2tagadd.php:65 +msgid "Add Tag Link" +msgstr "Добавить тэг к ссылке" + +#: ../../../tag2tagdelete.php:66 +msgid "Tag link deleted" +msgstr "Тэг ссылки удален" + +#: ../../../tag2tagdelete.php:69 +msgid "Failed to delete the link" +msgstr "Ошибка удаления ссылки" + +#: ../../../tag2tagdelete.php:81 +msgid "Delete Link Between Tags" +msgstr "Delete Link between Tags" + +#: ../../../tag2tagedit.php:55 +msgid "Edit Link Between Tags" +msgstr "Edit Link between Tags" + +#: ../../../tagcommondescriptionedit.php:55 +msgid "Tag common description updated" +msgstr "Tag common description updated" + +#: ../../../tagcommondescriptionedit.php:58 +msgid "Failed to update the tag common description" +msgstr "Failed to update the tag common description" + +#: ../../../tagcommondescriptionedit.php:64 +#: ../../../templates/sidebar.block.tagactions.php:26 +msgid "Edit Tag Common Description" +msgstr "Edit Tag common description" + +#: ../../../tagdelete.php:43 +msgid "Tag deleted" +msgstr "Тэг удален" + +#: ../../../tagdelete.php:46 +msgid "Failed to delete the tag" +msgstr "Ошибка удаления тэга" + +#: ../../../tagdelete.php:54 +#: ../../../templates/sidebar.block.tagactions.php:22 +msgid "Delete Tag" +msgstr "Удалить тэг" + +#: ../../../tagedit.php:52 +msgid "Tag description updated" +msgstr "Описание тэга обновлено" + +#: ../../../tagedit.php:55 +msgid "Failed to update the tag description" +msgstr "Ошибка обновления описания тэга" + +#: ../../../tagedit.php:61 +#: ../../../templates/sidebar.block.tagactions.php:24 +msgid "Edit Tag Description" +msgstr "Изменить описание тэга" + +#: ../../../tagrename.php:63 +msgid "Tag renamed" +msgstr "Тэг переименован" + +#: ../../../tagrename.php:66 +msgid "Failed to rename the tag" +msgstr "Ошибка переименования тэга" + +#: ../../../tagrename.php:72 +#: ../../../templates/sidebar.block.tagactions.php:9 +msgid "Rename Tag" +msgid_plural "Rename Tags" +msgstr[0] "Переименовать тэг" +msgstr[1] "Переименовать тэги" + +#: ../../../tags.php:45 +#: ../../../tags.php:67 +#: ../../../templates/editbookmark.tpl.php:69 +#: ../../../templates/toolbar.inc.php:10 +msgid "Tags" +msgstr "Тэги" + +#: ../../../users.php:35 +msgid "Users" +msgstr "Пользователи" + +#: ../../../watch.php:54 +msgid "User removed from your watchlist" +msgstr "Пользователь удален из списка наблюдения" + +#: ../../../watch.php:56 +msgid "User added to your watchlist" +msgstr "Пользователь добавлен в список наблюдения" + +#: ../../../watchlist.php:104 +msgid "My Watchlist" +msgstr "Мой список наблюдения" + +#: ../../../watchlist.php:106 +#: ../../../templates/toolbar.inc.php:11 +msgid "Watchlist" +msgstr "Список наблюдения" + +#: ../../../templates/about.tpl.php:6 +msgid "Store all your favourite links in one place, accessible from anywhere." +msgstr "Храните Ваши любимые ссылки в одной месте, доступном отовсюду." + +#: ../../../templates/about.tpl.php:7 +msgid "Share your bookmarks with everyone, with friends on your watchlist or just keep them private." +msgstr "Делитесь ссылками со всем миром, с Вашими друзьями или оставьте их приватными." + +#: ../../../templates/about.tpl.php:8 +msgid "Tag your bookmarks with as many labels as you want, instead of wrestling with folders." +msgstr "Помечайте тэгами Ваши ссылки с таким количеством меток сколько хотите, вместо того чтобы бороться со свалкой ссылок." + +#: ../../../templates/about.tpl.php:9 +msgid "Register now" +msgstr "Зарегистрируйтесь сейчас" + +#: ../../../templates/about.tpl.php:9 +#, php-format +msgid " to start using %s!" +msgstr " чтобы начать пользоваться %s!" + +#: ../../../templates/about.tpl.php:12 +msgid "Geek Stuff" +msgstr "Geek Stuff" + +#: ../../../templates/about.tpl.php:14 +msgid "is licensed under the " +msgstr "лицензировано по" + +#: ../../../templates/about.tpl.php:14 +msgid "you can freely host it on your own web server." +msgstr "Вы можете свободно устанавливать его на свой веб-сервер." + +#: ../../../templates/about.tpl.php:15 +#, php-format +msgid "%1$s supports most of the del.icio.us API. Almost all of the neat tools made for that system can be modified to work with %1$s instead. If you find a tool that won't let you change the API address, ask the creator to add this setting. You never know, they might just do it." +msgstr "%1$s поддерживает большинство del.icio.us API. Большинство инструментов сделаных для этой системы, могут быть изменены для работы с %1$s. Если Вы нашли инструмент, который не позволяет изменить адрес API, попросите авторов добавить эту настройку. Возможно они это сделают." + +#: ../../../templates/about.tpl.php:24 +msgid "Tips" +msgstr "Подсказки" + +#: ../../../templates/about.tpl.php:26 +msgid "Add search plugin into your browser:" +msgstr "Добавить плагин поиска в браузер:" + +#: ../../../templates/about.tpl.php:27 +msgid "The secret tag \"system:unfiled\" allows you to find bookmarks without tags." +msgstr "Секретный тэг \"system:unfiled\" позволяет Вам находить закладки без тэгов." + +#: ../../../templates/about.tpl.php:28 +msgid "The secret tag \"system:imported\" allows you to find imported bookmarks." +msgstr "Секретный тэг \"system:imported\" позволяет Вам находить импортированные закладки." + +#: ../../../templates/admin.tpl.php:5 +msgid "Users management" +msgstr "Управление пользователем" + +#: ../../../templates/admin.tpl.php:14 +#, fuzzy +msgid "Public/Shared/Private" +msgstr "Публичный/Общий/Приватный" + +#: ../../../templates/admin.tpl.php:14 +#: ../../../templates/bookmarks.tpl.php:93 +msgid "bookmark(s)" +msgstr "закладка(и)" + +#: ../../../templates/admin.tpl.php:19 +#: ../../../templates/bookmarks.tpl.php:231 +msgid "Delete" +msgstr "Удалить" + +#: ../../../templates/admin.tpl.php:27 +msgid "Other actions" +msgstr "Другие действия" + +#: ../../../templates/admin.tpl.php:29 +msgid "Check all URLs (May take some time)" +msgstr "Проверить все ссылки (может занять некоторое время)" + +#: ../../../templates/bookmarkcommondescriptionedit.tpl.php:16 +#, fuzzy +msgid "Collaborative description: these fields can be viewed and modified by every users" +msgstr "Совместное описание: эти поля могут быть просмотрены и изменены любым пользователем" + +#: ../../../templates/bookmarkcommondescriptionedit.tpl.php:18 +#: ../../../templates/bookmarks.tpl.php:123 +#: ../../../templates/editbookmark.tpl.php:38 +msgid "Title" +msgstr "Название" + +#: ../../../templates/bookmarkcommondescriptionedit.tpl.php:23 +#: ../../../templates/editbookmark.tpl.php:44 +#: ../../../templates/editprofile.tpl.php:47 +#: ../../../templates/profile.tpl.php:33 +#: ../../../templates/tagcommondescriptionedit.tpl.php:13 +#: ../../../templates/tagedit.tpl.php:12 +msgid "Description" +msgstr "Описание" + +#: ../../../templates/bookmarkcommondescriptionedit.tpl.php:31 +#: ../../../templates/tagcommondescriptionedit.tpl.php:21 +msgid "Last modification:" +msgstr "Последнее изменение:" + +#: ../../../templates/bookmarkcommondescriptionedit.tpl.php:42 +#: ../../../templates/tagcommondescriptionedit.tpl.php:32 +#: ../../../templates/tagedit.tpl.php:18 +msgid "Update" +msgstr "Имзенить" + +#: ../../../templates/bookmarkcommondescriptionedit.tpl.php:43 +#: ../../../templates/editbookmark.tpl.php:98 +#: ../../../templates/tag2tagadd.tpl.php:24 +#: ../../../templates/tag2tagedit.tpl.php:38 +#: ../../../templates/tagcommondescriptionedit.tpl.php:33 +#: ../../../templates/tagedit.tpl.php:19 +#: ../../../templates/tagrename.tpl.php:25 +msgid "Cancel" +msgstr "Отмена" + +#: ../../../templates/bookmarks.tpl.php:26 +#, fuzzy +msgid "Bookmarks on this page are managed by an admin user." +msgstr "Закладки на этой странице управляются администратором." + +#: ../../../templates/bookmarks.tpl.php:51 +#: ../../../templates/bookmarks.tpl.php:52 +#, fuzzy +msgid "Edit the common description of this tag" +msgstr "Изменить описание этого тэга" + +#: ../../../templates/bookmarks.tpl.php:55 +#: ../../../templates/bookmarks.tpl.php:56 +msgid "Edit the common description of this bookmark" +msgstr "Изменить описание этой закладки" + +#: ../../../templates/bookmarks.tpl.php:76 +#: ../../../templates/bookmarks.tpl.php:77 +msgid "Edit your personal description of this tag" +msgstr "Изменить личное описание этой закладки" + +#: ../../../templates/bookmarks.tpl.php:93 +#: ../../../templates/tags.tpl.php:10 +#: ../../../templates/users.tpl.php:8 +msgid "Sort by:" +msgstr "Сортировать по:" + +#: ../../../templates/bookmarks.tpl.php:122 +msgid "Date" +msgstr "Дате" + +#: ../../../templates/bookmarks.tpl.php:129 +msgid "Bookmarks from other users for this tag" +msgstr "Ссылки других пользователей с этим тэгом" + +#: ../../../templates/bookmarks.tpl.php:134 +msgid "Only your bookmarks for this tag" +msgstr "Только Ваши ссылки с этим тэгом" + +#: ../../../templates/bookmarks.tpl.php:157 +#: ../../../templates/bookmarks.tpl.php:163 +msgid "First" +msgstr "Первая" + +#: ../../../templates/bookmarks.tpl.php:158 +#: ../../../templates/bookmarks.tpl.php:164 +msgid "Previous" +msgstr "Предыдущая" + +#: ../../../templates/bookmarks.tpl.php:171 +#: ../../../templates/bookmarks.tpl.php:174 +msgid "Next" +msgstr "Следующая" + +#: ../../../templates/bookmarks.tpl.php:172 +#: ../../../templates/bookmarks.tpl.php:175 +msgid "Last" +msgstr "Последняя" + +#: ../../../templates/bookmarks.tpl.php:185 +#, php-format +msgid "Page %d of %d" +msgstr "Страница%d из %d" + +#: ../../../templates/bookmarks.tpl.php:225 +msgid "Tags:" +msgstr "Тэги:" + +#: ../../../templates/bookmarks.tpl.php:231 +msgid "Edit" +msgstr "Изменить" + +#: ../../../templates/bookmarks.tpl.php:235 +msgid "Last update" +msgstr "Последнее изменение" + +#: ../../../templates/bookmarks.tpl.php:238 +msgid "by" +msgstr " добавлено" + +#: ../../../templates/bookmarks.tpl.php:240 +msgid "you" +msgstr "Вами" + +#: ../../../templates/bookmarks.tpl.php:254 +#, fuzzy, php-format +msgid " and %s1 other%s" +msgstr " и %s1 другие%s" + +#: ../../../templates/bookmarks.tpl.php:257 +#, fuzzy, php-format +msgid " and %2$s%1$s others%3$s" +msgstr " и %2$s%1$s другими%3$s" + +#: ../../../templates/bookmarks.tpl.php:265 +msgid "Copy this bookmark to YOUR bookmarks." +msgstr "Скопировать эту ссылку закладку в ВАШИ закладки" + +#: ../../../templates/bookmarks.tpl.php:265 +msgid "Copy" +msgstr "Копировать" + +#: ../../../templates/bookmarks.tpl.php:284 +msgid "This bookmark is certified by an admin user." +msgstr "Эта закладка заверена администрацией." + +#: ../../../templates/bookmarks.tpl.php:323 +msgid "Private Note on this bookmark" +msgstr "Личная заметка к этой закладке" + +#: ../../../templates/bookmarks.tpl.php:334 +#, fuzzy +msgid "Come back to the top of this page." +msgstr "Вернуться наверх этой страницы." + +#: ../../../templates/bookmarks.tpl.php:334 +#, fuzzy +msgid "Top of the page" +msgstr "Верх страницы" + +#: ../../../templates/bookmarks.tpl.php:340 +msgid "No bookmarks available" +msgstr "Ни одной закладки недоступно" + +#: ../../../templates/bottom.inc.php:7 +msgid "Propulsed by " +msgstr "Propulsed by " + +#: ../../../templates/dynamictags.inc.php:47 +#: ../../../templates/sidebar.block.common.php:19 +#: ../../../templates/sidebar.block.popular.php:34 +#: ../../../templates/sidebar.block.recent.php:29 +#: ../../../templates/tags.tpl.php:19 +msgid "bookmark" +msgid_plural "bookmarks" +msgstr[0] "закладка" +msgstr[1] "закладки" + +#: ../../../templates/dynamictags.inc.php:131 +msgid "Popular Tags From All Users" +msgstr "Популярные тэги всех пользователей" + +#: ../../../templates/editbookmark.tpl.php:33 +msgid "Address" +msgstr "Адрес" + +#: ../../../templates/editbookmark.tpl.php:35 +#: ../../../templates/editbookmark.tpl.php:40 +#: ../../../templates/editprofile.tpl.php:31 +#: ../../../templates/tagrename.tpl.php:14 +#: ../../../templates/tagrename.tpl.php:19 +#, fuzzy +msgid "Required" +msgstr "Обязательно" + +#: ../../../templates/editbookmark.tpl.php:45 +msgid "Add Note" +msgstr "Добавить заметку" + +#: ../../../templates/editbookmark.tpl.php:48 +#, fuzzy +msgid "You can use anchors to delimite attributes. for example: [publisher]blah[/publisher] " +msgstr "Вы можете использовать \"анкоры\" чтобы разделать атрибуты, например: [publisher]blah[/publisher] " + +#: ../../../templates/editbookmark.tpl.php:51 +#, fuzzy +msgid "Suggested anchors: " +msgstr "Предлагаемые анкоры: " + +#: ../../../templates/editbookmark.tpl.php:63 +msgid "Private Note" +msgstr "Личная заметка" + +#: ../../../templates/editbookmark.tpl.php:65 +msgid "Just visible by you and your contacts." +msgstr "Видимо только для Вас и Ваших контактов." + +#: ../../../templates/editbookmark.tpl.php:73 +msgid "Comma-separated" +msgstr "Разделенный запятыми" + +#: ../../../templates/editbookmark.tpl.php:77 +#: ../../../templates/tag2tagadd.tpl.php:9 +msgid "Note: use \">\" to include one tag in another. e.g.: europe>france>paris" +msgstr "Внимание: используйте \">\" чтобы включить один тэг в другой. например: европа>россия>москва" + +#: ../../../templates/editbookmark.tpl.php:81 +#: ../../../templates/tag2tagadd.tpl.php:8 +msgid "Note: use \"=\" to make synonym two tags. e.g.: france=frenchcountry" +msgstr "Внимание: используйте \"=\" чтобы сделать два тэга синонимами. например: россия=рф" + +#: ../../../templates/editbookmark.tpl.php:84 +#: ../../../templates/importDelicious.tpl.php:15 +#: ../../../templates/importNetscape.tpl.php:16 +msgid "Privacy" +msgstr "Конфиденциальность" + +#: ../../../templates/editbookmark.tpl.php:87 +#: ../../../templates/importDelicious.tpl.php:18 +#: ../../../templates/importNetscape.tpl.php:19 +msgid "Public" +msgstr "Публичный" + +#: ../../../templates/editbookmark.tpl.php:88 +msgid "Shared with Watch List" +msgstr "Shared with Watchlist" + +#: ../../../templates/editbookmark.tpl.php:89 +#: ../../../templates/importDelicious.tpl.php:20 +#: ../../../templates/importNetscape.tpl.php:21 +msgid "Private" +msgstr "Личный" + +#: ../../../templates/editbookmark.tpl.php:102 +msgid "Delete Bookmark" +msgstr "Удалить закладку" + +#: ../../../templates/editbookmark.tpl.php:107 +msgid "edit common description" +msgstr "изменит описание" + +#: ../../../templates/editbookmark.tpl.php:134 +#, fuzzy +msgid "Bookmarklet" +msgstr "Закладочник" + +#: ../../../templates/editbookmark.tpl.php:140 +#, php-format +msgid "Click one of the following bookmarklets to add a button you can click whenever you want to add the page you are on to %s" +msgstr "Кликните на один из букмарклетов чтобы добавить кнопку, на которую Вы можете нажать в любой момент когда захотите добавить страницу на которой находитесь в %s" + +#: ../../../templates/editbookmark.tpl.php:144 +#, fuzzy, php-format +msgid "Drag one of the following bookmarklets to your browser's bookmarks and click it whenever you want to add the page you are on to %s" +msgstr "Перетяните мышкой bookmarklets в закладки Вашего браузера и нажмите на него, в любой момент когда захотите добавить страницу на которой находитесь в %s" + +#: ../../../templates/editbookmark.tpl.php:157 +#: ../../../templates/editbookmark.tpl.php:162 +#, php-format +msgid "Post to %s" +msgstr "Добавить в %s" + +#: ../../../templates/editbookmark.tpl.php:158 +#: ../../../templates/editbookmark.tpl.php:163 +#, php-format +msgid "Post to %s (Pop-up)" +msgstr "Добавить в %s (pop-up)" + +#: ../../../templates/editbookmark.tpl.php:168 +#: ../../../templates/importDelicious.tpl.php:26 +#: ../../../templates/importNetscape.tpl.php:27 +#: ../../../templates/importStructure.tpl.php:16 +msgid "Import" +msgstr "Импорт" + +#: ../../../templates/editbookmark.tpl.php:170 +msgid "Import bookmarks from bookmark file" +msgstr "Импортировать закладки из файла закладок" + +#: ../../../templates/editbookmark.tpl.php:170 +msgid "Internet Explorer, Mozilla Firefox and Netscape" +msgstr "Internet Explorer, Mozilla Firefox и Netscape" + +#: ../../../templates/editbookmark.tpl.php:171 +msgid "Import bookmarks from del.icio.us" +msgstr "Импортировать закладки из del.icio.us" + +#: ../../../templates/editprofile.tpl.php:10 +msgid "Account Details" +msgstr "Данные аккаунта" + +#: ../../../templates/editprofile.tpl.php:14 +#: ../../../templates/login.tpl.php:15 +#: ../../../templates/password.tpl.php:10 +#: ../../../templates/profile.tpl.php:6 +#: ../../../templates/register.tpl.php:16 +msgid "Username" +msgstr "Имя пользователя" + +#: ../../../templates/editprofile.tpl.php:19 +msgid "New Password" +msgstr "Новый пароль" + +#: ../../../templates/editprofile.tpl.php:24 +msgid "Confirm Password" +msgstr "Подтвердите пароль" + +#: ../../../templates/editprofile.tpl.php:29 +#: ../../../templates/password.tpl.php:14 +#: ../../../templates/register.tpl.php:26 +msgid "E-mail" +msgstr "E-mail" + +#: ../../../templates/editprofile.tpl.php:35 +msgid "Personal Details" +msgstr "Личные данные" + +#: ../../../templates/editprofile.tpl.php:39 +#: ../../../templates/profile.tpl.php:17 +msgid "Name" +msgstr "Имя" + +#: ../../../templates/editprofile.tpl.php:43 +#: ../../../templates/profile.tpl.php:23 +msgid "Homepage" +msgstr "Домашняя страница" + +#: ../../../templates/editprofile.tpl.php:55 +#: ../../../templates/sidebar.block.tagactions.php:17 +#: ../../../templates/sidebar.block.watchstatus.php:18 +msgid "Actions" +msgstr "Действия" + +#: ../../../templates/editprofile.tpl.php:58 +msgid "Export bookmarks" +msgstr "Экспорт закладок" + +#: ../../../templates/editprofile.tpl.php:60 +msgid "HTML file (for browsers)" +msgstr "HTML файл (для браузеров)" + +#: ../../../templates/editprofile.tpl.php:61 +msgid "XML file (like del.icio.us)" +msgstr "XML файл (как del.icio.us)" + +#: ../../../templates/editprofile.tpl.php:62 +#, fuzzy +msgid "CSV file (for spreadsheet tools)" +msgstr "CSV файл (для табличных процессоров)" + +#: ../../../templates/error.404.tpl.php:5 +msgid "Not Found" +msgstr "Не найдено" + +#: ../../../templates/error.404.tpl.php:6 +msgid "The requested URL was not found on this server" +msgstr "Запрашиваемый адрес не найден на сервере" + +#: ../../../templates/error.500.tpl.php:5 +msgid "General server error" +msgstr "Ошибка сервера" + +#: ../../../templates/error.500.tpl.php:6 +msgid "The requested URL could not be processed" +msgstr "Запрашиваемый адрес не может быть обработан" + +#: ../../../templates/importDelicious.tpl.php:19 +#: ../../../templates/importNetscape.tpl.php:20 +msgid "Shared with Watchlist" +msgstr "Открыть для листа наблюдения" + +#: ../../../templates/importDelicious.tpl.php:31 +#: ../../../templates/importNetscape.tpl.php:32 +#: ../../../templates/importStructure.tpl.php:21 +msgid "Instructions" +msgstr "Инструкции" + +#: ../../../templates/importDelicious.tpl.php:33 +msgid "Log in to the export page at del.icio.us" +msgstr "Войдите на страницу экспорта на del.icio.us" + +#: ../../../templates/importDelicious.tpl.php:34 +msgid "Save the resulting XML file to your computer" +msgstr "Сохраните полученныйXML файл на Ваш компьютер" + +#: ../../../templates/importDelicious.tpl.php:35 +msgid "Click Browse... to find this file on your computer. The maximum size the file can be is 1MB" +msgstr "Yf;vbnt Просмотр... чтобы выбрать файл на Вашем компьютере. Максимальный размер файла - 1MB" + +#: ../../../templates/importDelicious.tpl.php:36 +#: ../../../templates/importNetscape.tpl.php:43 +msgid "Select the default privacy setting for your imported bookmarks" +msgstr "Выберете уровень доступа, который будет применяться по умолчанию к импортируемый закладкам" + +#: ../../../templates/importDelicious.tpl.php:37 +#: ../../../templates/importNetscape.tpl.php:44 +msgid "Click Import to start importing the bookmarks; it may take a minute" +msgstr "Нажмите Импорт для начала импорта закладок; это может занять минуту" + +#: ../../../templates/importNetscape.tpl.php:35 +msgid "Export your bookmarks from your browser to a file" +msgstr "Экспортировать Ваши закладки из браузера в файл" + +#: ../../../templates/importNetscape.tpl.php:37 +msgid "Internet Explorer: File > Import and Export... > Export Favorites" +msgstr "Internet Explorer: File > Import and Export... > Export Favorites" + +#: ../../../templates/importNetscape.tpl.php:38 +msgid "Mozilla Firefox: Bookmarks > Manage Bookmarks... > File > Export..." +msgstr "Mozilla Firefox: Bookmarks > Manage Bookmarks... > File > Export..." + +#: ../../../templates/importNetscape.tpl.php:39 +msgid "Netscape: Bookmarks > Manage Bookmarks... > Tools > Export..." +msgstr "Netscape: Bookmarks > Manage Bookmarks... > Tools > Export..." + +#: ../../../templates/importNetscape.tpl.php:42 +msgid "Click Browse... to find the saved bookmark file on your computer. The maximum size the file can be is 1MB" +msgstr "Нажмите Просмотр... чтобы выбрать сохраненный файл закладок на Вашем компьютере. Максимальный размер файла - 1MB" + +#: ../../../templates/importStructure.tpl.php:24 +#, fuzzy +msgid "Create your structure into a simple text file and following this model:" +msgstr "Создайте структуру в простом текстовом файле используя эту модель:" + +#: ../../../templates/importStructure.tpl.php:35 +#, fuzzy +msgid "Then import the file. The tags and their relations will be added to your profile." +msgstr "Затем импортируйте файл. Тэги и их отношения будут добавлены в Ваш профиль." + +#: ../../../templates/login.tpl.php:20 +#: ../../../templates/register.tpl.php:21 +msgid "Password" +msgstr "Пароль" + +#: ../../../templates/login.tpl.php:22 +msgid "Don't ask for my password for 2 weeks" +msgstr "Не запрашивать мой пароль 2 недели" + +#: ../../../templates/login.tpl.php:30 +msgid "Forgotten your password?" +msgstr "Забыли пароль?" + +#: ../../../templates/password.tpl.php:5 +#, php-format +msgid "If you have forgotten your password, %s can generate a new one. Enter the username and e-mail address of your account into the form below and we will e-mail your new password to you." +msgstr "Если Вы забыли пароль, %s может создать новый. Введите имя пользователя и адрес e-mail Вашего аккаунта в форме ниже и мы вышлем Вам новый пароль." + +#: ../../../templates/password.tpl.php:19 +msgid "Generate Password" +msgstr "Сгенерировать пароль" + +#: ../../../templates/profile.tpl.php:11 +msgid "Email" +msgstr "Email" + +#: ../../../templates/profile.tpl.php:28 +msgid "Member Since" +msgstr "Участник с" + +#: ../../../templates/profile.tpl.php:40 +#: ../../../templates/sidebar.block.watchlist.php:30 +msgid "Watching" +msgstr "Watching" + +#: ../../../templates/profile.tpl.php:55 +#: ../../../templates/sidebar.block.watchlist.php:52 +msgid "Watched By" +msgstr "Наблюдается" + +#: ../../../templates/profile.tpl.php:68 +#: ../../../templates/toolbar.inc.php:9 +msgid "Bookmarks" +msgstr "Закладки" + +#: ../../../templates/profile.tpl.php:69 +msgid "Go to bookmarks" +msgstr "Перейти к закладкам" + +#: ../../../templates/register.tpl.php:11 +#, fuzzy, php-format +msgid "Sign up here to create a free %s account. All the information requested below is required" +msgstr "Зарегистрируйтесь здесь, чтобы создать бесплатный %s аккаунт. Вся поля обязательны для заполнения" + +#: ../../../templates/register.tpl.php:18 +msgid " at least 5 characters, alphanumeric (no spaces, no dots or other special ones)" +msgstr " как минимум 5 символов, буквенно-цифровой (без пробелов, без точек или других спецсимволов)" + +#: ../../../templates/register.tpl.php:28 +msgid " to send you your password if you forget it" +msgstr " чтобы выслать Вам Вамш пароль, если Вы его забудете" + +#: ../../../templates/register.tpl.php:33 +#, fuzzy +msgid "Antispam question" +msgstr "Антиспам вопрос" + +#: ../../../templates/sidebar.block.linked.php:51 +#, fuzzy +msgid "Linked Tags" +msgstr "Связанные тэги" + +#: ../../../templates/sidebar.block.linked.php:62 +#: ../../../templates/sidebar.block.menu.php:46 +msgid "Add new link" +msgstr "Добавить новую ссылку" + +#: ../../../templates/sidebar.block.linked.php:63 +#: ../../../templates/sidebar.block.menu.php:47 +msgid "Delete link" +msgstr "Удалить ссылку" + +#: ../../../templates/sidebar.block.menu.php:35 +#, php-format +msgid "Tags included into the tag '%s'" +msgstr "Тэги включенные в тэг '%s'" + +#: ../../../templates/sidebar.block.menu.php:35 +msgid "Menu Tags" +msgstr "Меню тэгов" + +#: ../../../templates/sidebar.block.menu.php:68 +msgid "See all your tags" +msgstr "Просмотреть все свои тэги" + +#: ../../../templates/sidebar.block.menu.php:68 +msgid "all your tags" +msgstr "все Ваши тэги" + +#: ../../../templates/sidebar.block.menu.php:70 +msgid "See all tags from this user" +msgstr "Просмотреть все тэги этого пользователя" + +#: ../../../templates/sidebar.block.menu.php:70 +msgid "all tags from this user" +msgstr "все тэги этого пользователя" + +#: ../../../templates/sidebar.block.menu.php:74 +msgid "See popular tags" +msgstr "Просмотреть популярные тэги" + +#: ../../../templates/sidebar.block.menu2.php:25 +#, fuzzy +msgid "Featured Menu Tags" +msgstr "Рекомендуемые Тэги" + +#: ../../../templates/sidebar.block.menu2.php:29 +#, fuzzy +msgid "This menu is composed of keywords (tags) organized by admins." +msgstr "Это меню состоит из ключевых слов (тэгов) управляемых администраицей." + +#: ../../../templates/sidebar.block.recent.php:18 +msgid "Recent Tags" +msgstr "Последние Тэги" + +#: ../../../templates/sidebar.block.related.php:26 +msgid "Related Tags" +msgstr "Связанные Тэги" + +#: ../../../templates/sidebar.block.search.php:15 +#, fuzzy +msgid "Last Searches" +msgstr "Что искали недавно" + +#: ../../../templates/sidebar.block.search.php:24 +msgid "Number of bookmarks for this query" +msgstr "Количество закладок для этого запроса" + +#: ../../../templates/sidebar.block.tagactions.php:28 +msgid "Create a link to another tag" +msgstr "Создать ссылку на другой тэг" + +#: ../../../templates/sidebar.block.users.php:14 +msgid "New Users" +msgstr "Новые Пользователи" + +#: ../../../templates/sidebar.block.users.php:23 +#: ../../../templates/users.tpl.php:17 +msgid "bookmarks" +msgstr "закладки" + +#: ../../../templates/sidebar.block.users.php:30 +msgid "See all users" +msgstr "Просмотреть всех пользователей" + +#: ../../../templates/sidebar.block.users.php:30 +msgid "All users" +msgstr "Все пользователи" + +#: ../../../templates/sidebar.block.watchlist.php:19 +#, fuzzy +msgid "Close contacts are mutual contacts" +msgstr "Близкие контакты взаимных контактов" + +#: ../../../templates/sidebar.block.watchlist.php:19 +msgid "Close contacts" +msgstr "Близкие контакты" + +#: ../../../templates/sidebar.block.watchlist.php:36 +msgid "Add a contact..." +msgstr "Добавить контакт..." + +#: ../../../templates/sidebar.block.watchlist.php:36 +msgid "Type a username to add it to your contacts." +msgstr "Введите имя пользователя чтобы добавить его в контакты." + +#: ../../../templates/sidebar.block.watchlist.php:44 +msgid "Remove this contact" +msgstr "Удалить этот контакт" + +#: ../../../templates/sidebar.block.watchstatus.php:11 +msgid "Remove from Watchlist" +msgstr "Удалить из списка наблюдения" + +#: ../../../templates/sidebar.block.watchstatus.php:13 +msgid "Add to Watchlist" +msgstr "Добавить в список наблюдения" + +#: ../../../templates/sidebar.linkedtags.inc.php:18 +msgid "Edit link" +msgstr "Изменить ссылку" + +#: ../../../templates/sidebar.linkedtags.inc.php:47 +msgid "Synonyms:" +msgstr "Синонимы:" + +#: ../../../templates/tag2tagadd.tpl.php:12 +msgid "Create new link:" +msgstr "Создать новую ссылку:" + +#: ../../../templates/tag2tagadd.tpl.php:19 +#, php-format +msgid "Note: include a tag into '%s' tag (e.g. %s>countries) display the tag into the menu box" +msgstr "Внимание: включение тэга в '%s' тэг (например: %s>страны) выведет тэг в списке меню" + +#: ../../../templates/tag2tagadd.tpl.php:23 +#: ../../../templates/tag2tagedit.tpl.php:37 +msgid "Create" +msgstr "Создать" + +#: ../../../templates/tag2tagadd.tpl.php:35 +#: ../../../templates/tag2tagdelete.tpl.php:27 +#: ../../../templates/tag2tagedit.tpl.php:51 +msgid "Existing links:" +msgstr "Существующие ссылки:" + +#: ../../../templates/tag2tagadd.tpl.php:53 +#: ../../../templates/tag2tagdelete.tpl.php:45 +#: ../../../templates/tag2tagedit.tpl.php:69 +msgid "No links" +msgstr "Ссылок нет" + +#: ../../../templates/tag2tagedit.tpl.php:6 +msgid "Delete the link" +msgstr "Удалить ссылку" + +#: ../../../templates/tag2tagedit.tpl.php:29 +msgid "Create new link" +msgstr "Создать новую ссылку" + +#: ../../../templates/tagrename.tpl.php:12 +msgid "Old" +msgstr "Старый" + +#: ../../../templates/tagrename.tpl.php:17 +msgid "New" +msgstr "Новый" + +#: ../../../templates/tagrename.tpl.php:24 +msgid "Rename" +msgstr "Переименовать" + +#: ../../../templates/tags.tpl.php:11 +#: ../../../templates/users.tpl.php:9 +msgid "Alphabet" +msgstr "Алфавиту" + +#: ../../../templates/tags.tpl.php:12 +#: ../../../templates/users.tpl.php:10 +msgid "Popularity" +msgstr "Популярности" + +#: ../../../templates/toolbar.inc.php:8 +#: ../../../templates/toolbar.inc.php:26 +msgid "Home" +msgstr "Домой" + +#: ../../../templates/toolbar.inc.php:14 +msgid "Log Out" +msgstr "Выйти" + +#: ../../../templates/toolbar.inc.php:17 +msgid "Admin" +msgstr "Админ" + +#: ../../../templates/top.inc.php:51 +msgid "Admins, your installation is in \"Debug Mode\" ($debugMode = true). To go in \"Normal Mode\" and hide debugging messages, change $debugMode to false into config.inc.php." +msgstr "" + +#: ../../../templates/users.tpl.php:17 +msgid "profile" +msgstr "Профиль" + +#: ../../../templates/users.tpl.php:17 +msgid "created in" +msgstr "создано в" + From 1b8977f23abc7045504bb1c91233decfb9016f49 Mon Sep 17 00:00:00 2001 From: cweiske Date: Mon, 3 May 2010 06:25:05 +0000 Subject: [PATCH 56/63] typo git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@707 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/locales/en_GB/LC_MESSAGES/messages.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/locales/en_GB/LC_MESSAGES/messages.po b/data/locales/en_GB/LC_MESSAGES/messages.po index 1bac385..0deecb3 100644 --- a/data/locales/en_GB/LC_MESSAGES/messages.po +++ b/data/locales/en_GB/LC_MESSAGES/messages.po @@ -1,4 +1,4 @@ -# Scuttle en-GB Translation +# SemanticScuttle en-GB Translation # Copyright (C) 2005 - 2009 SemanticScuttle project # This file is distributed under the same license as the SemanticScuttle package. # Ogee From b98ba3e0bdf481f5972743d39425998c3851d840 Mon Sep 17 00:00:00 2001 From: cweiske Date: Mon, 3 May 2010 06:25:31 +0000 Subject: [PATCH 57/63] Revert "Vietnamese translation" - was accidentially put into fr_FR This reverts commit d8dc6eb9e0fc4289fa3e43ddbad9e6699b728dbc. git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@708 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/locales/fr_FR/LC_MESSAGES/messages.mo | Bin 30931 -> 27267 bytes data/locales/fr_FR/LC_MESSAGES/messages.po | 618 ++++++++++----------- 2 files changed, 309 insertions(+), 309 deletions(-) diff --git a/data/locales/fr_FR/LC_MESSAGES/messages.mo b/data/locales/fr_FR/LC_MESSAGES/messages.mo index afc69dc8b9bf273c8a6a1f40ad4521159d5b40b5..392adf5ffe635dc3ce6dfd11bb49e91e6606a039 100644 GIT binary patch literal 27267 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 DuoS*3 literal 30931 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 diff --git a/data/locales/fr_FR/LC_MESSAGES/messages.po b/data/locales/fr_FR/LC_MESSAGES/messages.po index 114521e..396c85e 100644 --- a/data/locales/fr_FR/LC_MESSAGES/messages.po +++ b/data/locales/fr_FR/LC_MESSAGES/messages.po @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: Scuttle\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-11-16 20:55+0100\n" -"PO-Revision-Date: 2009-11-18 15:42+0100\n" -"Last-Translator: Nguyen Thi Hong Thai \n" +"PO-Revision-Date: 2009-11-16 21:14+0100\n" +"Last-Translator: BenjaminHKB \n" "Language-Team: fr-FR \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" @@ -21,71 +21,71 @@ msgstr "" #: src/SemanticScuttle/functions.php:163 msgid "message_die() was called multiple times." -msgstr "message_die() bị gọi nhiều lần." +msgstr "message_die() was called multiple times. ?" #: src/SemanticScuttle/functions.php:175 msgid "SQL Error" -msgstr "Lỗi cấu trúc truy vấn" +msgstr "Erreur SQL" #: src/SemanticScuttle/functions.php:181 msgid "Line" -msgstr "mạng" +msgstr "Ligne" #: src/SemanticScuttle/functions.php:181 #: data/templates/importDelicious.tpl.php:8 #: data/templates/importNetscape.tpl.php:9 #: data/templates/importStructure.tpl.php:10 msgid "File" -msgstr "File" +msgstr "Fichier" #: src/SemanticScuttle/functions.php:189 msgid "Information" -msgstr "Thông tin" +msgstr "Information" #: src/SemanticScuttle/functions.php:194 msgid "Critical Information" -msgstr "Thông tin nguy cấp" +msgstr "Information critique." #: src/SemanticScuttle/functions.php:199 msgid "An error occured" -msgstr "Một lỗi đã xảy ra" +msgstr "Une erreur s'est produite." #: src/SemanticScuttle/functions.php:202 msgid "General Error" -msgstr "Lỗi thông thường" +msgstr "Erreur générale." #: src/SemanticScuttle/functions.php:210 msgid "An critical error occured" -msgstr "Một lỗi nguy cấp đã xảy ra" +msgstr "Une erreur critique s'est produite." #: src/SemanticScuttle/functions.php:213 msgid "Critical Error" -msgstr "Lỗi nguy cấp" +msgstr "Erreur critique." #: src/SemanticScuttle/functions.php:222 msgid "DEBUG MODE" -msgstr "Chế độ gỡ rối" +msgstr "Mode de débogage." #: data/templates/about.tpl.php:6 msgid "Store all your favourite links in one place, accessible from anywhere." -msgstr "Lưu trữtất cả các đường links ở một nơi, có thể truy cập tại mọi nơi" +msgstr "Conservez tous vos signets au même endroit, accessibles de partout. " #: data/templates/about.tpl.php:7 msgid "Share your bookmarks with everyone, with friends on your watchlist or just keep them private." -msgstr "Chia xẻ các trang ghi nhớ của bạn với tất cả mọi ngườii, bạn có thể chia xẻ với bạn bè trong danh sách hoặc giữ cá nhân." +msgstr "Partagez vos signets avec tout le monde, avec vos contacts ou gardez-les pour vous." #: data/templates/about.tpl.php:8 msgid "Tag your bookmarks with as many labels as you want, instead of wrestling with folders." -msgstr "Gắn từ khoá/strong> những trang ghi nhớ của bạn với bất kì tên nào mà bạn muốn mà không phải làm việc với các thư mục" +msgstr "Taggez vos signets avec autant de labels que vous le souhaitez au lieu de les hiérarchiser avec des dossiers." #: data/templates/about.tpl.php:9 msgid "Register now" -msgstr "Đăng kí ngay bây giờ" +msgstr "S'enregistrer maintenant" #: data/templates/about.tpl.php:9 #, php-format msgid " to start using %s!" -msgstr "Bắt đầu sử dụng %s !" +msgstr "pour commencer à employer %s !" #: data/templates/about.tpl.php:12 msgid "Geek Stuff" @@ -93,45 +93,45 @@ msgstr "Pour les Geeks" #: data/templates/about.tpl.php:14 msgid "is licensed under the " -msgstr "phân dưới quyền" +msgstr "est sous licence" #: data/templates/about.tpl.php:14 msgid "you can freely host it on your own web server." -msgstr "Bạn có thể thoải mái cài đặt nó trên Web server của bạn" +msgstr "vous pouvez librement l'installer sur votre serveur Web" #: data/templates/about.tpl.php:15 #, php-format msgid "%1$s supports most of the del.icio.us API. Almost all of the neat tools made for that system can be modified to work with %1$s instead. If you find a tool that won't let you change the API address, ask the creator to add this setting. You never know, they might just do it." -msgstr "%1$s hỗ trợ phần lớn từ'API del.icio.us." +msgstr "%1$s supporte la plupart de l'API del.icio.us." #: data/templates/about.tpl.php:24 msgid "Tips" -msgstr "Mẹo" +msgstr "Astuces" #: data/templates/about.tpl.php:26 msgid "Add search plugin into your browser:" -msgstr "Thêm một nút tìm kiếm vào trong trình duyệt của bạn:" +msgstr "Ajouter un plugin de recherche à votre navigateur :" #: data/templates/about.tpl.php:27 msgid "The secret tag \"system:unfiled\" allows you to find bookmarks without tags." -msgstr "Thẻ bí mật \"system:unfiled\" cho phép bạn tìm thấy những trang ghi nhớ không có thẻ." +msgstr "Le tag secret \"system:unfiled\" vous permet de trouver les signets sans tags." #: data/templates/about.tpl.php:28 msgid "The secret tag \"system:imported\" allows you to find imported bookmarks." -msgstr "Từ khoá bí mật \"system:imported\" cho phép bạn tìm thấy những trang ghi nhớ quan trọng." +msgstr "Le tag secret \"system:imported\" vous permet de trouver les signets importés." #: data/templates/admin.tpl.php:5 msgid "Users management" -msgstr "Quản lí những người dùng" +msgstr "Gestion des utilisateurs" #: data/templates/admin.tpl.php:14 msgid "Public/Shared/Private" -msgstr "Công cộng/Chia xẻ/Cá nhân" +msgstr "Publique/Partagé/Privé" #: data/templates/admin.tpl.php:14 #: data/templates/bookmarks.tpl.php:93 msgid "bookmark(s)" -msgstr "Những trang ghi nhớ" +msgstr "signet(s)" #: data/templates/admin.tpl.php:19 #: data/templates/tag2tagadd.tpl.php:21 @@ -141,30 +141,30 @@ msgstr "Những trang ghi nhớ" #: data/templates/tagdelete.tpl.php:6 #: www/jsScuttle.php:23 msgid "Are you sure?" -msgstr "Bạn có chắc chắn không ?" +msgstr "Etes-vous sûr ?" #: data/templates/admin.tpl.php:19 #: data/templates/bookmarks.tpl.php:251 msgid "Delete" -msgstr "Xoá" +msgstr "Supprimer" #: data/templates/admin.tpl.php:27 msgid "Other actions" -msgstr "Những hành động khác" +msgstr "Autres actions" #: data/templates/admin.tpl.php:29 msgid "Check all URLs (May take some time)" -msgstr "Kiểm tra tất cả đường link (Có thể mất ít thời gian)" +msgstr "Vérifier toutes les URLs (Peut prendre du temps)" #: data/templates/bookmarkcommondescriptionedit.tpl.php:16 msgid "Collaborative description: these fields can be viewed and modified by every users" -msgstr "Sự mô tả cộng tác : những trường này có thể được nhìn thấy và được sửa đổi bởi tất cả những người dùng." +msgstr "Description collaborative : ces champs peuvent être vus et modifiés par tous les utilisateurs." #: data/templates/bookmarkcommondescriptionedit.tpl.php:18 #: data/templates/bookmarks.tpl.php:137 #: data/templates/editbookmark.tpl.php:38 msgid "Title" -msgstr "Tiêu đề" +msgstr "Titre" #: data/templates/bookmarkcommondescriptionedit.tpl.php:23 #: data/templates/editbookmark.tpl.php:44 @@ -173,18 +173,18 @@ msgstr "Tiêu đề" #: data/templates/tagcommondescriptionedit.tpl.php:13 #: data/templates/tagedit.tpl.php:12 msgid "Description" -msgstr "Mô tả" +msgstr "Description" #: data/templates/bookmarkcommondescriptionedit.tpl.php:31 #: data/templates/tagcommondescriptionedit.tpl.php:21 msgid "Last modification:" -msgstr "Những thay đổi cuối:" +msgstr "Dernière modification :" #: data/templates/bookmarkcommondescriptionedit.tpl.php:42 #: data/templates/tagcommondescriptionedit.tpl.php:32 #: data/templates/tagedit.tpl.php:18 msgid "Update" -msgstr "Cập nhật" +msgstr "Mettre à jour" #: data/templates/bookmarkcommondescriptionedit.tpl.php:43 #: data/templates/editbookmark.tpl.php:98 @@ -194,146 +194,146 @@ msgstr "Cập nhật" #: data/templates/tagedit.tpl.php:19 #: data/templates/tagrename.tpl.php:25 msgid "Cancel" -msgstr "Huỷ bỏ" +msgstr "Annuler" #: data/templates/bookmarks-vote-horizontal.inc.tpl.php:24 #, php-format msgid "Voting %d" -msgstr "Sự ủng hộ %d" +msgstr "Vote %d" #: data/templates/bookmarks-vote-horizontal.inc.tpl.php:32 #: data/templates/bookmarks-vote-horizontal.inc.tpl.php:35 msgid "Vote for" -msgstr "Ủng hộ cho" +msgstr "Vote pour" #: data/templates/bookmarks-vote-horizontal.inc.tpl.php:43 #: data/templates/bookmarks-vote-horizontal.inc.tpl.php:46 msgid "Vote against" -msgstr "Không ủng hộ" +msgstr "Vote contre" #: data/templates/bookmarks.tpl.php:26 msgid "Bookmarks on this page are managed by an admin user." -msgstr "Những trang ghi nhớ trên trang này được quản lí bởi một người quản trị." +msgstr "Les signets de cette page sont gérés par un administrateur." #: data/templates/bookmarks.tpl.php:51 #: data/templates/bookmarks.tpl.php:52 msgid "Edit the common description of this tag" -msgstr "Sửa mô tả chung của từ khoá này" +msgstr "Editer la description commune de ce tag" #: data/templates/bookmarks.tpl.php:55 #: data/templates/bookmarks.tpl.php:56 msgid "Edit the common description of this bookmark" -msgstr "Sửa mô tả chung của trang ghi nhớ này" +msgstr "Editer la description commune de ce signet" #: data/templates/bookmarks.tpl.php:76 #: data/templates/bookmarks.tpl.php:77 msgid "Edit your personal description of this tag" -msgstr "Sửa mô tả cá nhân của bạn của thẻ này" +msgstr "Editer votre description personnelle de ce tag" #: data/templates/bookmarks.tpl.php:93 #: data/templates/tags.tpl.php:10 #: data/templates/users.tpl.php:8 msgid "Sort by:" -msgstr "Sắp xếp bởi :" +msgstr "Classer par :" #: data/templates/bookmarks.tpl.php:135 msgid "Date" -msgstr "Ngày" +msgstr "Date" #: data/templates/bookmarks.tpl.php:140 msgid "Voting" -msgstr "Sự bầu cử" +msgstr "Vote" #: data/templates/bookmarks.tpl.php:149 msgid "Bookmarks from other users for this tag" -msgstr "Ghi nhớ trang từ những người dùng khác cho thẻ này" +msgstr "Signets des autres utilisateurs pour ce tag" #: data/templates/bookmarks.tpl.php:154 msgid "Only your bookmarks for this tag" -msgstr "Chỉ có những trang ghi nhớ của bạn" +msgstr "Uniquement vos signets pour ce tag" #: data/templates/bookmarks.tpl.php:177 #: data/templates/bookmarks.tpl.php:183 msgid "First" -msgstr "Đầu tiên" +msgstr "Première" #: data/templates/bookmarks.tpl.php:178 #: data/templates/bookmarks.tpl.php:184 msgid "Previous" -msgstr "Trước" +msgstr "Précédent" #: data/templates/bookmarks.tpl.php:191 #: data/templates/bookmarks.tpl.php:194 msgid "Next" -msgstr "Sau" +msgstr "Suivant" #: data/templates/bookmarks.tpl.php:192 #: data/templates/bookmarks.tpl.php:195 msgid "Last" -msgstr "Cuối cùng" +msgstr "Dernière" #: data/templates/bookmarks.tpl.php:205 #, php-format msgid "Page %d of %d" -msgstr "Trang %d của %d" +msgstr "Page %d de %d" #: data/templates/bookmarks.tpl.php:245 msgid "Tags:" -msgstr "Những từ khoá:" +msgstr "Tags:" #: data/templates/bookmarks.tpl.php:251 msgid "Edit" -msgstr "Sửa" +msgstr "Editer" #: data/templates/bookmarks.tpl.php:255 msgid "Last update" -msgstr "Lần cập nhật cuối" +msgstr "Date de dernière mise à jour" #: data/templates/bookmarks.tpl.php:258 msgid "by" -msgstr "bởi" +msgstr "par" #: data/templates/bookmarks.tpl.php:260 msgid "you" -msgstr "bạn" +msgstr "vous" #: data/templates/bookmarks.tpl.php:274 #, php-format msgid " and %s1 other%s" -msgstr "và %s1 khác%s" +msgstr " et %s1 autre%s" #: data/templates/bookmarks.tpl.php:277 #, php-format msgid " and %2$s%1$s others%3$s" -msgstr " và %2$s%1$s những cái khác%3$s" +msgstr " et %2$s%1$s autres%3$s" #: data/templates/bookmarks.tpl.php:288 msgid "Copy this bookmark to YOUR bookmarks." -msgstr "Copy trang ghi nhớ này vào những trang ghi nhớ của bạn." +msgstr "Copier ce signet dans VOS signets." #: data/templates/bookmarks.tpl.php:289 msgid "Copy" -msgstr "Copy" +msgstr "Copier" #: data/templates/bookmarks.tpl.php:309 msgid "This bookmark is certified by an admin user." -msgstr "Trang ghi nhớ này được bảo đảm bởi một người quản trị." +msgstr "Ce signet est certifié par un administrateur." #: data/templates/bookmarks.tpl.php:351 msgid "Private Note on this bookmark" -msgstr "Ghi chú cá nhân trên trang ghi nhớ này" +msgstr "Note privée sur ce signet" #: data/templates/bookmarks.tpl.php:363 msgid "Come back to the top of this page." -msgstr "Quay trở lại đầu trang này." +msgstr "Revenir en haut de cette page." #: data/templates/bookmarks.tpl.php:363 msgid "Top of the page" -msgstr "Đầu trang" +msgstr "Haut de page" #: data/templates/bookmarks.tpl.php:369 msgid "No bookmarks available" -msgstr "Không có trang ghi nhớ nào có sẵn." +msgstr "Pas de signets disponibles." #: data/templates/bottom.inc.php:5 #: data/templates/toolbar.inc.php:15 @@ -341,11 +341,11 @@ msgstr "Không có trang ghi nhớ nào có sẵn." #: www/about.php:23 #: www/about.php:24 msgid "About" -msgstr "Về" +msgstr "À propos" #: data/templates/bottom.inc.php:7 msgid "Propulsed by " -msgstr "Đã đẩy bởi" +msgstr "Propulsé par " #: data/templates/dynamictags.inc.php:47 #: data/templates/sidebar.block.common.php:19 @@ -354,7 +354,7 @@ msgstr "Đã đẩy bởi" #: data/templates/tags.tpl.php:19 msgid "bookmark" msgid_plural "bookmarks" -msgstr[0] "Trang ghi nhớ" +msgstr[0] "signet" msgstr[1] "Signets" #: data/templates/dynamictags.inc.php:128 @@ -365,15 +365,15 @@ msgstr[1] "Signets" #: data/templates/toolbar.inc.php:27 #: www/populartags.php:46 msgid "Popular Tags" -msgstr "Những thẻ phổ biến" +msgstr "Tags populaires" #: data/templates/dynamictags.inc.php:131 msgid "Popular Tags From All Users" -msgstr "Những thẻ phổ biến cho tất cả những người dùng" +msgstr "Tags populaires pour tous les utilisateurs" #: data/templates/editbookmark.tpl.php:33 msgid "Address" -msgstr "Địa chỉ" +msgstr "Adresse" #: data/templates/editbookmark.tpl.php:35 #: data/templates/editbookmark.tpl.php:40 @@ -381,78 +381,78 @@ msgstr "Địa chỉ" #: data/templates/tagrename.tpl.php:14 #: data/templates/tagrename.tpl.php:19 msgid "Required" -msgstr "Yêu cầu" +msgstr "Requis" #: data/templates/editbookmark.tpl.php:45 msgid "Add Note" -msgstr "Thêm vào ghi chú" +msgstr "Ajouter une note" #: data/templates/editbookmark.tpl.php:48 msgid "You can use anchors to delimite attributes. for example: [publisher]blah[/publisher] " -msgstr "Bạn có thể sử dụng những nguồn tin cậy để xác định phạm vi những thuộc tính. Ví dụ : [publisher]blah[/publisher]" +msgstr "Vous pouvez utiliser des balises pour délimiter des attributs. Par exemple : [publisher]blah[/publisher]" #: data/templates/editbookmark.tpl.php:51 msgid "Suggested anchors: " -msgstr "Những gợi ý tin cậy : " +msgstr "Balises suggérées : " #: data/templates/editbookmark.tpl.php:63 msgid "Private Note" -msgstr "Ghi chú cá nhân" +msgstr "Note privée" #: data/templates/editbookmark.tpl.php:65 msgid "Just visible by you and your contacts." -msgstr "Chỉ được xem bới bạn và danh sách liên lạc của bạn" +msgstr "Visible uniquement par vous et vos contacts." #: data/templates/editbookmark.tpl.php:69 #: data/templates/toolbar.inc.php:10 #: www/tags.php:45 #: www/tags.php:67 msgid "Tags" -msgstr "Thẻ" +msgstr "Tags" #: data/templates/editbookmark.tpl.php:73 msgid "Comma-separated" -msgstr "Phân tách bởi những dấu phẩy" +msgstr "Séparés par des virgules" #: data/templates/editbookmark.tpl.php:77 #: data/templates/tag2tagadd.tpl.php:9 msgid "Note: use \">\" to include one tag in another. e.g.: europe>france>paris" -msgstr "Chú ý: sử dụng \">\" để cho một mô tả mối liên hệ giữa các thẻ. Ví dụ: Chau_Au>Phap>paris" +msgstr "Note: utiliser \">\" pour inclure un tag dans un autre. ex: europe>france>paris" #: data/templates/editbookmark.tpl.php:81 #: data/templates/tag2tagadd.tpl.php:8 msgid "Note: use \"=\" to make synonym two tags. e.g.: france=frenchcountry" -msgstr "Chú ý : sử dụng \"=\" để diễn tả hai thẻ tương đương nhau. Ví dụ: europe=eu" +msgstr "Note : utiliser \"=\" pour rendre deux tags synonymes ex: europe=eu" #: data/templates/editbookmark.tpl.php:84 #: data/templates/importDelicious.tpl.php:15 #: data/templates/importNetscape.tpl.php:16 msgid "Privacy" -msgstr "Riêng tư" +msgstr "Accès" #: data/templates/editbookmark.tpl.php:87 #: data/templates/importDelicious.tpl.php:18 #: data/templates/importNetscape.tpl.php:19 msgid "Public" -msgstr "Công cộng" +msgstr "Publique" #: data/templates/editbookmark.tpl.php:88 msgid "Shared with Watch List" -msgstr "Chia xẻ với danh sách liên hệ của tôi" +msgstr "Partagé avec mes contacts" #: data/templates/editbookmark.tpl.php:89 #: data/templates/importDelicious.tpl.php:20 #: data/templates/importNetscape.tpl.php:21 msgid "Private" -msgstr "cá nhân" +msgstr "Privée" #: data/templates/editbookmark.tpl.php:102 msgid "Delete Bookmark" -msgstr "Xoá trang ghi nhớ này" +msgstr "Supprimer le signet" #: data/templates/editbookmark.tpl.php:107 msgid "edit common description" -msgstr "Sửa mô tả chung" +msgstr "éditer la description commune" #: data/templates/editbookmark.tpl.php:134 msgid "Bookmarklet" @@ -461,35 +461,35 @@ msgstr "Bookmarklet" #: data/templates/editbookmark.tpl.php:140 #, php-format msgid "Click one of the following bookmarklets to add a button you can click whenever you want to add the page you are on to %s" -msgstr "Click theo một trong những bookmarklets để thêm một nút, bạn có thể click bất cứ khi nào bạn muốn thêm một trang cho trang hiện tại %s " +msgstr "Déplacez l'un des 'bookmarklet' suivants dans les marques-pages de votre navigateur et cliquez dessus chaque fois que vous souhaitez ajouter un signet pour la page courante dans %s " #: data/templates/editbookmark.tpl.php:144 #, php-format msgid "Drag one of the following bookmarklets to your browser's bookmarks and click it whenever you want to add the page you are on to %s" -msgstr "Click theo một trong những bookmarklets vào trình duyệt bookmark của bạn và click nó bất cứ khi nào bạn muốn thêm một trang cho trang hiện tại %s " +msgstr "Déplacez l'un des 'bookmarklet' suivants dans les marques-pages de votre navigateur et cliquez dessus chaque fois que vous souhaitez ajouter un signet pour la page courante dans %s " #: data/templates/editbookmark.tpl.php:157 #: data/templates/editbookmark.tpl.php:162 #, php-format msgid "Post to %s" -msgstr "Thêm vào %s" +msgstr "Ajouter à %s" #: data/templates/editbookmark.tpl.php:158 #: data/templates/editbookmark.tpl.php:163 #, php-format msgid "Post to %s (Pop-up)" -msgstr "Thêm vào %s (Pop-up)" +msgstr "Ajouter à %s (Pop-up)" #: data/templates/editbookmark.tpl.php:168 #: data/templates/importDelicious.tpl.php:26 #: data/templates/importNetscape.tpl.php:27 #: data/templates/importStructure.tpl.php:16 msgid "Import" -msgstr "Nhập " +msgstr "Importer" #: data/templates/editbookmark.tpl.php:170 msgid "Import bookmarks from bookmark file" -msgstr "Nạp những trang ghi nhớ từ một file " +msgstr "Importer les signets depuis un fichier" #: data/templates/editbookmark.tpl.php:170 msgid "Internet Explorer, Mozilla Firefox and Netscape" @@ -497,11 +497,11 @@ msgstr "Internet Explorer, Mozilla Firefox et Netscape" #: data/templates/editbookmark.tpl.php:171 msgid "Import bookmarks from del.icio.us" -msgstr "Nạp những trang ghi nhớ từ del.icio.us" +msgstr "Importer les signets depuis del.icio.us" #: data/templates/editprofile.tpl.php:10 msgid "Account Details" -msgstr "Tài khoản cụ thể" +msgstr "Détail du compte" #: data/templates/editprofile.tpl.php:14 #: data/templates/login.tpl.php:21 @@ -509,15 +509,15 @@ msgstr "Tài khoản cụ thể" #: data/templates/profile.tpl.php:6 #: data/templates/register.tpl.php:16 msgid "Username" -msgstr "Tên người dùng" +msgstr "Nom d'utilisateur" #: data/templates/editprofile.tpl.php:19 msgid "New Password" -msgstr "Mật khẩu mới" +msgstr "Nouveau mot de passe" #: data/templates/editprofile.tpl.php:24 msgid "Confirm Password" -msgstr "Xác nhận mật khẩu" +msgstr "Confirmer le mot de passe" #: data/templates/editprofile.tpl.php:29 #: data/templates/password.tpl.php:14 @@ -527,153 +527,153 @@ msgstr "E-mail" #: data/templates/editprofile.tpl.php:35 msgid "Personal Details" -msgstr "Chi tiết cá nhân" +msgstr "Détails personnels" #: data/templates/editprofile.tpl.php:39 #: data/templates/profile.tpl.php:17 msgid "Name" -msgstr "Tên" +msgstr "Nom" #: data/templates/editprofile.tpl.php:43 #: data/templates/profile.tpl.php:23 msgid "Homepage" -msgstr "Trang chủ" +msgstr "Page personnelle" #: data/templates/editprofile.tpl.php:52 #: www/edit.php:113 msgid "Save Changes" -msgstr "Lưu lại sự thay đổi" +msgstr "Enregistrer les modifications" #: data/templates/editprofile.tpl.php:55 #: data/templates/sidebar.block.tagactions.php:17 #: data/templates/sidebar.block.watchstatus.php:18 msgid "Actions" -msgstr "Những thao tác" +msgstr "Actions" #: data/templates/editprofile.tpl.php:58 msgid "Export bookmarks" -msgstr "Xuất những trang ghi nhớ" +msgstr "Exporter les signets" #: data/templates/editprofile.tpl.php:60 msgid "HTML file (for browsers)" -msgstr "file HTML (để duyệt)" +msgstr "Fichier HTML (pour navigateurs)" #: data/templates/editprofile.tpl.php:61 msgid "XML file (like del.icio.us)" -msgstr "file XML (như del.icio.us)" +msgstr "Fichier XML (comme del.icio.us)" #: data/templates/editprofile.tpl.php:62 msgid "CSV file (for spreadsheet tools)" -msgstr "file CSV (cho những công cụ lan truyền)" +msgstr "Fichier CSV (pour tableurs)" #: data/templates/error.404.tpl.php:5 msgid "Not Found" -msgstr "Không tìm thấy" +msgstr "Non trouvé" #: data/templates/error.404.tpl.php:6 msgid "The requested URL was not found on this server" -msgstr "Yêu cầu đường link đã không được tìm thấy trên server này." +msgstr "L'URL demandée n'a pas été trouvée sur ce serveur." #: data/templates/error.500.tpl.php:5 msgid "General server error" -msgstr "Lỗi tác độgn từ serveur." +msgstr "Erreur généralisée du serveur." #: data/templates/error.500.tpl.php:6 msgid "The requested URL could not be processed" -msgstr "Yêu cầu đường link không thể tìm thấy trên server này" +msgstr "L'URL demandée n'a pas été trouvée." #: data/templates/importDelicious.tpl.php:19 #: data/templates/importNetscape.tpl.php:20 msgid "Shared with Watchlist" -msgstr "Chia xẻ với danh sách liên lạc" +msgstr "Partagé avec mes contacts" #: data/templates/importDelicious.tpl.php:31 #: data/templates/importNetscape.tpl.php:32 #: data/templates/importStructure.tpl.php:21 msgid "Instructions" -msgstr "Giới thiệu" +msgstr "Instructions" #: data/templates/importDelicious.tpl.php:33 msgid "Log in to the export page at del.icio.us" -msgstr "Đăng nhập vào trang trích xuất từ del.icio.us" +msgstr "Se connecter à la page d'export de del.icio.us" #: data/templates/importDelicious.tpl.php:34 msgid "Save the resulting XML file to your computer" -msgstr "Lưu file kết quả XML trên máy tính của bạn" +msgstr "Enregistrer le fichier XML résultant sur votre ordinateur" #: data/templates/importDelicious.tpl.php:35 msgid "Click Browse... to find this file on your computer. The maximum size the file can be is 1MB" -msgstr "Click Browse... để tìm thấy file trên máy tính của bạn. Kích cỡ tối đa của file không được vượt quá 1 MB" +msgstr "Cliquez sur Parcourir... pour trouver le fichier sur votre ordinateur. La taille maximale du fichier ne peut excèder 1Mo" #: data/templates/importDelicious.tpl.php:36 #: data/templates/importNetscape.tpl.php:43 msgid "Select the default privacy setting for your imported bookmarks" -msgstr "Lựa chọn cài đặt mặc định cho những trang ghi nhớ được nạp vào" +msgstr "Selectionnez la vision par défaut à appliquer à vos signets importés" #: data/templates/importDelicious.tpl.php:37 #: data/templates/importNetscape.tpl.php:44 msgid "Click Import to start importing the bookmarks; it may take a minute" -msgstr "Click vào Importer để bắt đầu nạp những trang ghi nhớ; thao tác này có thể mất vài phút" +msgstr "Cliquez sur Importer pour débuter l'import des signets; cette opération peut prendre quelques minutes" #: data/templates/importNetscape.tpl.php:35 msgid "Export your bookmarks from your browser to a file" -msgstr "Xuất những trang ghi nhớ ra một file từ danh sách duyệt của bạn" +msgstr "Exporter vos signets dans un fichier depuis votre navigateur" #: data/templates/importNetscape.tpl.php:37 msgid "Internet Explorer: File > Import and Export... > Export Favorites" -msgstr "Internet Explorer: File > Nạp và Đưa ra... > Đưa ra những cái được ưa chuộng" +msgstr "Internet Explorer: Ficher > Importer et Exporter... > Exporter les favoris" #: data/templates/importNetscape.tpl.php:38 msgid "Mozilla Firefox: Bookmarks > Manage Bookmarks... > File > Export..." -msgstr "Mozilla Firefox: Những trang đánh dấu >Quản lí những trang được đánh dấu... >File > Đưa rar..." +msgstr "Mozilla Firefox: Marques-pages > Gérer les marques-pages... > Fichier > Exporter..." #: data/templates/importNetscape.tpl.php:39 msgid "Netscape: Bookmarks > Manage Bookmarks... > Tools > Export..." -msgstr "Netscape: Những trang đánh dấu > Quản lí những trang đánh dấu... > Những công cụ > Đưa ra..." +msgstr "Netscape: Marques-pages > Gérer les marques-pages... > Outils > Exporter..." #: data/templates/importNetscape.tpl.php:42 msgid "Click Browse... to find the saved bookmark file on your computer. The maximum size the file can be is 1MB" -msgstr "Click Browse... để tìm thấy file chứa những trang ghi nhớ đã được lưu trên máy tính của bạn. Kích thước tối đa của file không vượt quá 1MB" +msgstr "Cliquez sur Parcourir... pour trouver le fichier sur votre ordinateur. La taille maximale du fichier ne peut excèder 1Mo" #: data/templates/importStructure.tpl.php:24 msgid "Create your structure into a simple text file and following this model:" -msgstr "Tạo cấu trúc của bạn vào một file văn bản đơn giản theo mô hình sau" +msgstr "" #: data/templates/importStructure.tpl.php:35 msgid "Then import the file. The tags and their relations will be added to your profile." -msgstr "Sau khi nạp vào file này. Những thẻ này và mối liên hệ giữa chúng sẽ được thêm vào thông tin của bạn" +msgstr "" #: data/templates/login.tpl.php:13 msgid "Please activate cookies" -msgstr "Hãy kích hoạt việc xác nhận sử dụng dịch vụ" +msgstr "SVP activez les cookies" #: data/templates/login.tpl.php:26 #: data/templates/register.tpl.php:21 msgid "Password" -msgstr "Mật khẩu" +msgstr "Mot de passe" #: data/templates/login.tpl.php:28 msgid "Don't ask for my password for 2 weeks" -msgstr "Đừng hỏi mật khẩu của tôi trong 2 tuần" +msgstr "Ne pas demander mon mot de passe pendant 2 semaines" #: data/templates/login.tpl.php:32 #: data/templates/toolbar.inc.php:29 #: www/login.php:57 msgid "Log In" -msgstr "Đăng nhập" +msgstr "Se connecter" #: data/templates/login.tpl.php:36 msgid "Forgotten your password?" -msgstr "Có phải bạn đã quên mật khẩu ?" +msgstr "Avez-vous oublié votre mot de passe ?" #: data/templates/password.tpl.php:5 #, php-format msgid "If you have forgotten your password, %s can generate a new one. Enter the username and e-mail address of your account into the form below and we will e-mail your new password to you." -msgstr "Nếu bạn đã quên mật khẩu, %s có thể tạo ra một mật khẩu mới. Nhập vào tên đăng nhập và địa chỉ email của bạn trong mẫu dưới đây và chúng tôi sẽ gửi cho bạn một mật khẩu mới." +msgstr "Si vous avez oublié votre mot de passe, %s peut en générer un nouveau. Entrez le nom d'utilisateur et l'adresse email de votre compte dans le formulaire ci-dessous et nous vous enverrons un nouveau mot de passe." #: data/templates/password.tpl.php:19 msgid "Generate Password" -msgstr "Phát sinh một mật khẩu" +msgstr "Générer un mot de passe" #: data/templates/profile.tpl.php:11 msgid "Email" @@ -681,359 +681,359 @@ msgstr "E-mail" #: data/templates/profile.tpl.php:28 msgid "Member Since" -msgstr "Thành viên trước đây" +msgstr "Membre depuis" #: data/templates/profile.tpl.php:40 #: data/templates/sidebar.block.watchlist.php:30 msgid "Watching" -msgstr "Những danh sách liên lạc của tôi" +msgstr "Mes contacts" #: data/templates/profile.tpl.php:55 #: data/templates/sidebar.block.watchlist.php:52 msgid "Watched By" -msgstr "Được xem bởi" +msgstr "Dans les contacts de" #: data/templates/profile.tpl.php:68 #: data/templates/toolbar.inc.php:9 msgid "Bookmarks" -msgstr "Những trang ghi nhớ" +msgstr "Signets" #: data/templates/profile.tpl.php:69 msgid "Go to bookmarks" -msgstr "Vào những trang ghi nhớ" +msgstr "Aller aux signets" #: data/templates/register.tpl.php:11 #, php-format msgid "Sign up here to create a free %s account. All the information requested below is required" -msgstr "Bạn đăng kí ở đây để tạo ra một tài khoản miến phí %s. Tất cả những thông tin yêu cầu dưới đây là cần thiết." +msgstr "Enregistrez-vous ici pour créer un compte gratuit %s. Toutes les informations requises ci-dessous sont nécessaires." #: data/templates/register.tpl.php:18 msgid " at least 5 characters, alphanumeric (no spaces, no dots or other special ones)" -msgstr " ít nhất 5 kí tự, chứa chữ và số (không khoảng trống, không dấu chấm hoặc kí tự đặc biệt khác)" +msgstr " au moins 5 caractères, alphanumériques (pas d'espaces, pas de points ou autre caractère spécial)" #: data/templates/register.tpl.php:28 msgid " to send you your password if you forget it" -msgstr "để gửi cho bạn mật khẩu của bạn nếu bạn quên nó" +msgstr " pour vous envoyer votre mot de passe en cas de perte" #: data/templates/register.tpl.php:33 msgid "Antispam question" -msgstr "Câu hỏi chống thư rác" +msgstr "Question antispam" #: data/templates/register.tpl.php:41 #: data/templates/toolbar.inc.php:31 #: www/register.php:83 msgid "Register" -msgstr "Đăng kí" +msgstr "S'enregistrer" #: data/templates/search.menu.php:27 msgid "Search..." -msgstr "Tìm kiếm..." +msgstr "Chercher..." #: data/templates/search.menu.php:28 msgid "in" -msgstr "trong" +msgstr "dans" #: data/templates/search.menu.php:34 msgid "this user's bookmarks" -msgstr "những trang ghi nhớ của người dùng" +msgstr "les signets de cet utilisateur" #: data/templates/search.menu.php:39 msgid "my bookmarks" -msgstr "những trang ghi nhớ của tôi" +msgstr "mes signets" #: data/templates/search.menu.php:40 msgid "my watchlist" -msgstr "danh sách liên lạc của tôi" +msgstr "mes contacts" #: data/templates/search.menu.php:44 msgid "all bookmarks" -msgstr "tất cả những trang được ghi nhớ " +msgstr "tous les signets" #: data/templates/search.menu.php:54 msgid "Search" -msgstr "Tìm kiếm" +msgstr "Chercher" #: data/templates/sidebar.block.linked.php:51 msgid "Linked Tags" -msgstr "Liên kết những từ khoá" +msgstr "Tags structurés" #: data/templates/sidebar.block.linked.php:62 #: data/templates/sidebar.block.menu.php:46 msgid "Add new link" -msgstr "Tạo một liên kết" +msgstr "Créer un lien" #: data/templates/sidebar.block.linked.php:63 #: data/templates/sidebar.block.menu.php:47 msgid "Delete link" -msgstr "Xoá một liên kết" +msgstr "Supprimer un lien" #: data/templates/sidebar.block.menu.php:35 #, php-format msgid "Tags included into the tag '%s'" -msgstr "Những từ khoá chứa trong từ khoá '%s'" +msgstr "Tags inclus dans le tag '%s'" #: data/templates/sidebar.block.menu.php:35 msgid "Menu Tags" -msgstr "Danh sách từ khoá" +msgstr "Tags Menu" #: data/templates/sidebar.block.menu.php:68 msgid "See all your tags" -msgstr "Nhìn thấy tất cả thẻ của bạn" +msgstr "Voir tous vos tags" #: data/templates/sidebar.block.menu.php:68 msgid "all your tags" -msgstr "Tất cả thẻ của bạn" +msgstr "Tous vos tags" #: data/templates/sidebar.block.menu.php:70 msgid "See all tags from this user" -msgstr "Nhìn thấy tất cả từ khoá của người dùng này" +msgstr "Voir tous les tags de cet utilisateur" #: data/templates/sidebar.block.menu.php:70 msgid "all tags from this user" -msgstr "tất cả từ khoá từ người dùng này" +msgstr "tous les tags de cet utilisateur" #: data/templates/sidebar.block.menu.php:74 msgid "See popular tags" -msgstr "Nhìn thấy những từ khoá thông thường" +msgstr "Voir les tags populaires" #: data/templates/sidebar.block.menu2.php:25 msgid "Featured Menu Tags" -msgstr "Danh sách những từ khoá chính" +msgstr "Tags Principaux" #: data/templates/sidebar.block.menu2.php:29 msgid "This menu is composed of keywords (tags) organized by admins." -msgstr "Danh mục này đã được tạo từ các từ khoá (thẻ) và được sắp xếp bởi những người quản trị." +msgstr "Ce menu est composé de mots-clefs (tags) organisés par les administrateurs." #: data/templates/sidebar.block.recent.php:18 msgid "Recent Tags" -msgstr "Những từ khoá gần đây" +msgstr "Tags récents" #: data/templates/sidebar.block.related.php:26 msgid "Related Tags" -msgstr "Quan hệ các từ khoá" +msgstr "Tags en relation" #: data/templates/sidebar.block.search.php:15 msgid "Last Searches" -msgstr "Những tìm kiếm trước" +msgstr "Dernières recherches" #: data/templates/sidebar.block.search.php:24 msgid "Number of bookmarks for this query" -msgstr "Tổng số trang ghi nhớ tìm thấy cho truy vấn này" +msgstr "Nombre de signets pour cette recherche" #: data/templates/sidebar.block.tagactions.php:9 #: www/tagrename.php:72 msgid "Rename Tag" msgid_plural "Rename Tags" -msgstr[0] "Thay đổi tên từ khoá" +msgstr[0] "Renommer le tag" msgstr[1] "Renommer les tags" #: data/templates/sidebar.block.tagactions.php:22 #: www/tagdelete.php:54 msgid "Delete Tag" -msgstr "Xoá từ khoá" +msgstr "Supprimer le tag" #: data/templates/sidebar.block.tagactions.php:24 #: www/tagedit.php:61 msgid "Edit Tag Description" -msgstr "Sửa mô tả của từ khoá" +msgstr "Editer la description du tag" #: data/templates/sidebar.block.tagactions.php:26 #: www/tagcommondescriptionedit.php:64 msgid "Edit Tag Common Description" -msgstr "Sửa mô tả chung của từ khoá" +msgstr "Editer la description commune du tag" #: data/templates/sidebar.block.tagactions.php:28 msgid "Create a link to another tag" -msgstr "Tạo một liên kết với một từ khoá khác" +msgstr "Créer un lien vers un autre tag" #: data/templates/sidebar.block.users.php:14 msgid "New Users" -msgstr "Những người dùng mới" +msgstr "Nouveaux Utilisateurs" #: data/templates/sidebar.block.users.php:23 #: data/templates/users.tpl.php:17 msgid "bookmarks" -msgstr "Danh mục những trang ghi nhớ" +msgstr "signets" #: data/templates/sidebar.block.users.php:30 msgid "See all users" -msgstr "Nhìn thấy tất cả người dùng" +msgstr "Voir tous les utilisateurs" #: data/templates/sidebar.block.users.php:30 msgid "All users" -msgstr "Tất cả người dùng" +msgstr "Tous les utilisateurs" #: data/templates/sidebar.block.watchlist.php:19 msgid "Close contacts are mutual contacts" -msgstr "Những danh sách liên lạc gần nhau là những danh sách liên lạc tương hỗ với nhau" +msgstr "Les contacts proches sont des contacts mutuels" #: data/templates/sidebar.block.watchlist.php:19 msgid "Close contacts" -msgstr "Danh sách liên lạc gần nhau" +msgstr "Contacts proches" #: data/templates/sidebar.block.watchlist.php:36 msgid "Add a contact..." -msgstr "Thêm một liên lạc..." +msgstr "Ajouter un contact..." #: data/templates/sidebar.block.watchlist.php:36 msgid "Type a username to add it to your contacts." -msgstr "Nhập vào tên truy cập để thêm vào danh sách liên lạc của bạn." +msgstr "Entrer un nom d'utilisateur pour l'ajouter à vos contacts." #: data/templates/sidebar.block.watchlist.php:44 msgid "Remove this contact" -msgstr "Bỏ liên lạc này" +msgstr "Enlever ce contact" #: data/templates/sidebar.block.watchstatus.php:11 msgid "Remove from Watchlist" -msgstr "Rời bỏ từ danh sách liên lạc" +msgstr "Enlever des contacts" #: data/templates/sidebar.block.watchstatus.php:13 msgid "Add to Watchlist" -msgstr "Thêm vào danh sách liên lạc" +msgstr "Ajouter aux contacts" #: data/templates/sidebar.linkedtags.inc.php:18 msgid "Edit link" -msgstr "Sửa một liên kết" +msgstr "Editer un lien" #: data/templates/sidebar.linkedtags.inc.php:47 msgid "Synonyms:" -msgstr "Đồng nghĩa :" +msgstr "Synonymes :" #: data/templates/tag2tagadd.tpl.php:12 msgid "Create new link:" -msgstr "Tạo một mối liên kết mới" +msgstr "Créer un nouveau lien" #: data/templates/tag2tagadd.tpl.php:19 #, php-format msgid "Note: include a tag into '%s' tag (e.g. %s>countries) display the tag into the menu box" -msgstr "Chú ý : gồm có một từ khoá chứa trong trong từ khoá'%s' (e.g. %s>Những lĩnh vực) để hiển thị từ khoá này trong hộp danh mục" +msgstr "Note : inclure un tag dans le tag '%s' (e.g. %s>countries) affiche ce tag dans la boîte de menu" #: data/templates/tag2tagadd.tpl.php:23 #: data/templates/tag2tagedit.tpl.php:37 msgid "Create" -msgstr "Tạo " +msgstr "Créer" #: data/templates/tag2tagadd.tpl.php:35 #: data/templates/tag2tagdelete.tpl.php:27 #: data/templates/tag2tagedit.tpl.php:51 msgid "Existing links:" -msgstr "Những liên kết hiện có :" +msgstr "Liens existants :" #: data/templates/tag2tagadd.tpl.php:53 #: data/templates/tag2tagdelete.tpl.php:45 #: data/templates/tag2tagedit.tpl.php:69 msgid "No links" -msgstr "Không có liên kết nào" +msgstr "Pas de liens" #: data/templates/tag2tagdelete.tpl.php:15 #: data/templates/tag2tagedit.tpl.php:16 #: data/templates/tagdelete.tpl.php:8 #: www/jsScuttle.php:23 msgid "Yes" -msgstr "Đúng" +msgstr "Oui" #: data/templates/tag2tagdelete.tpl.php:16 #: data/templates/tag2tagedit.tpl.php:17 #: data/templates/tagdelete.tpl.php:9 #: www/jsScuttle.php:23 msgid "No" -msgstr "Không" +msgstr "Non" #: data/templates/tag2tagedit.tpl.php:6 msgid "Delete the link" -msgstr "Xoá liên kết này" +msgstr "Supprimer le lien" #: data/templates/tag2tagedit.tpl.php:29 msgid "Create new link" -msgstr "Tạo một liên kết mới" +msgstr "Créer un nouveau lien" #: data/templates/tagrename.tpl.php:12 msgid "Old" -msgstr "Cũ" +msgstr "Ancien" #: data/templates/tagrename.tpl.php:17 msgid "New" -msgstr "Mới" +msgstr "Nouveau" #: data/templates/tagrename.tpl.php:24 msgid "Rename" -msgstr "Đổi tên" +msgstr "Renommer" #: data/templates/tags.tpl.php:11 #: data/templates/users.tpl.php:9 msgid "Alphabet" -msgstr "Bảng chữ cái" +msgstr "Alphabet" #: data/templates/tags.tpl.php:12 #: data/templates/users.tpl.php:10 msgid "Popularity" -msgstr "Phổ biến" +msgstr "Popularité" #: data/templates/toolbar.inc.php:8 #: data/templates/toolbar.inc.php:26 msgid "Home" -msgstr "Chủ" +msgstr "Accueil" #: data/templates/toolbar.inc.php:11 #: www/watchlist.php:106 msgid "Watchlist" -msgstr "Danh mục liên lạc" +msgstr "Contacts" #: data/templates/toolbar.inc.php:12 #: www/profile.php:67 msgid "Profile" -msgstr "Mô tả cá nhân" +msgstr "Profil" #: data/templates/toolbar.inc.php:13 #: www/bookmarks.php:209 msgid "Add a Bookmark" -msgstr "Thêm một trang ghi nhớ" +msgstr "Ajouter un signet" #: data/templates/toolbar.inc.php:14 msgid "Log Out" -msgstr "Thoát" +msgstr "Quitter" #: data/templates/toolbar.inc.php:17 msgid "Admin" -msgstr "Quản trị" +msgstr "Admin" #: data/templates/top.inc.php:49 msgid "Admins, your installation is in \"Debug Mode\" ($debugMode = true). To go in \"Normal Mode\" and hide debugging messages, change $debugMode to false into config.php." -msgstr "Quản trị, sự cài đặt của bạn o trong \"Mode Debug\" ($debugMode = true). Để đến \"Mode Normal\" và ẩn những thông báo gỡ rối, thay đổi $debugMode thành false ở trong config.inc.php." +msgstr "Admins, votre installation est en \"Mode Debug\" ($debugMode = true). Pour passer en \"Mode Normal\" et cacher les messages de debuggage, changez $debugMode à false dans config.inc.php." #: data/templates/users.tpl.php:17 msgid "profile" -msgstr "thông tin cá nhân" +msgstr "Profil" #: data/templates/users.tpl.php:17 msgid "created in" -msgstr "Tạo trong" +msgstr "Créé en " #: www/admin.php:32 msgid "Manage users" -msgstr "Quản lí những người dùng" +msgstr "Gérer les utilisateurs" #: www/admin.php:68 #, php-format msgid "%s and all his bookmarks and tags were deleted." -msgstr "%s, tất cả những trang ghi nhớ và những thẻ bị xoá." +msgstr "%s, ses signets et ses tags ont été effacés." #: www/admin.php:75 msgid "Problem with " -msgstr "Có vấn đề với " +msgstr "Problème avec " #: www/ajaxDelete.php:37 msgid "You are not allowed to delete this bookmark" -msgstr "Bạn đã không cho phép xoá trang ghi nhớ này" +msgstr "Vous n'êtes pas autorisés à supprimer ce signet" #: www/ajaxDelete.php:41 #: www/edit.php:103 msgid "Failed to delete bookmark" -msgstr "Có lỗi trong việc xoá trang ghi nhớ này" +msgstr "Erreur dans la suppression du signet" #: www/alltags.php:49 msgid "All Tags" -msgstr "Tất cả từ khoá" +msgstr "Tous les tags" #: www/alltags.php:55 #: www/bookmarks.php:96 @@ -1045,7 +1045,7 @@ msgstr "Tất cả từ khoá" #: www/watchlist.php:61 #, php-format msgid "User with username %s was not found" -msgstr "Tên đăng nhập %s đã không tìm thấy." +msgstr "L'utilisateur %s n'a pas été trouvé." #: www/bookmarkcommondescriptionedit.php:51 #: www/tag2tagadd.php:37 @@ -1054,389 +1054,389 @@ msgstr "Tên đăng nhập %s đã không tìm thấy." #: www/tagcommondescriptionedit.php:43 #: www/tagedit.php:43 msgid "Permission denied." -msgstr "Cho phép từ chối." +msgstr "Permission non accordée." #: www/bookmarkcommondescriptionedit.php:60 msgid "Bookmark common description updated" -msgstr "Cập nhật mô tả trang ghi nhớ." +msgstr "Description commune du signet mise à jour." #: www/bookmarkcommondescriptionedit.php:63 msgid "Failed to update the bookmark common description" -msgstr "Có lỗi trong việc cập nhật mô tả trang ghi nhớ" +msgstr "Erreur dans la mise à jour de la description du signet" #: www/bookmarkcommondescriptionedit.php:71 msgid "Edit Bookmark Common Description" -msgstr "Sửa mô tả trang ghi nhớ" +msgstr "Editer la description commune du signet" #: www/bookmarks.php:111 #: www/tags.php:47 msgid "Remove the tag from the selection" -msgstr "Huỷ bỏ từ khoá đã chọn" +msgstr "Retirer le tag de la sélection" #: www/bookmarks.php:131 #: www/edit.php:65 msgid "Your bookmark must have a title and an address" -msgstr "Trang ghi nhớ của bạn phải có một tiêu đề tóm tắt và một địa chỉ của trang đó." +msgstr "Votre signet doit avoir un titre et une adresse." #: www/bookmarks.php:152 #: www/edit.php:83 #: www/edit.php:86 msgid "Bookmark saved" -msgstr "Lưu lại trang ghi nhớ này." +msgstr "Signet enregistré." #: www/bookmarks.php:152 msgid "(Come back to previous page.)" -msgstr "(Quay lại trang trước đó.)" +msgstr "(Revenir à la page précédente.)" #: www/bookmarks.php:159 #: www/import.php:106 #: www/importNetscape.php:108 msgid "There was an error saving your bookmark. Please try again or contact the administrator." -msgstr "Có lỗi trong việc lưu lại trang ghi nhớ này. Hãy thử lại hoặc liên lạc với người quản trị." +msgstr "Il y a eu une erreur en enregistrant ce signet. Veuillez rééssayer ou contacter votre administrateur." #: www/bookmarks.php:216 msgid "Add Bookmark" -msgstr "Thêm một trang ghi nhớ" +msgstr "Ajouter signet" #: www/bookmarks.php:219 msgid "You must be logged in before you can add bookmarks." -msgstr "Để thêm một trang ghi nhớ bạn phải đăng nhập." +msgstr "Vous devez être authentifié avant de pouvoir ajouter des signets." #: www/bookmarks.php:274 #: www/bookmarks.php:275 msgid "My Bookmarks" -msgstr "Những trang ghi nhớ của tôi" +msgstr "Mes signets" #: www/edit.php:44 #: www/edit.php:45 msgid "Edit Bookmark" -msgstr "Sửa trang ghi nhớ" +msgstr "Editer le signet" #: www/edit.php:51 #, php-format msgid "Bookmark with id %s not was not found" -msgstr "Trang ghi nhớ với tên %s đã không tìm thấy" +msgstr "Signet %s non trouvé" #: www/edit.php:57 msgid "You are not allowed to edit this bookmark" -msgstr "Bạn đã không cho phép sửa trang ghi nhớ này." +msgstr "Vous n'êtes pas autorisé à éditer ce signet." #: www/edit.php:77 msgid "Error while saving your bookmark" -msgstr "Có lỗi trong khi lưu lại trang ghi nhớ của bạn." +msgstr "Erreur pendant l'enregistrement de votre signet." #: www/history.php:61 msgid "History" -msgstr "Lưu vết quá trình" +msgstr "Historique" #: www/history.php:62 #, php-format msgid "History for %s" -msgstr "Lưu vết quá trình cho %s" +msgstr "Historique de %s" #: www/history.php:84 msgid "Address was not found" -msgstr "Địa chỉ này đã không tìm thấy." +msgstr "L'adresse n'a pas été trouvée." #: www/import.php:47 msgid "Could not open XML input" -msgstr "Không thể mở dữ liệu XML." +msgstr "Impossible d'ouvrir le flux XML." #: www/import.php:51 #, php-format msgid "XML error: %s at line %d" -msgstr "Lỗi XML: %s tại đường truyền %d" +msgstr "Erreur XML: %s à la ligne %d" #: www/import.php:60 msgid "Import Bookmarks from del.icio.us" -msgstr "Nạp vào những trang ghi nhớ từ del.icio.us" +msgstr "Importer les signet depuis del.icio.us" #: www/import.php:93 msgid "You have already submitted this bookmark." -msgstr "Bạn vừa nhập trang ghi nhớ này." +msgstr "Vous avez déjà enregistré ce signet." #: www/import.php:104 msgid "Bookmark imported." -msgstr "Trang ghi nhớ này đã nạp." +msgstr "Signet importé." #: www/importNetscape.php:95 msgid "You have already submitted some of these bookmarks." -msgstr "Bạn vừa nhập một trong số những trang ghi nhớ này." +msgstr "Vous avez déjà enregistré certains de ces signets." #: www/importNetscape.php:115 msgid "Bookmarks found: " -msgstr "Trang ghi nhớ này đã được tìm thấy :" +msgstr "Signets trouvés :" #: www/importNetscape.php:116 msgid "Bookmarks imported: " -msgstr "Những trang ghi nhớ đã nạp :" +msgstr "Signets importés :" #: www/importNetscape.php:117 #: www/importNetscape.php:122 msgid "Import Bookmarks from Browser File" -msgstr "Nạp những trang ghi nhớ này từ một file trong danh sách duyệt" +msgstr "Importer les signets depuis un fichier" #: www/importStructure.php:61 msgid "Bad indentation" -msgstr "Xác định kém" +msgstr "Mauvaise indentation" #: www/importStructure.php:67 msgid "New links between tags: " -msgstr "Liên kết mới giữa các từ khoá :" +msgstr "Nouveau lien entre tags :" #: www/importStructure.php:72 msgid "Import Structure" -msgstr "Nạp một cấu trúc" +msgstr "Importer une structure" #: www/index.php:38 msgid "You have now logged out" -msgstr "Bạn vừa thoátt khỏi" +msgstr "Vous êtes maintenant déconnecté." #: www/index.php:45 #, php-format msgid "%s: Recent bookmarks" -msgstr "%s: Những trang ghi nhớ gần đây" +msgstr "%s: Signets récents" #: www/index.php:78 msgid "Store, share and tag your favourite links" -msgstr "Lưu trữ, chia xẻ và gán từ khoá cho những liên kết yêu thích của bạn" +msgstr "Conservez, partagez et taggez vos liens favoris" #: www/index.php:79 msgid "All Bookmarks" -msgstr "Tất cả các trang ghi nhớ" +msgstr "Tous les signets" #: www/jsScuttle.php:70 msgid "Available" -msgstr "Có giá trị" +msgstr "Disponible" #: www/jsScuttle.php:73 msgid "Not Available" -msgstr "Không có giá trị" +msgstr "Non Disponible" #: www/login.php:48 msgid "The details you have entered are incorrect. Please try again." -msgstr "Những thông tin bạn đã nhập không chính xác. Hãy thử lại." +msgstr "Les informations que vous avez entrées sont incorrectes. Veuillez recommencer." #: www/password.php:36 msgid "You must enter your username." -msgstr "Bạn phải nhập vào tên truy cập." +msgstr "Vous devez entrer votre nom d'utilisateur." #: www/password.php:40 msgid "You must enter your e-mail address." -msgstr "Bạn phải đưa ra một E-mail." +msgstr "Vous devez saisir une E-mail." #: www/password.php:48 msgid "No matches found for that username." -msgstr "Không có tên truy cập này." +msgstr "Rien de trouvé pour ce nom d'utilisateur." #: www/password.php:51 msgid "No matches found for that combination of username and e-mail address." -msgstr "Không phù hợp giữa tên người dùng này và e-mail." +msgstr "Pas d'entrée pour ce nom d'utilisateur et cet e-mail." #: www/password.php:59 msgid "There was an error while generating your new password. Please try again." -msgstr "Đã có lỗi trong khi nhập trang ghi nhớ này. Hãy thử lại hoặc liên lạc với người quản trị." +msgstr "Il y a eu une erreur en enregistrant ce signet. Veuillez rééssayer ou contacter votre administrateur." #: www/password.php:63 msgid "Your new password is:" -msgstr "Mật khẩu mới của bạn là:" +msgstr "Votre nouveau mot de passe est:" #: www/password.php:63 msgid "To keep your bookmarks secure, you should change this password in your profile the next time you log in." -msgstr "Để giữ an toàn và bảo mật cho những trang ghi nhớ của bạn, bạn nên thay đổi mật khẩu trong mô tả cá nhân cho lần đăng nhập sau." +msgstr "Pour garder vos signets sûrs, vous devriez changer ce mot de passe dans votre profil lors de votre prochaine authentification." #: www/password.php:66 #, php-format msgid "%s Account Information" -msgstr "Thông tin tài khoản %s" +msgstr "Informations du compte de %s" #: www/password.php:68 #, php-format msgid "New password generated and sent to %s" -msgstr "Mật khẩu mới sẽ được gửi đến địa chỉ email %s" +msgstr "Nouveau mot de passe généré et envoyé à l'adresse %s" #: www/password.php:75 msgid "Forgotten Password" -msgstr "Quên mật khẩu" +msgstr "Mot de passe oublié" #: www/profile.php:59 #: www/watchlist.php:119 msgid "Username was not specified" -msgstr "Tên truy cập đã không chỉ rõ ." +msgstr "Le nom d'utilisateur n'a pas été spécifié." #: www/profile.php:65 msgid "My Profile" -msgstr "Hồ sơ cá nhân" +msgstr "Mon Profil" #: www/profile.php:89 msgid "Invalid Token" -msgstr "Token không có hiệu lực" +msgstr "Token invalide" #: www/profile.php:94 msgid "Password and confirmation do not match." -msgstr "Mật khẩu không tương thích với tên truy cập." +msgstr "Le mot de passe et sa vérification ne correspondent pas." #: www/profile.php:98 msgid "Password must be at least 6 characters long." -msgstr "Mật khẩu phải chứa ít nhất 6 kí tự." +msgstr "Le mot de passe doit avoir au moins 6 caractères." #: www/profile.php:102 msgid "E-mail address is not valid." -msgstr "Địa chỉ email không có giá trị." +msgstr "Adresse de courrier électronique invalide." #: www/profile.php:106 msgid "An error occurred while saving your changes." -msgstr "Có một lỗi xuất hiện trong khi lưu lại những sửa đổi của bạn." +msgstr "Une erreur s'est produite pendant l'enregistrement de vos modifications." #: www/profile.php:108 msgid "Changes saved." -msgstr "Lưu lại những thay đổi." +msgstr "Modifications enregistrées." #: www/register.php:46 msgid "You must enter a username, password and e-mail address." -msgstr "Bạn phải đưa ra một tên truy cập, một mật khẩu, một e-mail" +msgstr "Vous devez saisir un nom d'utilisateur, un mot de passe, un nom et un e-mail" #: www/register.php:50 msgid "This username has been reserved, please make another choice." -msgstr "Tên truy cập này đã được đăng kí, hãy chọn tên khác." +msgstr "Ce nom d'utilisateur existe déjà, veuillez en choisir un autre." #: www/register.php:54 msgid "This username already exists, please make another choice." -msgstr "Tên truy cập này đã tồn tại, hãy chọn một tên khác." +msgstr "Ce nom d'utilisateur existe déjà, veuillez en choisir un autre." #: www/register.php:58 msgid "This username is not valid (too short, too long, forbidden characters...), please make another choice." -msgstr "Tên truy cập này không được xác nhận (quá ngắn, quá dài, kí tự cấm...), hãy tạo tên khác." +msgstr "Ce nom d'utilisateur n'est pas valide (trop court, trop long, caractères interdits...), Merci de faire un autre choix." #: www/register.php:62 msgid "E-mail address is not valid. Please try again." -msgstr "Địa chỉ email không được xác nhận. Hãy thử lại." +msgstr "Adresse de courrier électronique invalide. Veuillez réessayer." #: www/register.php:66 msgid "Antispam answer is not valid. Please try again." -msgstr "Câu trả lời chống thư rác không được xác nhận. hãy thử lại." +msgstr "La réponse antispam n'est pas valide. Veuillez réessayer." #: www/register.php:75 msgid "You have successfully registered. Enjoy!" -msgstr "Bạn đã đăng kí thành công!" +msgstr "Votre inscription a bien été prise en compte !" #: www/register.php:77 msgid "Registration failed. Please try again." -msgstr "Đăng kí thất bại. hãy thử làm lại." +msgstr "Enregistrement raté. Veuillez rééssayer." #: www/rss.php:84 #, php-format msgid "Recent bookmarks posted to %s" -msgstr "Những trang ghi nhớ gần đây %s" +msgstr "Signets ajoutés récemment à %s" #: www/search.php:81 #: www/search.php:145 msgid "Search Bookmarks" -msgstr "Tìm kiếm trang ghi nhớ" +msgstr "Recherche de signets" #: www/search.php:87 msgid "Search Results" -msgstr "Kêt quả tìm kiếm" +msgstr "Résultats de recherche" #: www/search.php:135 msgid "Unsatisfied? You can also try our " -msgstr "Có phải bạn không vừa lòng? Bạn có thể thử của chúng tôi " +msgstr "Insatisfait ? Vous pouvez aussi essayer notre " #: www/tag2tagadd.php:50 msgid "Tag link created" -msgstr "Liên kết giữa các từ khoá được tạo." +msgstr "Lien entre tags créé." #: www/tag2tagadd.php:53 msgid "Failed to create the link" -msgstr "Không thể tạo liên kết này" +msgstr "Impossible de créer le lien" #: www/tag2tagadd.php:65 msgid "Add Tag Link" -msgstr "Thêm một liên kết giữa các từ khoá" +msgstr "Ajout d'un lien entre tags" #: www/tag2tagdelete.php:66 msgid "Tag link deleted" -msgstr "Xoá một liên kết từ khoá" +msgstr "Effacement d'un lien entre tags" #: www/tag2tagdelete.php:69 msgid "Failed to delete the link" -msgstr "Không thể xoá liên kết này" +msgstr "Impossible d'effacer le lien" #: www/tag2tagdelete.php:81 msgid "Delete Link Between Tags" -msgstr "Xoá một liên kết giữa các từ khoá" +msgstr "Effacer un lien entre tags" #: www/tag2tagedit.php:55 msgid "Edit Link Between Tags" -msgstr "Sửa một liên kết giữa các từ khoá" +msgstr "Editer un lien entre tags" #: www/tagcommondescriptionedit.php:55 msgid "Tag common description updated" -msgstr "Sửa mô tả chung của từ khoá" +msgstr "Editer la description commune du tag" #: www/tagcommondescriptionedit.php:58 msgid "Failed to update the tag common description" -msgstr "Không thể cập nhật mô tả chung của từ khoá" +msgstr "Impossible de mettre à jour la description commune du tag" #: www/tagdelete.php:43 msgid "Tag deleted" -msgstr "Từ khoá đã được xoá" +msgstr "Tag effacé" #: www/tagdelete.php:46 msgid "Failed to delete the tag" -msgstr "Không thể xoá từ khoá này" +msgstr "Impossible d'effacer le tag" #: www/tagedit.php:52 msgid "Tag description updated" -msgstr "Mô tả của từ khoá đã được cập nhật" +msgstr "Description du tag mise à jour" #: www/tagedit.php:55 msgid "Failed to update the tag description" -msgstr "Không thể cập nhật mô tả của từ khoá" +msgstr "Impossible de mettre à jour la description du tag" #: www/tagrename.php:63 msgid "Tag renamed" -msgstr "Từ khoá đã được đổi tên" +msgstr "Tag renommé" #: www/tagrename.php:66 msgid "Failed to rename the tag" -msgstr "Lỗi trong việc đổi tên từ khoá" +msgstr "Erreur dans le renommage du tag" #: www/users.php:31 msgid "Users" -msgstr "Những người tham gia" +msgstr "Utilisateurs" #: www/watch.php:54 msgid "User removed from your watchlist" -msgstr "Tên truy cập đã dời khỏi danh sách liên lạc của bạn" +msgstr "Utilisateur enlevé de vos contacts" #: www/watch.php:56 msgid "User added to your watchlist" -msgstr "Tên truy cập đã được thêm vào danh sách liên lạc của bạn" +msgstr "Utilisateur ajouté à vos contacts" #: www/watchlist.php:104 msgid "My Watchlist" -msgstr "Danh sách liên lạc của tôi" +msgstr "Mes Contacts" #: www/api/httpauth.inc.php:11 msgid "Use of the API calls requires authentication." -msgstr "Sử dụng API để gọi yêu cầu chính thức." +msgstr "L'utilisation de l'API requiert une authentification." #: www/gsearch/index.php:27 msgid "Come back to " -msgstr "Quay lại" +msgstr "Revenir à" #: www/gsearch/index.php:32 msgid "Admin tips: " -msgstr "Lời khuyên của quản trị:" +msgstr "Conseil pour admin:" #: www/gsearch/index.php:33 msgid "To refresh manually Google Custom Search Engine, goes to: " -msgstr "Để khởi động lại điều khiển bằng tay của máy tìm kiếm Google, hãy đến :" +msgstr "Pour rafraîchir manuellement le moteur de Google Custom Search, allez à :" #: www/gsearch/index.php:35 msgid "If no result appears, check that all the urls are valid in the admin section." -msgstr "Nếu không có kết quả nào xuất hiệnt, hãy kiểm tra lại tất cả các đường link được xác nhận trong phần quản lí." +msgstr "Si aucun résultat apparaît, vérifier que toutes les urls sont valides dans la section admin." #~ msgid "Add this tag to the query" #~ msgstr "Ajouter ce tag à la requête" From a95280c9353f03c01504c70572f28e28df364aa4 Mon Sep 17 00:00:00 2001 From: cweiske Date: Mon, 3 May 2010 06:26:00 +0000 Subject: [PATCH 58/63] add compiled russian translation git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@709 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/locales/ru_RU/LC_MESSAGES/messages.mo | Bin 0 -> 29086 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/locales/ru_RU/LC_MESSAGES/messages.mo diff --git a/data/locales/ru_RU/LC_MESSAGES/messages.mo b/data/locales/ru_RU/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..7a68b6c728e1228d58d518bd3186857a24f9a076 GIT binary patch literal 29086 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 Date: Mon, 3 May 2010 06:26:19 +0000 Subject: [PATCH 59/63] update changelog git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@710 b3834d28-1941-0410-a4f8-b48e95affb8f --- doc/ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9af38d5..42d96cd 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -6,8 +6,11 @@ ChangeLog for SemantiScuttle - Many SQL optimizations - New config option to skip "SET NAMES UTF8" call: $dbneedssetnames - Do not highlight admin bookmarks when $enableAdminColors is disabled +- Add russian translation +- Make HTML export follow the specifications a bit better - Fix bug #2953732: faulty error message for duplicate bookmarks - Fix bug #2960663: do not send content-type headers twice for ajax/api scripts +- Fix bug #2976593: fr_FR locale is vietnamese 0.96.1 - 2010-02-09 From 549cae3de45c701a8363cce6f8f57e1704f6d803 Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 9 Jun 2010 05:58:48 +0000 Subject: [PATCH 60/63] put sergey's name in the russian translation file git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@711 b3834d28-1941-0410-a4f8-b48e95affb8f --- data/locales/ru_RU/LC_MESSAGES/messages.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/locales/ru_RU/LC_MESSAGES/messages.po b/data/locales/ru_RU/LC_MESSAGES/messages.po index 5a2607a..4bf666e 100644 --- a/data/locales/ru_RU/LC_MESSAGES/messages.po +++ b/data/locales/ru_RU/LC_MESSAGES/messages.po @@ -1,7 +1,7 @@ # SemanticScuttle ru_RU Translation # Copyright (C) 2005 - 2009 SemanticScuttle project # This file is distributed under the same license as the SemanticScuttle package. -# webii.ru +# Sergey Ulitin # msgid "" msgstr "" @@ -9,14 +9,14 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-06-04 11:33+0200\n" "PO-Revision-Date: 2010-04-30 02:35+0400\n" -"Last-Translator: webii.ru \n" -"Language-Team: webii.ru \n" +"Last-Translator: Sergey Ulitin \n" +"Language-Team: Sergey Ulitin \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Poedit-Language: English\n" -"X-Poedit-Country: UNITED KINGDOM\n" +"X-Poedit-Language: Russian\n" +"X-Poedit-Country: Russia\n" "X-Poedit-SourceCharset: utf-8\n" #: ../../../about.php:23 From 733304908251397114d8895df2603242a2b7043c Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 9 Jun 2010 05:59:51 +0000 Subject: [PATCH 61/63] prepare release of 0.97.0 git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@712 b3834d28-1941-0410-a4f8-b48e95affb8f --- build.xml | 4 ++-- data/templates/about.tpl.php | 2 +- doc/ChangeLog | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.xml b/build.xml index 9cf4de9..c1db166 100644 --- a/build.xml +++ b/build.xml @@ -8,8 +8,8 @@ --> - - + + diff --git a/data/templates/about.tpl.php b/data/templates/about.tpl.php index af5c6e7..7bff98d 100644 --- a/data/templates/about.tpl.php +++ b/data/templates/about.tpl.php @@ -17,7 +17,7 @@ $this->includeTemplate($GLOBALS['top_include']); isAdmin()): ?> -
  1. SemanticScuttle v0.96.1
  2. +
  3. SemanticScuttle v0.97.0
  4. diff --git a/doc/ChangeLog b/doc/ChangeLog index 42d96cd..5b4e4d3 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,9 +1,9 @@ ChangeLog for SemantiScuttle ============================ -0.97.0 - 2010-????? +0.97.0 - 2010-06-09 ------------------- -- Many SQL optimizations +- Many SQL optimizations - SemanticScuttle shows bookmarks 4 times faster now - New config option to skip "SET NAMES UTF8" call: $dbneedssetnames - Do not highlight admin bookmarks when $enableAdminColors is disabled - Add russian translation From 1962e3d2bc30333d3dbe133c759fc650d6e8a5c7 Mon Sep 17 00:00:00 2001 From: cweiske Date: Wed, 9 Jun 2010 06:05:48 +0000 Subject: [PATCH 62/63] update upgrade.txt file and ajust changelog git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@713 b3834d28-1941-0410-a4f8-b48e95affb8f --- doc/UPGRADE.txt | 6 ++++++ doc/developers/release-new-version | 13 +++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/doc/UPGRADE.txt b/doc/UPGRADE.txt index 371c302..c4470f9 100644 --- a/doc/UPGRADE.txt +++ b/doc/UPGRADE.txt @@ -1,6 +1,12 @@ Upgrading SemanticScuttle from a previous version ================================================= + +From version 0.96 to 0.97 +------------------------- +No database changes necessary. + + From version 0.95 to 0.96 ------------------------- Update your database: diff --git a/doc/developers/release-new-version b/doc/developers/release-new-version index 33a3ef6..69530df 100644 --- a/doc/developers/release-new-version +++ b/doc/developers/release-new-version @@ -3,19 +3,20 @@ How to release a new version of SemanticScuttle 0. Run unit tests and verify that all of them pass 1. Update doc/ChangeLog -2. Update version in data/templates/about.tpl.php +2. Update doc/UPGRADE.txt +3. Update version in data/templates/about.tpl.php and build.xml -3. Create a release zip file via the build script: +4. Create a release zip file via the build script: Just type "phing". -4. Make a test installation from your zip file with a fresh +5. Make a test installation from your zip file with a fresh database. Register a user, add bookmarks etc. -5. When all is fine, it's time to release. +6. When all is fine, it's time to release. The build script takes care for most of the tasks. Run "phing release", and it will upload the release to sourceforge and create a svn tag. -6. Write announcement mail to the SemanticScuttle mailing list +7. Write announcement mail to the SemanticScuttle mailing list semanticscuttle-devel@lists.sourceforge.net -7. Announce the new release in the sourceforge project news +8. Announce the new release in the sourceforge project news https://sourceforge.net/apps/trac/sourceforge/wiki/News From 31570df64ce6543de407e7b9d751ba9033d930de Mon Sep 17 00:00:00 2001 From: cweiske Date: Fri, 9 Jul 2010 10:04:35 +0000 Subject: [PATCH 63/63] Fix bug getTagsForBookmarks() that fetched all tags, see http://sourceforge.net/projects/semanticscuttle/forums/forum/759510/topic/3752670 for details git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@715 b3834d28-1941-0410-a4f8-b48e95affb8f --- doc/ChangeLog | 5 +++++ src/SemanticScuttle/Service/Bookmark2Tag.php | 7 +------ tests/Bookmark2TagTest.php | 6 ++++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 5b4e4d3..5e24f07 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,6 +1,11 @@ ChangeLog for SemantiScuttle ============================ +0.9X.X - 2010-XX-XX +------------------- +- Fix bug getTagsForBookmarks() that fetched all tags + + 0.97.0 - 2010-06-09 ------------------- - Many SQL optimizations - SemanticScuttle shows bookmarks 4 times faster now diff --git a/src/SemanticScuttle/Service/Bookmark2Tag.php b/src/SemanticScuttle/Service/Bookmark2Tag.php index d6c0e58..4d2c969 100644 --- a/src/SemanticScuttle/Service/Bookmark2Tag.php +++ b/src/SemanticScuttle/Service/Bookmark2Tag.php @@ -325,13 +325,8 @@ class SemanticScuttle_Service_Bookmark2Tag extends SemanticScuttle_DbService return array(); } - $sql = ''; - foreach ($bookmarkids as $bookmarkid) { - $sql .= ' OR bId = ' . intval($bookmarkid); - } - $query = 'SELECT tag, bId FROM ' . $this->getTableName() - . ' WHERE (1' . $sql . ')' + . ' WHERE bId IN (' . implode(',', $bookmarkids) . ')' . ' AND LEFT(tag, 7) <> "system:"' . ' ORDER BY id, bId ASC'; diff --git a/tests/Bookmark2TagTest.php b/tests/Bookmark2TagTest.php index 0afaaf8..14b71cc 100644 --- a/tests/Bookmark2TagTest.php +++ b/tests/Bookmark2TagTest.php @@ -171,6 +171,12 @@ class Bookmark2TagTest extends TestBase $bid4 = $this->addBookmark(null, null, 0, array()); //no tags + //bookmark that does not get queried + //http://sourceforge.net/projects/semanticscuttle/forums/forum/759510/topic/3752670 + $bid5 = $this->addBookmark(null, null, 0, array()); + $this->b2ts->attachTags($bid5, array('foo', 'bar2', 'fuu5')); + + $alltags = $this->b2ts->getTagsForBookmarks( array($bid1, $bid2, $bid3, $bid4) );