From 818d2283465b76931db168a9e2c72f2c0f004ecc Mon Sep 17 00:00:00 2001
From: Michael Hamann <michael@content-space.de>
Date: Wed, 31 Jul 2013 17:20:00 +0200
Subject: [PATCH] Fix the useheading cache invalidation for hidden pages, add
 tests

This adds a new parameter to ft_backlinks() to ignore permissions which
is needed for invalidating the cache of linking pages with useheading
enabled. This also adds various test cases for ft_backlinks().
---
 _test/tests/inc/fulltext_backlinks.test.php | 77 +++++++++++++++++++++
 inc/common.php                              |  2 +-
 inc/fulltext.php                            | 12 ++--
 3 files changed, 86 insertions(+), 5 deletions(-)
 create mode 100644 _test/tests/inc/fulltext_backlinks.test.php

diff --git a/_test/tests/inc/fulltext_backlinks.test.php b/_test/tests/inc/fulltext_backlinks.test.php
new file mode 100644
index 000000000..058e13498
--- /dev/null
+++ b/_test/tests/inc/fulltext_backlinks.test.php
@@ -0,0 +1,77 @@
+<?php
+
+// must be run within Dokuwiki
+if (!defined('DOKU_INC')) die();
+
+/**
+ * Test cases for the link index
+ *
+ * @author Michael Hamann <michael@content-space.de>
+ */
+class fultext_backlinks_test extends DokuWikiTest {
+
+    public function test_internallink() {
+        saveWikiText('test:internallinks', '[[internälLink]] [[..:internal link]]', 'Test initialization');
+        idx_addPage('test:internallinks');
+
+        $this->assertEquals(array('test:internallinks'), ft_backlinks('internal_link'));
+        $this->assertEquals(array('test:internallinks'), ft_backlinks('test:internaellink'));
+    }
+
+    public function test_links_in_footnotes() {
+        saveWikiText('test:link_footnotes', '(([[footnote]] [[:foÖtnotel]]))', 'Test initialization');
+        idx_addPage('test:link_footnotes');
+
+        $this->assertEquals(array('test:link_footnotes'), ft_backlinks('test:footnote'));
+        $this->assertEquals(array('test:link_footnotes'), ft_backlinks('fooetnotel'));
+    }
+
+    public function test_links_in_hidden_pages() {
+        global $conf;
+        $conf['hidepages'] = 'hidden:.*';
+        saveWikiText('hidden:links', '[[wiki:hiddenlink|linktitle]]', 'Test initialization');
+        idx_addPage('hidden:links');
+        saveWikiText('visible:links', '[[wiki:hiddenlink]]', 'Test initialization');
+        idx_addPage('visible:links');
+
+        $this->assertEquals(array('visible:links'), ft_backlinks('wiki:hiddenlink'));
+        $this->assertEquals(array('visible:links'), ft_backlinks('wiki:hiddenlink', false));
+        $this->assertEquals(array('hidden:links', 'visible:links'), ft_backlinks('wiki:hiddenlink', true));
+    }
+
+    public function test_links_in_protected_pages() {
+        global $conf;
+        global $AUTH_ACL;
+        $conf['superuser'] = 'alice';
+        $conf['useacl']    = 1;
+
+        $AUTH_ACL = array(
+            '*           @ALL           8',
+            'secret:*      @ALL           0',
+        );
+
+        $_SERVER['REMOTE_USER'] = 'eve';
+
+        saveWikiText('secret:links', '[[wiki:secretlink]]', 'Test initialization');
+        idx_addPage('secret:links');
+        saveWikiText('public:links', '[[wiki:secretlink]]', 'Test initialization');
+        idx_addPage('public:links');
+
+        $this->assertEquals(array('public:links'), ft_backlinks('wiki:secretlink'));
+        $this->assertEquals(array('public:links'), ft_backlinks('wiki:secretlink', false));
+        $this->assertEquals(array('public:links', 'secret:links'), ft_backlinks('wiki:secretlink', true));
+    }
+
+    public function test_links_in_deleted_pages() {
+        saveWikiText('test:internallinks', '[[internallink]] [[..:internal link]]', 'Test initialization');
+        idx_addPage('test:internallinks');
+
+        $this->assertEquals(array('test:internallinks'), ft_backlinks('test:internallink'));
+        $this->assertEquals(array('test:internallinks'), ft_backlinks('internal_link'));
+
+        saveWikiText('test:internallinks', '', 'Deleted');
+
+        $this->assertEquals(array(), ft_backlinks('test:internallink'));
+        $this->assertEquals(array(), ft_backlinks('internal_link'));
+    }
+}
diff --git a/inc/common.php b/inc/common.php
index 1b4d9e8e4..bff6e80de 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -1130,7 +1130,7 @@ function saveWikiText($id, $text, $summary, $minor = false) {
 
     // if useheading is enabled, purge the cache of all linking pages
     if(useHeading('content')) {
-        $pages = ft_backlinks($id);
+        $pages = ft_backlinks($id, true);
         foreach($pages as $page) {
             $cache = new cache_renderer($page, wikiFN($page), 'xhtml');
             $cache->removeCache();
diff --git a/inc/fulltext.php b/inc/fulltext.php
index 2f073acea..1afff25dd 100644
--- a/inc/fulltext.php
+++ b/inc/fulltext.php
@@ -125,17 +125,21 @@ function _ft_pageSearch(&$data) {
  * Returns the backlinks for a given page
  *
  * Uses the metadata index.
+ *
+ * @param string $id           The id for which links shall be returned
+ * @param bool   $ignore_perms Ignore the fact that pages are hidden or read-protected
+ * @return array The pages that contain links to the given page
  */
-function ft_backlinks($id){
-    $result = array();
-
+function ft_backlinks($id, $ignore_perms = false){
     $result = idx_get_indexer()->lookupKey('relation_references', $id);
 
     if(!count($result)) return $result;
 
     // check ACL permissions
     foreach(array_keys($result) as $idx){
-        if(isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ || !page_exists($result[$idx], '', false)){
+        if(($ignore_perms !== true && (
+                isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ
+            )) || !page_exists($result[$idx], '', false)){
             unset($result[$idx]);
         }
     }
-- 
GitLab