Skip to content

Commit

Permalink
Add a button to set links as sticky
Browse files Browse the repository at this point in the history
Meaning that they always appear on top of all links

Fixes shaarli#186
  • Loading branch information
ArthurHoaro committed May 22, 2018
1 parent 73da3a2 commit abca238
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 26 deletions.
3 changes: 3 additions & 0 deletions application/LinkDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,9 @@ public function reorder($order = 'DESC')
$order = $order === 'ASC' ? -1 : 1;
// Reorder array by dates.
usort($this->links, function($a, $b) use ($order) {
if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
return $a['sticky'] ? -1 : 1;
}
return $a['created'] < $b['created'] ? 1 * $order : -1 * $order;
});

Expand Down
6 changes: 6 additions & 0 deletions application/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class Router

public static $PAGE_DELETELINK = 'delete_link';

public static $PAGE_PINLINK = 'pin';

public static $PAGE_EXPORT = 'export';

public static $PAGE_IMPORT = 'import';
Expand Down Expand Up @@ -134,6 +136,10 @@ public static function findPage($query, $get, $loggedIn)
return self::$PAGE_DELETELINK;
}

if (startsWith($query, 'do='. self::$PAGE_PINLINK)) {
return self::$PAGE_PINLINK;
}

if (startsWith($query, 'do='. self::$PAGE_EXPORT)) {
return self::$PAGE_EXPORT;
}
Expand Down
20 changes: 20 additions & 0 deletions application/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,26 @@ public function updateMethodDownloadSizeAndTimeoutConf()

return true;
}

/**
* Set sticky = false on all links
*
* @return bool true if the update is successful, false otherwise.
*/
public function updateMethodSetSticky()
{
foreach ($this->linkDB as $key => $link) {
if (isset($link['sticky'])) {
return true;
}
$link['sticky'] = false;
$this->linkDB[$key] = $link;
}

$this->linkDB->save($this->conf->get('resource.page_cache'));

return true;
}
}

/**
Expand Down
12 changes: 12 additions & 0 deletions assets/default/scss/shaarli.scss
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,14 @@ body, .pure-g [class*="pure-u"] {
color: #ac2925 !important;
}

.pin-link {
font-size: 1.3em;
}

.pinned-link {
color: #0b5ea6 !important;
}

.linklist-item-description {
position: relative;
padding: 0 10px;
Expand Down Expand Up @@ -731,6 +739,10 @@ body, .pure-g [class*="pure-u"] {
margin: 0 7px;
}

.ctrl-delete {
margin: 0 7px 0 0;
}

/** 64em -> lg **/
@media screen and (max-width: 64em) {
.linklist-item-infos-url {
Expand Down
19 changes: 19 additions & 0 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -1423,6 +1423,25 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
exit;
}

if ($targetPage == Router::$PAGE_PINLINK) {
if (! isset($_GET['id']) || empty($LINKSDB[$_GET['id']])) {
// FIXME! Use a proper error system.
$msg = t('Invalid link ID provided');
echo '<script>alert("'. $msg .'");document.location=\''. index_url($_SERVER) .'\';</script>';
exit;
}
if (! $sessionManager->checkToken($_GET['token'])) {
die('Wrong token.');
}

$link = $LINKSDB[$_GET['id']];
$link['sticky'] = ! $link['sticky'];
$LINKSDB[(int) $_GET['id']] = $link;
$LINKSDB->save($conf->get('resource.page_cache'));
header('Location: '.index_url($_SERVER));
exit;
}

if ($targetPage == Router::$PAGE_EXPORT) {
// Export links as a Netscape Bookmarks file

Expand Down
18 changes: 9 additions & 9 deletions tests/FeedBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ public function testRSSBuildData()
$this->assertFalse($data['usepermalinks']);
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));

