aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2018-05-22 22:44:38 +0200
committerArthurHoaro <arthur@hoa.ro>2018-10-06 12:55:05 +0200
commit4154c25b5f2f8044a37d7f84e04173bb54f2375b (patch)
treee7f61835072a54eee8590286496bdbbbef0e4a37
parent10a7b5cee96a742fbe86edbea977f3c55c92e9aa (diff)
downloadShaarli-4154c25b5f2f8044a37d7f84e04173bb54f2375b.tar.gz
Shaarli-4154c25b5f2f8044a37d7f84e04173bb54f2375b.tar.zst
Shaarli-4154c25b5f2f8044a37d7f84e04173bb54f2375b.zip
Add a button to set links as sticky
Meaning that they always appear on top of all links Fixes #186
-rw-r--r--application/LinkDB.php3
-rw-r--r--application/Router.php6
-rw-r--r--application/Updater.php20
-rw-r--r--assets/default/scss/shaarli.scss12
-rw-r--r--index.php19
-rw-r--r--tests/FeedBuilderTest.php18
-rw-r--r--tests/LinkDBTest.php10
-rw-r--r--tests/NetscapeBookmarkUtils/BookmarkExportTest.php4
-rw-r--r--tests/Updater/UpdaterTest.php61
-rw-r--r--tests/api/controllers/links/GetLinksTest.php21
-rw-r--r--tests/utils/ReferenceLinkDB.php45
-rw-r--r--tpl/default/linklist.html6
12 files changed, 199 insertions, 26 deletions
diff --git a/application/LinkDB.php b/application/LinkDB.php
index cd0f2967..cdd68cfb 100644
--- a/application/LinkDB.php
+++ b/application/LinkDB.php
@@ -537,6 +537,9 @@ You use the community supported version of the original Shaarli project, by Seba
537 $order = $order === 'ASC' ? -1 : 1; 537 $order = $order === 'ASC' ? -1 : 1;
538 // Reorder array by dates. 538 // Reorder array by dates.
539 usort($this->links, function($a, $b) use ($order) { 539 usort($this->links, function($a, $b) use ($order) {
540 if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
541 return $a['sticky'] ? -1 : 1;
542 }
540 return $a['created'] < $b['created'] ? 1 * $order : -1 * $order; 543 return $a['created'] < $b['created'] ? 1 * $order : -1 * $order;
541 }); 544 });
542 545
diff --git a/application/Router.php b/application/Router.php
index bf86b884..beb3165b 100644
--- a/application/Router.php
+++ b/application/Router.php
@@ -37,6 +37,8 @@ class Router
37 37
38 public static $PAGE_DELETELINK = 'delete_link'; 38 public static $PAGE_DELETELINK = 'delete_link';
39 39
40 public static $PAGE_PINLINK = 'pin';
41
40 public static $PAGE_EXPORT = 'export'; 42 public static $PAGE_EXPORT = 'export';
41 43
42 public static $PAGE_IMPORT = 'import'; 44 public static $PAGE_IMPORT = 'import';
@@ -146,6 +148,10 @@ class Router
146 return self::$PAGE_DELETELINK; 148 return self::$PAGE_DELETELINK;
147 } 149 }
148 150
151 if (startsWith($query, 'do='. self::$PAGE_PINLINK)) {
152 return self::$PAGE_PINLINK;
153 }
154
149 if (startsWith($query, 'do='. self::$PAGE_EXPORT)) { 155 if (startsWith($query, 'do='. self::$PAGE_EXPORT)) {
150 return self::$PAGE_EXPORT; 156 return self::$PAGE_EXPORT;
151 } 157 }
diff --git a/application/Updater.php b/application/Updater.php
index 480bff82..5dde47cb 100644
--- a/application/Updater.php
+++ b/application/Updater.php
@@ -517,6 +517,26 @@ class Updater
517 517
518 return true; 518 return true;
519 } 519 }
520
521 /**
522 * Set sticky = false on all links
523 *
524 * @return bool true if the update is successful, false otherwise.
525 */
526 public function updateMethodSetSticky()
527 {
528 foreach ($this->linkDB as $key => $link) {
529 if (isset($link['sticky'])) {
530 return true;
531 }
532 $link['sticky'] = false;
533 $this->linkDB[$key] = $link;
534 }
535
536 $this->linkDB->save($this->conf->get('resource.page_cache'));
537
538 return true;
539 }
520} 540}
521 541
522/** 542/**
diff --git a/assets/default/scss/shaarli.scss b/assets/default/scss/shaarli.scss
index b8578ea6..037183dd 100644
--- a/assets/default/scss/shaarli.scss
+++ b/assets/default/scss/shaarli.scss
@@ -755,6 +755,14 @@ body,
755 font-size: 1.3em; 755 font-size: 1.3em;
756} 756}
757 757
758.pin-link {
759 font-size: 1.3em;
760}
761
762.pinned-link {
763 color: #0b5ea6 !important;
764}
765
758.linklist-item-description { 766.linklist-item-description {
759 position: relative; 767 position: relative;
760 padding: 0 10px; 768 padding: 0 10px;
@@ -848,6 +856,10 @@ body,
848 margin: 0 7px; 856 margin: 0 7px;
849} 857}
850 858
859.ctrl-delete {
860 margin: 0 7px 0 0;
861}
862
851// 64em -> lg 863// 64em -> lg
852@media screen and (max-width: 64em) { 864@media screen and (max-width: 64em) {
853 .linklist-item-infos-url { 865 .linklist-item-infos-url {
diff --git a/index.php b/index.php
index 0ef33633..b702bd13 100644
--- a/index.php
+++ b/index.php
@@ -1353,6 +1353,25 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
1353 exit; 1353 exit;
1354 } 1354 }
1355 1355
1356 if ($targetPage == Router::$PAGE_PINLINK) {
1357 if (! isset($_GET['id']) || empty($LINKSDB[$_GET['id']])) {
1358 // FIXME! Use a proper error system.
1359 $msg = t('Invalid link ID provided');
1360 echo '<script>alert("'. $msg .'");document.location=\''. index_url($_SERVER) .'\';</script>';
1361 exit;
1362 }
1363 if (! $sessionManager->checkToken($_GET['token'])) {
1364 die('Wrong token.');
1365 }
1366
1367 $link = $LINKSDB[$_GET['id']];
1368 $link['sticky'] = ! $link['sticky'];
1369 $LINKSDB[(int) $_GET['id']] = $link;
1370 $LINKSDB->save($conf->get('resource.page_cache'));
1371 header('Location: '.index_url($_SERVER));
1372 exit;
1373 }
1374
1356 if ($targetPage == Router::$PAGE_EXPORT) { 1375 if ($targetPage == Router::$PAGE_EXPORT) {
1357 // Export links as a Netscape Bookmarks file 1376 // Export links as a Netscape Bookmarks file
1358 1377
diff --git a/tests/FeedBuilderTest.php b/tests/FeedBuilderTest.php
index a590306d..4ca58e5a 100644
--- a/tests/FeedBuilderTest.php
+++ b/tests/FeedBuilderTest.php
@@ -82,8 +82,8 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
82 $this->assertFalse($data['usepermalinks']); 82 $this->assertFalse($data['usepermalinks']);
83 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); 83 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
84 84
85 // Test first link (note link) 85 // Test first not pinned link (note link)
86 $link = reset($data['links']); 86 $link = $data['links'][array_keys($data['links'])[2]];
87 $this->assertEquals(41, $link['id']); 87 $this->assertEquals(41, $link['id']);
88 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); 88 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
89 $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); 89 $this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
@@ -119,7 +119,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
119 $data = $feedBuilder->buildData(); 119 $data = $feedBuilder->buildData();
120 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); 120 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
121 $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']); 121 $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']);
122 $link = reset($data['links']); 122 $link = $data['links'][array_keys($data['links'])[2]];
123 $this->assertRegExp('/2015-03-10T11:46:51\+\d{2}:\d{2}/', $link['pub_iso_date']); 123 $this->assertRegExp('/2015-03-10T11:46:51\+\d{2}:\d{2}/', $link['pub_iso_date']);
124 $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['links'][8]['up_iso_date']); 124 $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['links'][8]['up_iso_date']);
125 } 125 }
@@ -148,13 +148,13 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
148 public function testBuildDataCount() 148 public function testBuildDataCount()
149 { 149 {
150 $criteria = array( 150 $criteria = array(
151 'nb' => '1', 151 'nb' => '3',
152 ); 152 );
153 $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false); 153 $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false);
154 $feedBuilder->setLocale(self::$LOCALE); 154 $feedBuilder->setLocale(self::$LOCALE);
155 $data = $feedBuilder->buildData(); 155 $data = $feedBuilder->buildData();
156 $this->assertEquals(1, count($data['links'])); 156 $this->assertEquals(3, count($data['links']));
157 $link = array_shift($data['links']); 157 $link = $data['links'][array_keys($data['links'])[2]];
158 $this->assertEquals(41, $link['id']); 158 $this->assertEquals(41, $link['id']);
159 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); 159 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
160 } 160 }
@@ -171,7 +171,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
171 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); 171 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
172 $this->assertTrue($data['usepermalinks']); 172 $this->assertTrue($data['usepermalinks']);
173 // First link is a permalink 173 // First link is a permalink
174 $link = array_shift($data['links']); 174 $link = $data['links'][array_keys($data['links'])[2]];
175 $this->assertEquals(41, $link['id']); 175 $this->assertEquals(41, $link['id']);
176 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); 176 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
177 $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); 177 $this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
@@ -179,7 +179,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
179 $this->assertContains('Direct link', $link['description']); 179 $this->assertContains('Direct link', $link['description']);
180 $this->assertContains('http://host.tld/?WDWyig', $link['description']); 180 $this->assertContains('http://host.tld/?WDWyig', $link['description']);
181 // Second link is a direct link 181 // Second link is a direct link
182 $link = array_shift($data['links']); 182 $link = $data['links'][array_keys($data['links'])[3]];
183 $this->assertEquals(8, $link['id']); 183 $this->assertEquals(8, $link['id']);
184 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114633'), $link['created']); 184 $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150310_114633'), $link['created']);
185 $this->assertEquals('http://host.tld/?RttfEw', $link['guid']); 185 $this->assertEquals('http://host.tld/?RttfEw', $link['guid']);
@@ -237,7 +237,7 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
237 ); 237 );
238 238
239 // Test first link (note link) 239 // Test first link (note link)
240 $link = array_shift($data['links']); 240 $link = $data['links'][array_keys($data['links'])[2]];
241 $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']); 241 $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']);
242 $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']); 242 $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']);
243 $this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']); 243 $this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']);
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php
index 3b980878..fcab76f6 100644
--- a/tests/LinkDBTest.php
+++ b/tests/LinkDBTest.php
@@ -239,12 +239,12 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
239 public function testDays() 239 public function testDays()
240 { 240 {
241 $this->assertEquals( 241 $this->assertEquals(
242 array('20100310', '20121206', '20130614', '20150310'), 242 array('20100309', '20100310', '20121206', '20121207', '20130614', '20150310'),
243 self::$publicLinkDB->days() 243 self::$publicLinkDB->days()
244 ); 244 );
245 245
246 $this->assertEquals( 246 $this->assertEquals(
247 array('20100310', '20121206', '20130614', '20141125', '20150310'), 247 array('20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'),
248 self::$privateLinkDB->days() 248 self::$privateLinkDB->days()
249 ); 249 );
250 } 250 }
@@ -475,13 +475,15 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
475 public function testReorderLinksDesc() 475 public function testReorderLinksDesc()
476 { 476 {
477 self::$privateLinkDB->reorder('ASC'); 477 self::$privateLinkDB->reorder('ASC');
478 $linkIds = array(42, 4, 9, 1, 0, 7, 6, 8, 41); 478 $stickyIds = [11, 10];
479 $standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41];
480 $linkIds = array_merge($stickyIds, $standardIds);
479 $cpt = 0; 481 $cpt = 0;
480 foreach (self::$privateLinkDB as $key => $value) { 482 foreach (self::$privateLinkDB as $key => $value) {
481 $this->assertEquals($linkIds[$cpt++], $key); 483 $this->assertEquals($linkIds[$cpt++], $key);
482 } 484 }
483 self::$privateLinkDB->reorder('DESC'); 485 self::$privateLinkDB->reorder('DESC');
484 $linkIds = array_reverse($linkIds); 486 $linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds));
485 $cpt = 0; 487 $cpt = 0;
486 foreach (self::$privateLinkDB as $key => $value) { 488 foreach (self::$privateLinkDB as $key => $value) {
487 $this->assertEquals($linkIds[$cpt++], $key); 489 $this->assertEquals($linkIds[$cpt++], $key);
diff --git a/tests/NetscapeBookmarkUtils/BookmarkExportTest.php b/tests/NetscapeBookmarkUtils/BookmarkExportTest.php
index 6a47bbb9..77fbd5f3 100644
--- a/tests/NetscapeBookmarkUtils/BookmarkExportTest.php
+++ b/tests/NetscapeBookmarkUtils/BookmarkExportTest.php
@@ -110,7 +110,7 @@ class BookmarkExportTest extends PHPUnit_Framework_TestCase
110 $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, ''); 110 $links = NetscapeBookmarkUtils::filterAndFormat(self::$linkDb, 'public', false, '');
111 $this->assertEquals( 111 $this->assertEquals(
112 '?WDWyig', 112 '?WDWyig',
113 $links[0]['url'] 113 $links[2]['url']
114 ); 114 );
115 } 115 }
116 116
@@ -128,7 +128,7 @@ class BookmarkExportTest extends PHPUnit_Framework_TestCase
128 ); 128 );
129 $this->assertEquals( 129 $this->assertEquals(
130 $indexUrl . '?WDWyig', 130 $indexUrl . '?WDWyig',
131 $links[0]['url'] 131 $links[2]['url']
132 ); 132 );
133 } 133 }
134} 134}
diff --git a/tests/Updater/UpdaterTest.php b/tests/Updater/UpdaterTest.php
index cacee2d2..870f169a 100644
--- a/tests/Updater/UpdaterTest.php
+++ b/tests/Updater/UpdaterTest.php
@@ -688,6 +688,7 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
688 } 688 }
689 689
690 /** 690 /**
691<<<<<<< HEAD
691 * Test updateMethodWebThumbnailer with thumbnails enabled. 692 * Test updateMethodWebThumbnailer with thumbnails enabled.
692 */ 693 */
693 public function testUpdateMethodWebThumbnailerEnabled() 694 public function testUpdateMethodWebThumbnailerEnabled()
@@ -732,4 +733,64 @@ $GLOBALS[\'privateLinkByDefault\'] = true;';
732 $this->assertEquals(53, $this->conf->get('thumbnails.height')); 733 $this->assertEquals(53, $this->conf->get('thumbnails.height'));
733 $this->assertTrue(empty($_SESSION['warnings'])); 734 $this->assertTrue(empty($_SESSION['warnings']));
734 } 735 }
736
737 /**
738 * Test updateMethodSetSticky().
739 */
740 public function testUpdateStickyValid()
741 {
742 $blank = [
743 'id' => 1,
744 'url' => 'z',
745 'title' => '',
746 'description' => '',
747 'tags' => '',
748 'created' => new DateTime(),
749 ];
750 $links = [
751 1 => ['id' => 1] + $blank,
752 2 => ['id' => 2] + $blank,
753 ];
754 $refDB = new ReferenceLinkDB();
755 $refDB->setLinks($links);
756 $refDB->write(self::$testDatastore);
757 $linkDB = new LinkDB(self::$testDatastore, true, false);
758
759 $updater = new Updater(array(), $linkDB, $this->conf, true);
760 $this->assertTrue($updater->updateMethodSetSticky());
761
762 $linkDB = new LinkDB(self::$testDatastore, true, false);
763 foreach ($linkDB as $link) {
764 $this->assertFalse($link['sticky']);
765 }
766 }
767
768 /**
769 * Test updateMethodSetSticky().
770 */
771 public function testUpdateStickyNothingToDo()
772 {
773 $blank = [
774 'id' => 1,
775 'url' => 'z',
776 'title' => '',
777 'description' => '',
778 'tags' => '',
779 'created' => new DateTime(),
780 ];
781 $links = [
782 1 => ['id' => 1, 'sticky' => true] + $blank,
783 2 => ['id' => 2] + $blank,
784 ];
785 $refDB = new ReferenceLinkDB();
786 $refDB->setLinks($links);
787 $refDB->write(self::$testDatastore);
788 $linkDB = new LinkDB(self::$testDatastore, true, false);
789
790 $updater = new Updater(array(), $linkDB, $this->conf, true);
791 $this->assertTrue($updater->updateMethodSetSticky());
792
793 $linkDB = new LinkDB(self::$testDatastore, true, false);
794 $this->assertTrue($linkDB[1]['sticky']);
795 }
735} 796}
diff --git a/tests/api/controllers/links/GetLinksTest.php b/tests/api/controllers/links/GetLinksTest.php
index d22ed3bf..64f02774 100644
--- a/tests/api/controllers/links/GetLinksTest.php
+++ b/tests/api/controllers/links/GetLinksTest.php
@@ -95,7 +95,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
95 $this->assertEquals($this->refDB->countLinks(), count($data)); 95 $this->assertEquals($this->refDB->countLinks(), count($data));
96 96
97 // Check order 97 // Check order
98 $order = [41, 8, 6, 7, 0, 1, 9, 4, 42]; 98 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
99 $cpt = 0; 99 $cpt = 0;
100 foreach ($data as $link) { 100 foreach ($data as $link) {
101 $this->assertEquals(self::NB_FIELDS_LINK, count($link)); 101 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
@@ -103,7 +103,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
103 } 103 }
104 104
105 // Check first element fields 105 // Check first element fields
106 $first = $data[0]; 106 $first = $data[2];
107 $this->assertEquals('http://domain.tld/?WDWyig', $first['url']); 107 $this->assertEquals('http://domain.tld/?WDWyig', $first['url']);
108 $this->assertEquals('WDWyig', $first['shorturl']); 108 $this->assertEquals('WDWyig', $first['shorturl']);
109 $this->assertEquals('Link title: @website', $first['title']); 109 $this->assertEquals('Link title: @website', $first['title']);
@@ -120,7 +120,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
120 $this->assertEmpty($first['updated']); 120 $this->assertEmpty($first['updated']);
121 121
122 // Multi tags 122 // Multi tags
123 $link = $data[1]; 123 $link = $data[3];
124 $this->assertEquals(7, count($link['tags'])); 124 $this->assertEquals(7, count($link['tags']));
125 125
126 // Update date 126 // Update date
@@ -138,7 +138,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
138 { 138 {
139 $env = Environment::mock([ 139 $env = Environment::mock([
140 'REQUEST_METHOD' => 'GET', 140 'REQUEST_METHOD' => 'GET',
141 'QUERY_STRING' => 'offset=1&limit=1' 141 'QUERY_STRING' => 'offset=3&limit=1'
142 ]); 142 ]);
143 $request = Request::createFromEnvironment($env); 143 $request = Request::createFromEnvironment($env);
144 $response = $this->controller->getLinks($request, new Response()); 144 $response = $this->controller->getLinks($request, new Response());
@@ -164,7 +164,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
164 $data = json_decode((string) $response->getBody(), true); 164 $data = json_decode((string) $response->getBody(), true);
165 $this->assertEquals($this->refDB->countLinks(), count($data)); 165 $this->assertEquals($this->refDB->countLinks(), count($data));
166 // Check order 166 // Check order
167 $order = [41, 8, 6, 7, 0, 1, 9, 4, 42]; 167 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
168 $cpt = 0; 168 $cpt = 0;
169 foreach ($data as $link) { 169 foreach ($data as $link) {
170 $this->assertEquals(self::NB_FIELDS_LINK, count($link)); 170 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
@@ -205,7 +205,8 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
205 $this->assertEquals(200, $response->getStatusCode()); 205 $this->assertEquals(200, $response->getStatusCode());
206 $data = json_decode((string)$response->getBody(), true); 206 $data = json_decode((string)$response->getBody(), true);
207 $this->assertEquals($this->refDB->countLinks(), count($data)); 207 $this->assertEquals($this->refDB->countLinks(), count($data));
208 $this->assertEquals(41, $data[0]['id']); 208 $this->assertEquals(10, $data[0]['id']);
209 $this->assertEquals(41, $data[2]['id']);
209 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); 210 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
210 } 211 }
211 212
@@ -243,7 +244,8 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
243 $this->assertEquals(200, $response->getStatusCode()); 244 $this->assertEquals(200, $response->getStatusCode());
244 $data = json_decode((string)$response->getBody(), true); 245 $data = json_decode((string)$response->getBody(), true);
245 $this->assertEquals($this->refDB->countPublicLinks(), count($data)); 246 $this->assertEquals($this->refDB->countPublicLinks(), count($data));
246 $this->assertEquals(41, $data[0]['id']); 247 $this->assertEquals(10, $data[0]['id']);
248 $this->assertEquals(41, $data[2]['id']);
247 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); 249 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
248 } 250 }
249 251
@@ -413,8 +415,9 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase
413 $response = $this->controller->getLinks($request, new Response()); 415 $response = $this->controller->getLinks($request, new Response());
414 $this->assertEquals(200, $response->getStatusCode()); 416 $this->assertEquals(200, $response->getStatusCode());
415 $data = json_decode((string) $response->getBody(), true); 417 $data = json_decode((string) $response->getBody(), true);
416 $this->assertEquals(9, count($data)); 418 $this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, count($data));
417 $this->assertEquals(41, $data[0]['id']); 419 $this->assertEquals(10, $data[0]['id']);
420 $this->assertEquals(41, $data[2]['id']);
418 421
419 // wildcard: optional ('*' does not need to expand) 422 // wildcard: optional ('*' does not need to expand)
420 $env = Environment::mock([ 423 $env = Environment::mock([
diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php
index e887aa78..7426ad07 100644
--- a/tests/utils/ReferenceLinkDB.php
+++ b/tests/utils/ReferenceLinkDB.php
@@ -4,7 +4,7 @@
4 */ 4 */
5class ReferenceLinkDB 5class ReferenceLinkDB
6{ 6{
7 public static $NB_LINKS_TOTAL = 9; 7 public static $NB_LINKS_TOTAL = 11;
8 8
9 private $_links = array(); 9 private $_links = array();
10 private $_publicCount = 0; 10 private $_publicCount = 0;
@@ -16,6 +16,32 @@ class ReferenceLinkDB
16 public function __construct() 16 public function __construct()
17 { 17 {
18 $this->addLink( 18 $this->addLink(
19 11,
20 'Pined older',
21 '?PCRizQ',
22 'This is an older pinned link',
23 0,
24 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20100309_101010'),
25 '',
26 null,
27 'PCRizQ',
28 true
29 );
30
31 $this->addLink(
32 10,
33 'Pined',
34 '?0gCTjQ',
35 'This is a pinned link',
36 0,
37 DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121207_152312'),
38 '',
39 null,
40 '0gCTjQ',
41 true
42 );
43
44 $this->addLink(
19 41, 45 41,
20 'Link title: @website', 46 'Link title: @website',
21 '?WDWyig', 47 '?WDWyig',
@@ -114,7 +140,17 @@ class ReferenceLinkDB
114 /** 140 /**
115 * Adds a new link 141 * Adds a new link
116 */ 142 */
117 protected function addLink($id, $title, $url, $description, $private, $date, $tags, $updated = '', $shorturl = '') 143 protected function addLink(
144 $id,
145 $title,
146 $url,
147 $description,
148 $private,
149 $date,
150 $tags,
151 $updated = '',
152 $shorturl = '',
153 $pinned = false)
118 { 154 {
119 $link = array( 155 $link = array(
120 'id' => $id, 156 'id' => $id,
@@ -126,6 +162,7 @@ class ReferenceLinkDB
126 'created' => $date, 162 'created' => $date,
127 'updated' => $updated, 163 'updated' => $updated,
128 'shorturl' => $shorturl ? $shorturl : smallHash($date->format(LinkDB::LINK_DATE_FORMAT) . $id), 164 'shorturl' => $shorturl ? $shorturl : smallHash($date->format(LinkDB::LINK_DATE_FORMAT) . $id),
165 'sticky' => $pinned
129 ); 166 );
130 $this->_links[$id] = $link; 167 $this->_links[$id] = $link;
131 168
@@ -165,6 +202,10 @@ class ReferenceLinkDB
165 $order = $order === 'ASC' ? -1 : 1; 202 $order = $order === 'ASC' ? -1 : 1;
166 // Reorder array by dates. 203 // Reorder array by dates.
167 usort($this->_links, function($a, $b) use ($order) { 204 usort($this->_links, function($a, $b) use ($order) {
205 if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
206 return $a['sticky'] ? -1 : 1;
207 }
208
168 return $a['created'] < $b['created'] ? 1 * $order : -1 * $order; 209 return $a['created'] < $b['created'] ? 1 * $order : -1 * $order;
169 }); 210 });
170 } 211 }
diff --git a/tpl/default/linklist.html b/tpl/default/linklist.html
index 8ea2ce66..aaa9bc74 100644
--- a/tpl/default/linklist.html
+++ b/tpl/default/linklist.html
@@ -201,6 +201,12 @@
201 <i class="fa fa-trash"></i> 201 <i class="fa fa-trash"></i>
202 </a> 202 </a>
203 </span> 203 </span>
204 <span class="linklist-item-infos-controls-item ctrl-pin">
205 <a href="?do=pin&amp;id={$value.id}&amp;token={$token}"
206 title="{$strDelete}" class="pin-link {if="$value.sticky"}pinned-link{/if} pure-u-0 pure-u-lg-visible">
207 <i class="fa fa-thumb-tack"></i>
208 </a>
209 </span>
204 </div> 210 </div>
205 {/if} 211 {/if}
206 <a href="?{$value.shorturl}" title="{$strPermalink}"> 212 <a href="?{$value.shorturl}" title="{$strPermalink}">