aboutsummaryrefslogtreecommitdiffhomepage
path: root/application
diff options
context:
space:
mode:
Diffstat (limited to 'application')
-rw-r--r--application/FeedBuilder.php5
-rw-r--r--application/LinkDB.php38
-rw-r--r--application/LinkFilter.php30
-rw-r--r--application/PageBuilder.php2
-rw-r--r--application/Router.php12
-rw-r--r--application/Utils.php35
6 files changed, 95 insertions, 27 deletions
diff --git a/application/FeedBuilder.php b/application/FeedBuilder.php
index a1f4da48..7377bcec 100644
--- a/application/FeedBuilder.php
+++ b/application/FeedBuilder.php
@@ -97,6 +97,11 @@ class FeedBuilder
97 */ 97 */
98 public function buildData() 98 public function buildData()
99 { 99 {
100 // Search for untagged links
101 if (isset($this->userInput['searchtags']) && empty($this->userInput['searchtags'])) {
102 $this->userInput['searchtags'] = false;
103 }
104
100 // Optionally filter the results: 105 // Optionally filter the results:
101 $linksToDisplay = $this->linkDB->filterSearch($this->userInput); 106 $linksToDisplay = $this->linkDB->filterSearch($this->userInput);
102 107
diff --git a/application/LinkDB.php b/application/LinkDB.php
index 0d3c85bd..8ca0fab3 100644
--- a/application/LinkDB.php
+++ b/application/LinkDB.php
@@ -423,43 +423,29 @@ You use the community supported version of the original Shaarli project, by Seba
423 public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all') 423 public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all')
424 { 424 {
425 // Filter link database according to parameters. 425 // Filter link database according to parameters.
426 $searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; 426 $searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : '';
427 $searchterm = !empty($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; 427 $searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : '';
428 428
429 // Search tags + fullsearch. 429 // Search tags + fullsearch - blank string parameter will return all links.
430 if (! empty($searchtags) && ! empty($searchterm)) { 430 $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT;
431 $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT; 431 $request = [$searchtags, $searchterm];
432 $request = array($searchtags, $searchterm);
433 }
434 // Search by tags.
435 elseif (! empty($searchtags)) {
436 $type = LinkFilter::$FILTER_TAG;
437 $request = $searchtags;
438 }
439 // Fulltext search.
440 elseif (! empty($searchterm)) {
441 $type = LinkFilter::$FILTER_TEXT;
442 $request = $searchterm;
443 }
444 // Otherwise, display without filtering.
445 else {
446 $type = '';
447 $request = '';
448 }
449 432
450 $linkFilter = new LinkFilter($this); 433 $linkFilter = new LinkFilter($this);
451 return $linkFilter->filter($type, $request, $casesensitive, $visibility); 434 return $linkFilter->filter($type, $request, $casesensitive, $visibility);
452 } 435 }
453 436
454 /** 437 /**
455 * Returns the list of all tags 438 * Returns the list tags appearing in the links with the given tags
456 * Output: associative array key=tags, value=0 439 * @param $filteringTags: tags selecting the links to consider
440 * @param $visibility: process only all/private/public links
441 * @return: a tag=>linksCount array
457 */ 442 */
458 public function allTags() 443 public function linksCountPerTag($filteringTags = [], $visibility = 'all')
459 { 444 {
445 $links = empty($filteringTags) ? $this->links : $this->filterSearch(['searchtags' => $filteringTags], false, $visibility);
460 $tags = array(); 446 $tags = array();
461 $caseMapping = array(); 447 $caseMapping = array();
462 foreach ($this->links as $link) { 448 foreach ($links as $link) {
463 foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) { 449 foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) {
464 if (empty($tag)) { 450 if (empty($tag)) {
465 continue; 451 continue;
diff --git a/application/LinkFilter.php b/application/LinkFilter.php
index 81832a4b..0e887d38 100644
--- a/application/LinkFilter.php
+++ b/application/LinkFilter.php
@@ -253,6 +253,9 @@ class LinkFilter
253 { 253 {
254 // Implode if array for clean up. 254 // Implode if array for clean up.
255 $tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags; 255 $tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags;
256 if ($tags === false) {
257 return $this->filterUntagged($visibility);
258 }
256 if (empty($tags)) { 259 if (empty($tags)) {
257 return $this->noFilter($visibility); 260 return $this->noFilter($visibility);
258 } 261 }
@@ -296,6 +299,33 @@ class LinkFilter
296 } 299 }
297 300
298 /** 301 /**
302 * Return only links without any tag.
303 *
304 * @param string $visibility return only all/private/public links.
305 *
306 * @return array filtered links.
307 */
308 public function filterUntagged($visibility)
309 {
310 $filtered = [];
311 foreach ($this->links as $key => $link) {
312 if ($visibility !== 'all') {
313 if (! $link['private'] && $visibility === 'private') {
314 continue;
315 } else if ($link['private'] && $visibility === 'public') {
316 continue;
317 }
318 }
319
320 if (empty(trim($link['tags']))) {
321 $filtered[$key] = $link;
322 }
323 }
324
325 return $filtered;
326 }
327
328 /**
299 * Returns the list of articles for a given day, chronologically sorted 329 * Returns the list of articles for a given day, chronologically sorted
300 * 330 *
301 * Day must be in the form 'YYYYMMDD' (e.g. '20120125'), e.g. 331 * Day must be in the form 'YYYYMMDD' (e.g. '20120125'), e.g.
diff --git a/application/PageBuilder.php b/application/PageBuilder.php
index 50e3f124..c86621a2 100644
--- a/application/PageBuilder.php
+++ b/application/PageBuilder.php
@@ -89,7 +89,7 @@ class PageBuilder
89 $this->tpl->assign('hide_timestamps', $this->conf->get('privacy.hide_timestamps', false)); 89 $this->tpl->assign('hide_timestamps', $this->conf->get('privacy.hide_timestamps', false));
90 $this->tpl->assign('token', getToken($this->conf)); 90 $this->tpl->assign('token', getToken($this->conf));
91 if ($this->linkDB !== null) { 91 if ($this->linkDB !== null) {
92 $this->tpl->assign('tags', $this->linkDB->allTags()); 92 $this->tpl->assign('tags', $this->linkDB->linksCountPerTag());
93 } 93 }
94 // To be removed with a proper theme configuration. 94 // To be removed with a proper theme configuration.
95 $this->tpl->assign('conf', $this->conf); 95 $this->tpl->assign('conf', $this->conf);
diff --git a/application/Router.php b/application/Router.php
index c9a51912..4df0387c 100644
--- a/application/Router.php
+++ b/application/Router.php
@@ -13,6 +13,8 @@ class Router
13 13
14 public static $PAGE_TAGCLOUD = 'tagcloud'; 14 public static $PAGE_TAGCLOUD = 'tagcloud';
15 15
16 public static $PAGE_TAGLIST = 'taglist';
17
16 public static $PAGE_DAILY = 'daily'; 18 public static $PAGE_DAILY = 'daily';
17 19
18 public static $PAGE_FEED_ATOM = 'atom'; 20 public static $PAGE_FEED_ATOM = 'atom';
@@ -45,6 +47,8 @@ class Router
45 47
46 public static $PAGE_SAVE_PLUGINSADMIN = 'save_pluginadmin'; 48 public static $PAGE_SAVE_PLUGINSADMIN = 'save_pluginadmin';
47 49
50 public static $GET_TOKEN = 'token';
51
48 /** 52 /**
49 * Reproducing renderPage() if hell, to avoid regression. 53 * Reproducing renderPage() if hell, to avoid regression.
50 * 54 *
@@ -77,6 +81,10 @@ class Router
77 return self::$PAGE_TAGCLOUD; 81 return self::$PAGE_TAGCLOUD;
78 } 82 }
79 83
84 if (startsWith($query, 'do='. self::$PAGE_TAGLIST)) {
85 return self::$PAGE_TAGLIST;
86 }
87
80 if (startsWith($query, 'do='. self::$PAGE_OPENSEARCH)) { 88 if (startsWith($query, 'do='. self::$PAGE_OPENSEARCH)) {
81 return self::$PAGE_OPENSEARCH; 89 return self::$PAGE_OPENSEARCH;
82 } 90 }
@@ -142,6 +150,10 @@ class Router
142 return self::$PAGE_SAVE_PLUGINSADMIN; 150 return self::$PAGE_SAVE_PLUGINSADMIN;
143 } 151 }
144 152
153 if (startsWith($query, 'do='. self::$GET_TOKEN)) {
154 return self::$GET_TOKEN;
155 }
156
145 return self::$PAGE_LINKLIST; 157 return self::$PAGE_LINKLIST;
146 } 158 }
147} 159}
diff --git a/application/Utils.php b/application/Utils.php
index ab463af9..4a2f5561 100644
--- a/application/Utils.php
+++ b/application/Utils.php
@@ -91,6 +91,10 @@ function endsWith($haystack, $needle, $case = true)
91 */ 91 */
92function escape($input) 92function escape($input)
93{ 93{
94 if (is_bool($input)) {
95 return $input;
96 }
97
94 if (is_array($input)) { 98 if (is_array($input)) {
95 $out = array(); 99 $out = array();
96 foreach($input as $key => $value) { 100 foreach($input as $key => $value) {
@@ -435,3 +439,34 @@ function get_max_upload_size($limitPost, $limitUpload, $format = true)
435 $maxsize = min($size1, $size2); 439 $maxsize = min($size1, $size2);
436 return $format ? human_bytes($maxsize) : $maxsize; 440 return $format ? human_bytes($maxsize) : $maxsize;
437} 441}
442
443/**
444 * Sort the given array alphabetically using php-intl if available.
445 * Case sensitive.
446 *
447 * Note: doesn't support multidimensional arrays
448 *
449 * @param array $data Input array, passed by reference
450 * @param bool $reverse Reverse sort if set to true
451 * @param bool $byKeys Sort the array by keys if set to true, by value otherwise.
452 */
453function alphabetical_sort(&$data, $reverse = false, $byKeys = false)
454{
455 $callback = function($a, $b) use ($reverse) {
456 // Collator is part of PHP intl.
457 if (class_exists('Collator')) {
458 $collator = new Collator(setlocale(LC_COLLATE, 0));
459 if (!intl_is_failure(intl_get_error_code())) {
460 return $collator->compare($a, $b) * ($reverse ? -1 : 1);
461 }
462 }
463
464 return strcasecmp($a, $b) * ($reverse ? -1 : 1);
465 };
466
467 if ($byKeys) {
468 uksort($data, $callback);
469 } else {
470 usort($data, $callback);
471 }
472}