// Test first link (note link)
$link = reset($data['links']);
// Test first not pinned link (note link)
$link = $data['links'][array_keys($data['links'])[2]];
$this->assertEquals(41, $link['id']);
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
$this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
Expand Down Expand Up @@ -119,7 +119,7 @@ public function testAtomBuildData()
$data = $feedBuilder->buildData();
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
$this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']);
$link = reset($data['links']);
$link = $data['links'][array_keys($data['links'])[2]];
$this->assertRegExp('/2015-03-10T11:46:51\+\d{2}:\d{2}/', $link['pub_iso_date']);
$this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['links'][8]['up_iso_date']);
}
Expand Down Expand Up @@ -148,13 +148,13 @@ public function testBuildDataFiltered()
public function testBuildDataCount()
{
$criteria = array(
'nb' => '1',
'nb' => '3',
);
$feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false);
$feedBuilder->setLocale(self::$LOCALE);
$data = $feedBuilder->buildData();
$this->assertEquals(1, count($data['links']));
$link = array_shift($data['links']);
$this->assertEquals(3, count($data['links']));
$link = $data['links'][array_keys($data['links'])[2]];
$this->assertEquals(41, $link['id']);
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
}
Expand All @@ -171,15 +171,15 @@ public function testBuildDataPermalinks()
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
$this->assertTrue($data['usepermalinks']);
// First link is a permalink
$link = array_shift($data['links']);
$link = $data['links'][array_keys($data['links'])[2]];
$this->assertEquals(41, $link['id']);
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
$this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
$this->assertEquals('http://host.tld/?WDWyig', $link['url']);
$this->assertContains('Direct link', $link['description']);
$this->assertContains('http://host.tld/?WDWyig', $link['description']);
// Second link is a direct link
$link = array_shift($data['links']);
$link = $data['links'][array_keys($data['links'])[3]];
$this->assertEquals(8, $link['id']);
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114633'), $link['created']);
$this->assertEquals('http://host.tld/?RttfEw', $link['guid']);
Expand Down Expand Up @@ -237,7 +237,7 @@ public function testBuildDataServerSubdir()
);

// Test first link (note link)
$link = array_shift($data['links']);
$link = $data['links'][array_keys($data['links'])[2]];
$this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']);
$this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']);
$this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']);
Expand Down
10 changes: 6 additions & 4 deletions tests/LinkDBTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,12 @@ public function testCountHiddenPublic()
public function testDays()
{
$this->assertEquals(
array('20100310', '20121206', '20130614', '20150310'),
array('20100309', '20100310', '20121206', '20121207', '20130614', '20150310'),
self::$publicLinkDB->days()
);

$this->assertEquals(
array('20100310', '20121206', '20130614', '20141125', '20150310'),
array('20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'),
self::$privateLinkDB->days()
);
}
Expand Down Expand Up @@ -475,13 +475,15 @@ public function testFilterHashInValid()
public function testReorderLinksDesc()
{
self::$privateLinkDB->reorder('ASC');
$linkIds = array(42, 4, 9, 1, 0, 7, 6, 8, 41);
$stickyIds = [11, 10];
$standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41];
$linkIds = array_merge($stickyIds, $standardIds);
$cpt = 0;
foreach (self::$privateLinkDB as $key => $value) {
$this->assertEquals($linkIds[$cpt++], $key);
}
self::$privateLinkDB->reorder('DESC');
$linkIds = array_reverse($linkIds);
$linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds));
$cpt = 0;
foreach (self::$privateLinkDB as $key => $value) {
$this->assertEquals($linkIds[$cpt++], $key);
Expand Down
4 changes: 2 additions & 2 deletions tests/NetscapeBookmarkUtils/BookmarkExportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public function testFilterAndFormatDoNotPrependNoteUrl()
$links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, '');
$this->assertEquals(
'?WDWyig',
$links[0]['url']
$links[2]['url']
);
}

Expand All @@ -128,7 +128,7 @@ public function testFilterAndFormatPrependNoteUrl()
);
$this->assertEquals(
$indexUrl . '?WDWyig',
$links[0]['url']
$links[2]['url']
);
}
}
60 changes: 60 additions & 0 deletions tests/Updater/UpdaterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -684,4 +684,64 @@ public function testUpdateMethodDownloadSizeAndTimeoutConfOnlyTimeout()
$this->assertEquals(4194304, $this->conf->get('general.download_max_size'));
$this->assertEquals(3, $this->conf->get('general.download_timeout'));
}

/**
* Test updateMethodSetSticky().
*/
public function testUpdateStickyValid()
{
$blank = [
'id' => 1,
'url' => 'z',
'title' => '',
'description' => '',
'tags' => '',
'created' => new DateTime(),
];
$links = [
1 => ['id' => 1] + $blank,
2 => ['id' => 2] + $blank,
];
$refDB = new ReferenceLinkDB();
$refDB->setLinks($links);
$refDB->write(self::$testDatastore);
$linkDB = new LinkDB(self::$testDatastore, true, false);

$updater = new Updater(array(), $linkDB, $this->conf, true);
$this->assertTrue($updater->updateMethodSetSticky());

$linkDB = new LinkDB(self::$testDatastore, true, false);
foreach ($linkDB as $link) {
$this->assertFalse($link['sticky']);
}
}

