aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--application/FeedBuilder.php6
-rw-r--r--application/LinkFilter.php37
-rw-r--r--application/NetscapeBookmarkUtils.php25
-rw-r--r--application/Updater.php6
-rw-r--r--index.php92
-rw-r--r--plugins/isso/isso.php6
-rw-r--r--tpl/daily.html4
-rw-r--r--tpl/editlink.html3
-rw-r--r--tpl/linklist.html6
9 files changed, 100 insertions, 85 deletions
diff --git a/application/FeedBuilder.php b/application/FeedBuilder.php
index 4036a7cc..bfdf2fd3 100644
--- a/application/FeedBuilder.php
+++ b/application/FeedBuilder.php
@@ -143,7 +143,7 @@ class FeedBuilder
143 */ 143 */
144 protected function buildItem($link, $pageaddr) 144 protected function buildItem($link, $pageaddr)
145 { 145 {
146 $link['guid'] = $pageaddr .'?'. smallHash($link['linkdate']); 146 $link['guid'] = $pageaddr .'?'. smallHash($link['created']->format('Ymd_His'));
147 // Check for both signs of a note: starting with ? and 7 chars long. 147 // Check for both signs of a note: starting with ? and 7 chars long.
148 if ($link['url'][0] === '?' && strlen($link['url']) === 7) { 148 if ($link['url'][0] === '?' && strlen($link['url']) === 7) {
149 $link['url'] = $pageaddr . $link['url']; 149 $link['url'] = $pageaddr . $link['url'];
@@ -156,12 +156,12 @@ class FeedBuilder
156 $link['description'] = format_description($link['description'], '', $pageaddr); 156 $link['description'] = format_description($link['description'], '', $pageaddr);
157 $link['description'] .= PHP_EOL .'<br>&#8212; '. $permalink; 157 $link['description'] .= PHP_EOL .'<br>&#8212; '. $permalink;
158 158
159 $pubDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['linkdate']); 159 $pubDate = $link['created'];
160 $link['pub_iso_date'] = $this->getIsoDate($pubDate); 160 $link['pub_iso_date'] = $this->getIsoDate($pubDate);
161 161
162 // atom:entry elements MUST contain exactly one atom:updated element. 162 // atom:entry elements MUST contain exactly one atom:updated element.
163 if (!empty($link['updated'])) { 163 if (!empty($link['updated'])) {
164 $upDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['updated']); 164 $upDate = $link['updated'];
165 $link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM); 165 $link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM);
166 } else { 166 } else {
167 $link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);; 167 $link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);;
diff --git a/application/LinkFilter.php b/application/LinkFilter.php
index d4fe28df..7bab46ba 100644
--- a/application/LinkFilter.php
+++ b/application/LinkFilter.php
@@ -33,12 +33,12 @@ class LinkFilter
33 public static $HASHTAG_CHARS = '\p{Pc}\p{N}\p{L}\p{Mn}'; 33 public static $HASHTAG_CHARS = '\p{Pc}\p{N}\p{L}\p{Mn}';
34 34
35 /** 35 /**
36 * @var array all available links. 36 * @var LinkDB all available links.
37 */ 37 */
38 private $links; 38 private $links;
39 39
40 /** 40 /**
41 * @param array $links initialization. 41 * @param LinkDB $links initialization.
42 */ 42 */
43 public function __construct($links) 43 public function __construct($links)
44 { 44 {
@@ -94,18 +94,16 @@ class LinkFilter
94 private function noFilter($privateonly = false) 94 private function noFilter($privateonly = false)
95 { 95 {
96 if (! $privateonly) { 96 if (! $privateonly) {
97 krsort($this->links);
98 return $this->links; 97 return $this->links;
99 } 98 }
100 99
101 $out = array(); 100 $out = array();
102 foreach ($this->links as $value) { 101 foreach ($this->links as $key => $value) {
103 if ($value['private']) { 102 if ($value['private']) {
104 $out[$value['linkdate']] = $value; 103 $out[$key] = $value;
105 } 104 }
106 } 105 }
107 106
108 krsort($out);
109 return $out; 107 return $out;
110 } 108 }
111 109
@@ -121,10 +119,10 @@ class LinkFilter
121 private function filterSmallHash($smallHash) 119 private function filterSmallHash($smallHash)
122 { 120 {
123 $filtered = array(); 121 $filtered = array();
124 foreach ($this->links as $l) { 122 foreach ($this->links as $key => $l) {
125 if ($smallHash == smallHash($l['linkdate'])) { 123 if ($smallHash == smallHash($l['created']->format('Ymd_His'))) {
126 // Yes, this is ugly and slow 124 // Yes, this is ugly and slow
127 $filtered[$l['linkdate']] = $l; 125 $filtered[$key] = $l;
128 return $filtered; 126 return $filtered;
129 } 127 }
130 } 128 }
@@ -188,7 +186,7 @@ class LinkFilter
188 $keys = array('title', 'description', 'url', 'tags'); 186 $keys = array('title', 'description', 'url', 'tags');
189 187
190 // Iterate over every stored link. 188 // Iterate over every stored link.
191 foreach ($this->links as $link) { 189 foreach ($this->links as $id => $link) {
192 190
193 // ignore non private links when 'privatonly' is on. 191 // ignore non private links when 'privatonly' is on.
194 if (! $link['private'] && $privateonly === true) { 192 if (! $link['private'] && $privateonly === true) {
@@ -222,11 +220,10 @@ class LinkFilter
222 } 220 }
223 221
224 if ($found) { 222 if ($found) {
225 $filtered[$link['linkdate']] = $link; 223 $filtered[$id] = $link;
226 } 224 }
227 } 225 }
228 226
229 krsort($filtered);
230 return $filtered; 227 return $filtered;
231 } 228 }
232 229
@@ -256,7 +253,7 @@ class LinkFilter
256 return $filtered; 253 return $filtered;
257 } 254 }
258 255
259 foreach ($this->links as $link) { 256 foreach ($this->links as $key => $link) {
260 // ignore non private links when 'privatonly' is on. 257 // ignore non private links when 'privatonly' is on.
261 if (! $link['private'] && $privateonly === true) { 258 if (! $link['private'] && $privateonly === true) {
262 continue; 259 continue;
@@ -278,10 +275,9 @@ class LinkFilter
278 } 275 }
279 276
280 if ($found) { 277 if ($found) {
281 $filtered[$link['linkdate']] = $link; 278 $filtered[$key] = $link;
282 } 279 }
283 } 280 }
284 krsort($filtered);
285 return $filtered; 281 return $filtered;
286 } 282 }
287 283
@@ -304,13 +300,14 @@ class LinkFilter
304 } 300 }
305 301
306 $filtered = array(); 302 $filtered = array();
307 foreach ($this->links as $l) { 303 foreach ($this->links as $key => $l) {
308 if (startsWith($l['linkdate'], $day)) { 304 if ($l['created']->format('Ymd') == $day) {
309 $filtered[$l['linkdate']] = $l; 305 $filtered[$key] = $l;
310 } 306 }
311 } 307 }
312 ksort($filtered); 308
313 return $filtered; 309 // sort by date ASC
310 return array_reverse($filtered, true);
314 } 311 }
315 312
316 /** 313 /**
diff --git a/application/NetscapeBookmarkUtils.php b/application/NetscapeBookmarkUtils.php
index dd21f05b..8a939adb 100644
--- a/application/NetscapeBookmarkUtils.php
+++ b/application/NetscapeBookmarkUtils.php
@@ -38,7 +38,7 @@ class NetscapeBookmarkUtils
38 if ($link['private'] == 0 && $selection == 'private') { 38 if ($link['private'] == 0 && $selection == 'private') {
39 continue; 39 continue;
40 } 40 }
41 $date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['linkdate']); 41 $date = $link['created'];
42 $link['timestamp'] = $date->getTimestamp(); 42 $link['timestamp'] = $date->getTimestamp();
43 $link['taglist'] = str_replace(' ', ',', $link['tags']); 43 $link['taglist'] = str_replace(' ', ',', $link['tags']);
44 44
@@ -147,7 +147,6 @@ class NetscapeBookmarkUtils
147 'url' => $bkm['uri'], 147 'url' => $bkm['uri'],
148 'description' => $bkm['note'], 148 'description' => $bkm['note'],
149 'private' => $private, 149 'private' => $private,
150 'linkdate'=> '',
151 'tags' => $bkm['tags'] 150 'tags' => $bkm['tags']
152 ); 151 );
153 152
@@ -161,25 +160,21 @@ class NetscapeBookmarkUtils
161 } 160 }
162 161
163 // Overwrite an existing link, keep its date 162 // Overwrite an existing link, keep its date
164 $newLink['linkdate'] = $existingLink['linkdate']; 163 $newLink['id'] = $existingLink['id'];
165 $linkDb[$existingLink['linkdate']] = $newLink; 164 $newLink['created'] = $existingLink['created'];
165 $newLink['updated'] = new DateTime();
166 $linkDb[$existingLink['id']] = $newLink;
166 $importCount++; 167 $importCount++;
167 $overwriteCount++; 168 $overwriteCount++;
168 continue; 169 continue;
169 } 170 }
170 171
171 // Add a new link 172 // Add a new link - @ used for UNIX timestamps
172 $newLinkDate = new DateTime('@'.strval($bkm['time'])); 173 $newLinkDate = new DateTime('@'.strval($bkm['time']));
173 while (!empty($linkDb[$newLinkDate->format(LinkDB::LINK_DATE_FORMAT)])) { 174 $newLinkDate->setTimezone(new DateTimeZone(date_default_timezone_get()));
174 // Ensure the date/time is not already used 175 $newLink['created'] = $newLinkDate;
175 // - this hack is necessary as the date/time acts as a primary key 176 $newLink['id'] = $linkDb->getNextId();
176 // - apply 1 second increments until an unused index is found 177 $linkDb[$newLink['id']] = $newLink;
177 // See https://github.com/shaarli/Shaarli/issues/351
178 $newLinkDate->add(new DateInterval('PT1S'));
179 }
180 $linkDbDate = $newLinkDate->format(LinkDB::LINK_DATE_FORMAT);
181 $newLink['linkdate'] = $linkDbDate;
182 $linkDb[$linkDbDate] = $newLink;
183 $importCount++; 178 $importCount++;
184 } 179 }
185 180
diff --git a/application/Updater.php b/application/Updater.php
index 94b63990..16c8c376 100644
--- a/application/Updater.php
+++ b/application/Updater.php
@@ -218,7 +218,7 @@ class Updater
218 218
219 /** 219 /**
220 * Update the database to use the new ID system, which replaces linkdate primary keys. 220 * Update the database to use the new ID system, which replaces linkdate primary keys.
221 * Also, creation and update dates are now DateTime objects. 221 * Also, creation and update dates are now DateTime objects (done by LinkDB).
222 * 222 *
223 * Since this update is very sensitve (changing the whole database), the datastore will be 223 * Since this update is very sensitve (changing the whole database), the datastore will be
224 * automatically backed up into the file datastore.<datetime>.php. 224 * automatically backed up into the file datastore.<datetime>.php.
@@ -243,10 +243,6 @@ class Updater
243 $links = array_reverse($links); 243 $links = array_reverse($links);
244 $cpt = 0; 244 $cpt = 0;
245 foreach ($links as $l) { 245 foreach ($links as $l) {
246 $l['created'] = DateTime::createFromFormat('Ymd_His', $l['linkdate']);
247 if (! empty($l['updated'])) {
248 $l['updated'] = DateTime::createFromFormat('Ymd_His', $l['updated']);
249 }
250 unset($l['linkdate']); 246 unset($l['linkdate']);
251 $l['id'] = $cpt; 247 $l['id'] = $cpt;
252 $this->linkDB[$cpt++] = $l; 248 $this->linkDB[$cpt++] = $l;
diff --git a/index.php b/index.php
index 5366cb0e..05f06452 100644
--- a/index.php
+++ b/index.php
@@ -564,24 +564,23 @@ function showDailyRSS($conf) {
564 ); 564 );
565 565
566 /* Some Shaarlies may have very few links, so we need to look 566 /* Some Shaarlies may have very few links, so we need to look
567 back in time (rsort()) until we have enough days ($nb_of_days). 567 back in time until we have enough days ($nb_of_days).
568 */ 568 */
569 $linkdates = array(); 569 $ids = array();
570 foreach ($LINKSDB as $linkdate => $value) { 570 foreach ($LINKSDB as $id => $value) {
571 $linkdates[] = $linkdate; 571 $ids[] = $id;
572 } 572 }
573 rsort($linkdates);
574 $nb_of_days = 7; // We take 7 days. 573 $nb_of_days = 7; // We take 7 days.
575 $today = date('Ymd'); 574 $today = date('Ymd');
576 $days = array(); 575 $days = array();
577 576
578 foreach ($linkdates as $linkdate) { 577 foreach ($ids as $id) {
579 $day = substr($linkdate, 0, 8); // Extract day (without time) 578 $day = $LINKSDB[$id]['created']->format('Ymd'); // Extract day (without time)
580 if (strcmp($day,$today) < 0) { 579 if (strcmp($day, $today) < 0) {
581 if (empty($days[$day])) { 580 if (empty($days[$day])) {
582 $days[$day] = array(); 581 $days[$day] = array();
583 } 582 }
584 $days[$day][] = $linkdate; 583 $days[$day][] = $id;
585 } 584 }
586 585
587 if (count($days) > $nb_of_days) { 586 if (count($days) > $nb_of_days) {
@@ -601,7 +600,7 @@ function showDailyRSS($conf) {
601 echo '<copyright>'. $pageaddr .'</copyright>'. PHP_EOL; 600 echo '<copyright>'. $pageaddr .'</copyright>'. PHP_EOL;
602 601
603 // For each day. 602 // For each day.
604 foreach ($days as $day => $linkdates) { 603 foreach ($days as $day => $ids) {
605 $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000'); 604 $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000');
606 $absurl = escape(index_url($_SERVER).'?do=daily&day='.$day); // Absolute URL of the corresponding "Daily" page. 605 $absurl = escape(index_url($_SERVER).'?do=daily&day='.$day); // Absolute URL of the corresponding "Daily" page.
607 606
@@ -609,16 +608,15 @@ function showDailyRSS($conf) {
609 $links = array(); 608 $links = array();
610 609
611 // We pre-format some fields for proper output. 610 // We pre-format some fields for proper output.
612 foreach ($linkdates as $linkdate) { 611 foreach ($ids as $id) {
613 $l = $LINKSDB[$linkdate]; 612 $l = $LINKSDB[$id];
614 $l['formatedDescription'] = format_description($l['description'], $conf->get('redirector.url')); 613 $l['formatedDescription'] = format_description($l['description'], $conf->get('redirector.url'));
615 $l['thumbnail'] = thumbnail($conf, $l['url']); 614 $l['thumbnail'] = thumbnail($conf, $l['url']);
616 $l_date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $l['linkdate']); 615 $l['timestamp'] = $l['created']->getTimestamp();
617 $l['timestamp'] = $l_date->getTimestamp();
618 if (startsWith($l['url'], '?')) { 616 if (startsWith($l['url'], '?')) {
619 $l['url'] = index_url($_SERVER) . $l['url']; // make permalink URL absolute 617 $l['url'] = index_url($_SERVER) . $l['url']; // make permalink URL absolute
620 } 618 }
621 $links[$linkdate] = $l; 619 $links[$id] = $l;
622 } 620 }
623 621
624 // Then build the HTML for this day: 622 // Then build the HTML for this day:
@@ -677,11 +675,11 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager)
677 675
678 $taglist = explode(' ',$link['tags']); 676 $taglist = explode(' ',$link['tags']);
679 uasort($taglist, 'strcasecmp'); 677 uasort($taglist, 'strcasecmp');
678 $linksToDisplay[$key]['shorturl'] = smallHash($link['created']->format('Ymd_His'));
680 $linksToDisplay[$key]['taglist']=$taglist; 679 $linksToDisplay[$key]['taglist']=$taglist;
681 $linksToDisplay[$key]['formatedDescription'] = format_description($link['description'], $conf->get('redirector.url')); 680 $linksToDisplay[$key]['formatedDescription'] = format_description($link['description'], $conf->get('redirector.url'));
682 $linksToDisplay[$key]['thumbnail'] = thumbnail($conf, $link['url']); 681 $linksToDisplay[$key]['thumbnail'] = thumbnail($conf, $link['url']);
683 $date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['linkdate']); 682 $linksToDisplay[$key]['timestamp'] = $link['created']->getTimestamp();
684 $linksToDisplay[$key]['timestamp'] = $date->getTimestamp();
685 } 683 }
686 684
687 /* We need to spread the articles on 3 columns. 685 /* We need to spread the articles on 3 columns.
@@ -831,7 +829,7 @@ function renderPage($conf, $pluginManager)
831 // Get only links which have a thumbnail. 829 // Get only links which have a thumbnail.
832 foreach($links as $link) 830 foreach($links as $link)
833 { 831 {
834 $permalink='?'.escape(smallHash($link['linkdate'])); 832 $permalink='?'.escape(smallHash($link['created']->format('Ymd_His')));
835 $thumb=lazyThumbnail($conf, $link['url'],$permalink); 833 $thumb=lazyThumbnail($conf, $link['url'],$permalink);
836 if ($thumb!='') // Only output links which have a thumbnail. 834 if ($thumb!='') // Only output links which have a thumbnail.
837 { 835 {
@@ -1245,13 +1243,28 @@ function renderPage($conf, $pluginManager)
1245 // -------- User clicked the "Save" button when editing a link: Save link to database. 1243 // -------- User clicked the "Save" button when editing a link: Save link to database.
1246 if (isset($_POST['save_edit'])) 1244 if (isset($_POST['save_edit']))
1247 { 1245 {
1248 $linkdate = $_POST['lf_linkdate'];
1249 $updated = isset($LINKSDB[$linkdate]) ? strval(date('Ymd_His')) : false;
1250
1251 // Go away! 1246 // Go away!
1252 if (! tokenOk($_POST['token'])) { 1247 if (! tokenOk($_POST['token'])) {
1253 die('Wrong token.'); 1248 die('Wrong token.');
1254 } 1249 }
1250
1251 // lf_id should only be present if the link exists.
1252 $id = !empty($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : $LINKSDB->getNextId();
1253 // Linkdate is kept here to:
1254 // - use the same permalink for notes as they're displayed when creating them
1255 // - let users hack creation date of their posts
1256 // See: https://github.com/shaarli/Shaarli/wiki/Datastore-hacks#changing-the-timestamp-for-a-link
1257 $linkdate = escape($_POST['lf_linkdate']);
1258 if (isset($LINKSDB[$id])) {
1259 // Edit
1260 $created = DateTime::createFromFormat('Ymd_His', $linkdate);
1261 $updated = new DateTime();
1262 } else {
1263 // New link
1264 $created = DateTime::createFromFormat('Ymd_His', $linkdate);
1265 $updated = null;
1266 }
1267
1255 // Remove multiple spaces. 1268 // Remove multiple spaces.
1256 $tags = trim(preg_replace('/\s\s+/', ' ', $_POST['lf_tags'])); 1269 $tags = trim(preg_replace('/\s\s+/', ' ', $_POST['lf_tags']));
1257 // Remove first '-' char in tags. 1270 // Remove first '-' char in tags.
@@ -1268,14 +1281,16 @@ function renderPage($conf, $pluginManager)
1268 } 1281 }
1269 1282
1270 $link = array( 1283 $link = array(
1284 'id' => $id,
1271 'title' => trim($_POST['lf_title']), 1285 'title' => trim($_POST['lf_title']),
1272 'url' => $url, 1286 'url' => $url,
1273 'description' => $_POST['lf_description'], 1287 'description' => $_POST['lf_description'],
1274 'private' => (isset($_POST['lf_private']) ? 1 : 0), 1288 'private' => (isset($_POST['lf_private']) ? 1 : 0),
1275 'linkdate' => $linkdate, 1289 'created' => $created,
1276 'updated' => $updated, 1290 'updated' => $updated,
1277 'tags' => str_replace(',', ' ', $tags) 1291 'tags' => str_replace(',', ' ', $tags)
1278 ); 1292 );
1293
1279 // If title is empty, use the URL as title. 1294 // If title is empty, use the URL as title.
1280 if ($link['title'] == '') { 1295 if ($link['title'] == '') {
1281 $link['title'] = $link['url']; 1296 $link['title'] = $link['url'];
@@ -1283,7 +1298,7 @@ function renderPage($conf, $pluginManager)
1283 1298
1284 $pluginManager->executeHooks('save_link', $link); 1299 $pluginManager->executeHooks('save_link', $link);
1285 1300
1286 $LINKSDB[$linkdate] = $link; 1301 $LINKSDB[$id] = $link;
1287 $LINKSDB->save($conf->get('resource.page_cache')); 1302 $LINKSDB->save($conf->get('resource.page_cache'));
1288 pubsubhub($conf); 1303 pubsubhub($conf);
1289 1304
@@ -1296,7 +1311,7 @@ function renderPage($conf, $pluginManager)
1296 $returnurl = !empty($_POST['returnurl']) ? $_POST['returnurl'] : '?'; 1311 $returnurl = !empty($_POST['returnurl']) ? $_POST['returnurl'] : '?';
1297 $location = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link')); 1312 $location = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link'));
1298 // Scroll to the link which has been edited. 1313 // Scroll to the link which has been edited.
1299 $location .= '#' . smallHash($_POST['lf_linkdate']); 1314 $location .= '#' . smallHash($created->format('Ymd_His'));
1300 // After saving the link, redirect to the page the user was on. 1315 // After saving the link, redirect to the page the user was on.
1301 header('Location: '. $location); 1316 header('Location: '. $location);
1302 exit; 1317 exit;
@@ -1307,8 +1322,10 @@ function renderPage($conf, $pluginManager)
1307 { 1322 {
1308 // If we are called from the bookmarklet, we must close the popup: 1323 // If we are called from the bookmarklet, we must close the popup:
1309 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } 1324 if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
1325 $link = $LINKSDB[(int) escape($_POST['lf_id'])];
1310 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); 1326 $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
1311 $returnurl .= '#'.smallHash($_POST['lf_linkdate']); // Scroll to the link which has been edited. 1327 // Scroll to the link which has been edited.
1328 $returnurl .= '#'.smallHash($link['created']->format('Ymd_His'));
1312 $returnurl = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link')); 1329 $returnurl = generateLocation($returnurl, $_SERVER['HTTP_HOST'], array('addlink', 'post', 'edit_link'));
1313 header('Location: '.$returnurl); // After canceling, redirect to the page the user was on. 1330 header('Location: '.$returnurl); // After canceling, redirect to the page the user was on.
1314 exit; 1331 exit;
@@ -1318,14 +1335,17 @@ function renderPage($conf, $pluginManager)
1318 if (isset($_POST['delete_link'])) 1335 if (isset($_POST['delete_link']))
1319 { 1336 {
1320 if (!tokenOk($_POST['token'])) die('Wrong token.'); 1337 if (!tokenOk($_POST['token'])) die('Wrong token.');
1338
1321 // We do not need to ask for confirmation: 1339 // We do not need to ask for confirmation:
1322 // - confirmation is handled by JavaScript 1340 // - confirmation is handled by JavaScript
1323 // - we are protected from XSRF by the token. 1341 // - we are protected from XSRF by the token.
1324 $linkdate=$_POST['lf_linkdate'];
1325 1342
1326 $pluginManager->executeHooks('delete_link', $LINKSDB[$linkdate]); 1343 // FIXME! We keep `lf_linkdate` for consistency before a proper API. To be removed.
1344 $id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : (int) escape($_POST['lf_linkdate']);
1327 1345
1328 unset($LINKSDB[$linkdate]); 1346 $pluginManager->executeHooks('delete_link', $LINKSDB[$id]);
1347
1348 unset($LINKSDB[$id]);
1329 $LINKSDB->save('resource.page_cache'); // save to disk 1349 $LINKSDB->save('resource.page_cache'); // save to disk
1330 1350
1331 // If we are called from the bookmarklet, we must close the popup: 1351 // If we are called from the bookmarklet, we must close the popup:
@@ -1364,8 +1384,10 @@ function renderPage($conf, $pluginManager)
1364 // -------- User clicked the "EDIT" button on a link: Display link edit form. 1384 // -------- User clicked the "EDIT" button on a link: Display link edit form.
1365 if (isset($_GET['edit_link'])) 1385 if (isset($_GET['edit_link']))
1366 { 1386 {
1367 $link = $LINKSDB[$_GET['edit_link']]; // Read database 1387 $id = (int) escape($_GET['edit_link']);
1388 $link = $LINKSDB[$id]; // Read database
1368 if (!$link) { header('Location: ?'); exit; } // Link not found in database. 1389 if (!$link) { header('Location: ?'); exit; } // Link not found in database.
1390 $link['linkdate'] = $link['created']->format('Ymd_His');
1369 $data = array( 1391 $data = array(
1370 'link' => $link, 1392 'link' => $link,
1371 'link_is_new' => false, 1393 'link_is_new' => false,
@@ -1389,7 +1411,7 @@ function renderPage($conf, $pluginManager)
1389 $link_is_new = false; 1411 $link_is_new = false;
1390 // Check if URL is not already in database (in this case, we will edit the existing link) 1412 // Check if URL is not already in database (in this case, we will edit the existing link)
1391 $link = $LINKSDB->getLinkFromUrl($url); 1413 $link = $LINKSDB->getLinkFromUrl($url);
1392 if (!$link) 1414 if (! $link)
1393 { 1415 {
1394 $link_is_new = true; 1416 $link_is_new = true;
1395 $linkdate = strval(date('Ymd_His')); 1417 $linkdate = strval(date('Ymd_His'));
@@ -1430,6 +1452,8 @@ function renderPage($conf, $pluginManager)
1430 'tags' => $tags, 1452 'tags' => $tags,
1431 'private' => $private 1453 'private' => $private
1432 ); 1454 );
1455 } else {
1456 $link['linkdate'] = $link['created']->format('Ymd_His');
1433 } 1457 }
1434 1458
1435 $data = array( 1459 $data = array(
@@ -1635,18 +1659,16 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager)
1635 $link['description'] = format_description($link['description'], $conf->get('redirector.url')); 1659 $link['description'] = format_description($link['description'], $conf->get('redirector.url'));
1636 $classLi = ($i % 2) != 0 ? '' : 'publicLinkHightLight'; 1660 $classLi = ($i % 2) != 0 ? '' : 'publicLinkHightLight';
1637 $link['class'] = $link['private'] == 0 ? $classLi : 'private'; 1661 $link['class'] = $link['private'] == 0 ? $classLi : 'private';
1638 $date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['linkdate']); 1662 $link['timestamp'] = $link['created']->getTimestamp();
1639 $link['timestamp'] = $date->getTimestamp();
1640 if (! empty($link['updated'])) { 1663 if (! empty($link['updated'])) {
1641 $date = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $link['updated']); 1664 $link['updated_timestamp'] = $link['updated']->getTimestamp();
1642 $link['updated_timestamp'] = $date->getTimestamp();
1643 } else { 1665 } else {
1644 $link['updated_timestamp'] = ''; 1666 $link['updated_timestamp'] = '';
1645 } 1667 }
1646 $taglist = explode(' ', $link['tags']); 1668 $taglist = explode(' ', $link['tags']);
1647 uasort($taglist, 'strcasecmp'); 1669 uasort($taglist, 'strcasecmp');
1648 $link['taglist'] = $taglist; 1670 $link['taglist'] = $taglist;
1649 $link['shorturl'] = smallHash($link['linkdate']); 1671 $link['shorturl'] = smallHash($link['created']->format('Ymd_His'));
1650 // Check for both signs of a note: starting with ? and 7 chars long. 1672 // Check for both signs of a note: starting with ? and 7 chars long.
1651 if ($link['url'][0] === '?' && 1673 if ($link['url'][0] === '?' &&
1652 strlen($link['url']) === 7) { 1674 strlen($link['url']) === 7) {
diff --git a/plugins/isso/isso.php b/plugins/isso/isso.php
index ffb7cfac..c44f3c09 100644
--- a/plugins/isso/isso.php
+++ b/plugins/isso/isso.php
@@ -41,9 +41,11 @@ function hook_isso_render_linklist($data, $conf)
41 // Only display comments for permalinks. 41 // Only display comments for permalinks.
42 if (count($data['links']) == 1 && empty($data['search_tags']) && empty($data['search_term'])) { 42 if (count($data['links']) == 1 && empty($data['search_tags']) && empty($data['search_term'])) {
43 $link = reset($data['links']); 43 $link = reset($data['links']);
44 $isso_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/isso/isso.html'); 44 $issoHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/isso/isso.html');
45 45
46 $isso = sprintf($isso_html, $issoUrl, $issoUrl, $link['linkdate'], $link['linkdate']); 46 // FIXME! KO thread unique si même date
47 $linkDate = $link['created']->format('Ymd_His');
48 $isso = sprintf($issoHtml, $issoUrl, $issoUrl, $linkDate, $linkDate);
47 $data['plugin_end_zone'][] = $isso; 49 $data['plugin_end_zone'][] = $isso;
48 50
49 // Hackish way to include this CSS file only when necessary. 51 // Hackish way to include this CSS file only when necessary.
diff --git a/tpl/daily.html b/tpl/daily.html
index b82ad483..eba0af3b 100644
--- a/tpl/daily.html
+++ b/tpl/daily.html
@@ -49,13 +49,13 @@
49 {$link=$value} 49 {$link=$value}
50 <div class="dailyEntry"> 50 <div class="dailyEntry">
51 <div class="dailyEntryPermalink"> 51 <div class="dailyEntryPermalink">
52 <a href="?{$link.linkdate|smallHash}"> 52 <a href="?{$value.shorturl}">
53 <img src="../images/squiggle2.png" width="25" height="26" title="permalink" alt="permalink"> 53 <img src="../images/squiggle2.png" width="25" height="26" title="permalink" alt="permalink">
54 </a> 54 </a>
55 </div> 55 </div>
56 {if="!$hide_timestamps || isLoggedIn()"} 56 {if="!$hide_timestamps || isLoggedIn()"}
57 <div class="dailyEntryLinkdate"> 57 <div class="dailyEntryLinkdate">
58 <a href="?{$link.linkdate|smallHash}">{function="strftime('%c', $link.timestamp)"}</a> 58 <a href="?{$value.shorturl}">{function="strftime('%c', $link.timestamp)"}</a>
59 </div> 59 </div>
60 {/if} 60 {/if}
61 {if="$link.tags"} 61 {if="$link.tags"}
diff --git a/tpl/editlink.html b/tpl/editlink.html
index 9e7621db..870cc168 100644
--- a/tpl/editlink.html
+++ b/tpl/editlink.html
@@ -16,6 +16,9 @@
16 <div id="editlinkform"> 16 <div id="editlinkform">
17 <form method="post" name="linkform"> 17 <form method="post" name="linkform">
18 <input type="hidden" name="lf_linkdate" value="{$link.linkdate}"> 18 <input type="hidden" name="lf_linkdate" value="{$link.linkdate}">
19 {if="isset($link.id)"}
20 <input type="hidden" name="lf_id" value="{$link.id}">
21 {/if}
19 <label for="lf_url"><i>URL</i></label><br><input type="text" name="lf_url" id="lf_url" value="{$link.url}" class="lf_input"><br> 22 <label for="lf_url"><i>URL</i></label><br><input type="text" name="lf_url" id="lf_url" value="{$link.url}" class="lf_input"><br>
20 <label for="lf_title"><i>Title</i></label><br><input type="text" name="lf_title" id="lf_title" value="{$link.title}" class="lf_input"><br> 23 <label for="lf_title"><i>Title</i></label><br><input type="text" name="lf_title" id="lf_title" value="{$link.title}" class="lf_input"><br>
21 <label for="lf_description"><i>Description</i></label><br><textarea name="lf_description" id="lf_description" rows="4" cols="25">{$link.description}</textarea><br> 24 <label for="lf_description"><i>Description</i></label><br><textarea name="lf_description" id="lf_description" rows="4" cols="25">{$link.description}</textarea><br>
diff --git a/tpl/linklist.html b/tpl/linklist.html
index ddfd729a..de9586c6 100644
--- a/tpl/linklist.html
+++ b/tpl/linklist.html
@@ -71,11 +71,11 @@
71 {if="isLoggedIn()"} 71 {if="isLoggedIn()"}
72 <div class="linkeditbuttons"> 72 <div class="linkeditbuttons">
73 <form method="GET" class="buttoneditform"> 73 <form method="GET" class="buttoneditform">
74 <input type="hidden" name="edit_link" value="{$value.linkdate}"> 74 <input type="hidden" name="edit_link" value="{$value.id}">
75 <input type="image" alt="Edit" src="images/edit_icon.png#" title="Edit" class="button_edit"> 75 <input type="image" alt="Edit" src="images/edit_icon.png#" title="Edit" class="button_edit">
76 </form><br> 76 </form><br>
77 <form method="POST" class="buttoneditform"> 77 <form method="POST" class="buttoneditform">
78 <input type="hidden" name="lf_linkdate" value="{$value.linkdate}"> 78 <input type="hidden" name="lf_linkdate" value="{$value.id}">
79 <input type="hidden" name="token" value="{$token}"> 79 <input type="hidden" name="token" value="{$token}">
80 <input type="hidden" name="delete_link"> 80 <input type="hidden" name="delete_link">
81 <input type="image" alt="Delete" src="images/delete_icon.png#" title="Delete" 81 <input type="image" alt="Delete" src="images/delete_icon.png#" title="Delete"
@@ -91,7 +91,7 @@
91 {if="!$hide_timestamps || isLoggedIn()"} 91 {if="!$hide_timestamps || isLoggedIn()"}
92 {$updated=$value.updated_timestamp ? 'Edited: '. strftime('%c', $value.updated_timestamp) : 'Permalink'} 92 {$updated=$value.updated_timestamp ? 'Edited: '. strftime('%c', $value.updated_timestamp) : 'Permalink'}
93 <span class="linkdate" title="Permalink"> 93 <span class="linkdate" title="Permalink">
94 <a href="?{$value.linkdate|smallHash}"> 94 <a href="?{$value.shorturl}">
95 <span title="{$updated}"> 95 <span title="{$updated}">
96 {function="strftime('%c', $value.timestamp)"} 96 {function="strftime('%c', $value.timestamp)"}
97 {if="$value.updated_timestamp"}*{/if} 97 {if="$value.updated_timestamp"}*{/if}