/**
* Test updateMethodSetSticky().
*/
public function testUpdateStickyNothingToDo()
{
$blank = [
'id' => 1,
'url' => 'z',
'title' => '',
'description' => '',
'tags' => '',
'created' => new DateTime(),
];
$links = [
1 => ['id' => 1, 'sticky' => true] + $blank,
2 => ['id' => 2] + $blank,
];
$refDB = new ReferenceLinkDB();
$refDB->setLinks($links);
$refDB->write(self::$testDatastore);
$linkDB = new LinkDB(self::$testDatastore, true, false);

$updater = new Updater(array(), $linkDB, $this->conf, true);
$this->assertTrue($updater->updateMethodSetSticky());

$linkDB = new LinkDB(self::$testDatastore, true, false);
$this->assertTrue($linkDB[1]['sticky']);
}
}
21 changes: 12 additions & 9 deletions tests/api/controllers/GetLinksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ public function testGetLinks()
$this->assertEquals($this->refDB->countLinks(), count($data));

// Check order
$order = [41, 8, 6, 7, 0, 1, 9, 4, 42];
$order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
$cpt = 0;
foreach ($data as $link) {
$this->assertEquals(self::NB_FIELDS_LINK, count($link));
$this->assertEquals($order[$cpt++], $link['id']);
}

// Check first element fields
$first = $data[0];
$first = $data[2];
$this->assertEquals('http://domain.tld/?WDWyig', $first['url']);
$this->assertEquals('WDWyig', $first['shorturl']);
$this->assertEquals('Link title: @website', $first['title']);
Expand All @@ -120,7 +120,7 @@ public function testGetLinks()
$this->assertEmpty($first['updated']);

// Multi tags
$link = $data[1];
$link = $data[3];
$this->assertEquals(7, count($link['tags']));

// Update date
Expand All @@ -138,7 +138,7 @@ public function testGetLinksOffsetLimit()
{
$env = Environment::mock([
'REQUEST_METHOD' => 'GET',
'QUERY_STRING' => 'offset=1&limit=1'
'QUERY_STRING' => 'offset=3&limit=1'
]);
$request = Request::createFromEnvironment($env);
$response = $this->controller->getLinks($request, new Response());
Expand All @@ -164,7 +164,7 @@ public function testGetLinksLimitAll()
$data = json_decode((string) $response->getBody(), true);
$this->assertEquals($this->refDB->countLinks(), count($data));
// Check order
$order = [41, 8, 6, 7, 0, 1, 9, 4, 42];
$order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
$cpt = 0;
foreach ($data as $link) {
$this->assertEquals(self::NB_FIELDS_LINK, count($link));
Expand Down Expand Up @@ -205,7 +205,8 @@ public function testGetLinksVisibilityAll()
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode((string)$response->getBody(), true);
$this->assertEquals($this->refDB->countLinks(), count($data));
$this->assertEquals(41, $data[0]['id']);
$this->assertEquals(10, $data[0]['id']);
$this->assertEquals(41, $data[2]['id']);
$this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
}

Expand Down Expand Up @@ -243,7 +244,8 @@ public function testGetLinksVisibilityPublic()
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode((string)$response->getBody(), true);
$this->assertEquals($this->refDB->countPublicLinks(), count($data));
$this->assertEquals(41, $data[0]['id']);
$this->assertEquals(10, $data[0]['id']);
$this->assertEquals(41, $data[2]['id']);
$this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
}

Expand Down Expand Up @@ -413,8 +415,9 @@ public function testGetLinksSearchTags()
$response = $this->controller->getLinks($request, new Response());
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode((string) $response->getBody(), true);
$this->assertEquals(9, count($data));
$this->assertEquals(41, $data[0]['id']);
$this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, count($data));
$this->assertEquals(10, $data[0]['id']);
$this->assertEquals(41, $data[2]['id']);

// wildcard: optional ('*' does not need to expand)
$env = Environment::mock([
Expand Down
Loading

0 comments on commit abca238

Please sign in to comment.