Migrate wiki.inc.php as a core class PlWikiPage.
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Sun, 27 Jul 2008 18:13:52 +0000 (20:13 +0200)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Sun, 27 Jul 2008 18:13:52 +0000 (20:13 +0200)
Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
classes/plwikipage.php [new file with mode: 0644]

diff --git a/classes/plwikipage.php b/classes/plwikipage.php
new file mode 100644 (file)
index 0000000..20bcf97
--- /dev/null
@@ -0,0 +1,415 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+/** This namespace groups all the methods relative to the integration
+ * of PmWiki into plat/al.
+ *
+ * pagename: A page name is NameSpace.Page and must be acceed trough
+ *           NameSpace/Page.
+ */
+class PlWikiPage
+{
+    static private $permLevels = array('public' => 'Public',
+                                       'logged' => 'Connecté',
+                                       'mdp'    => 'Authentifié',
+                                       'admin'  => 'Admin');
+    static private $defaulPerms = array('logged', 'admin');
+
+    public $name;
+    public $path;
+
+    private $perms = null;
+
+    /** Build a new page from a PmWiki page name (ie NameSpace.Page).
+     */
+    public function __construct($n)
+    {
+        if (!is_utf8($n)) {
+            $n = utf8_encode($n);
+        }
+        $this->name = $n;
+        $this->path = str_replace('.', '/', $n);
+    }
+
+    /** Return the filename.
+     */
+    public function filename()
+    {
+        return self::workDir() . '/' . $this->name;
+    }
+
+    /** Return the filename for the cache file.
+     */
+    public function cacheFilename()
+    {
+        return self::workDir() . '/cache_' . $this->name . '.tpl';
+    }
+
+    /** Fetch the permissions.
+     */
+    private function fetchPerms()
+    {
+        if (!is_null($this->perms)) {
+            return;
+        }
+        $file = $this->filename();
+        if (!file_exists($file)) {
+            $this->perms = self::$defaulPerms;
+            return;
+        }
+        $lines = explode("\n", file_get_contents($file));
+        foreach ($lines as $line) {
+            @list($k, $v) = explode('=', $line, 2);
+            if ($k == 'platal_perms') {
+                $this->perms = explode(':', $v);
+                return;
+            }
+        }
+        $this->perms = self::$defaulPerms;
+    }
+
+    /** Return read perms.
+     */
+    public function readPerms()
+    {
+        if (is_null($this->perms)) {
+            $this->fetchPerms();
+        }
+        return $this->perms[0];
+    }
+
+    /** Check if the user can read the page.
+     */
+    public function canRead()
+    {
+        return self::havePerms($this->readPerms());
+    }
+
+    /** Return write perms.
+     */
+    public function writePerms()
+    {
+        if (is_null($this->perms)) {
+            $this->fetchPerms();
+        }
+        return $this->perms[1];
+    }
+
+    /** Check if the user can write the page.
+     */
+    public function canWrite()
+    {
+        return self::havePerms($this->writePerms());
+    }
+
+    /** Set the permission level for the page.
+     */
+    public function setPerms($read, $write)
+    {
+        $file = $this->filename();
+        if (!file_exists($file)) {
+            return false;
+        }
+
+        $p = $read . ':' . $write;
+        $lines = explode("\n", file_get_contents($file));
+        foreach ($lines as $i => $line) {
+            list($k, $v) = explode('=', $line, 2);
+            if ($k == 'platal_perms') {
+                unset($lines[$i]);
+                break;
+            }
+        }
+        array_splice($lines, 1, 0, array('platal_perms=' . $p));
+        file_put_contents($file, join("\n", $lines));
+        $this->perms = array($read, $write);
+        return true;
+    }
+
+
+    /** Check permission for RSS feed.
+     */
+    public function prepareFeed()
+    {
+        if ($this->canRead()) {
+            return;
+        }
+        $uid = Platal::session()->tokenAuth(Get::v('user'), Get::v('hash'));
+        if ($this->canRead()) {
+            return;
+        }
+        exit;
+    }
+
+    /** Apply the read permissions for the current page.
+     */
+    public function applyReadPerms()
+    {
+        if ($this->canRead()) {
+            return;
+        }
+        $this->applyPerms($this->readPerms());
+    }
+
+    /** Apply the write permissions for the current page.
+     */
+    public function applyWritePerms()
+    {
+        if ($this->canWrite()) {
+            return;
+        }
+        $this->applyPerms($this->writePerms());
+    }
+
+    /** Build the cache for the page.
+     */
+    public function buildCache()
+    {
+        global $globals;
+        if (is_file($this->cacheFilename())) {
+            return;
+        }
+        system('wget --no-check-certificate ' . escapeshellarg($globals->baseurl . '/' . $this->path) . ' -O /dev/null');
+    }
+
+    /** Remove the page.
+     */
+    public function delete()
+    {
+        $file  = $this->filename();
+        $cache = $this->cacheFilename();
+        if (is_file($cache)) {
+            unlink($cache);
+        }
+        if (!is_file($file)) {
+            return false;
+        }
+        unlink($file);
+        return true;
+    }
+
+    /** Return the wiki storage dir.
+     */
+    public static function workDir()
+    {
+        global $globals;
+        return $globals->spoolroot . '/spool/wiki.d';
+    }
+
+    /** Clear wiki cache.
+     */
+    public static function clearCache()
+    {
+        system('rm -f ' . self::workDir() . '/cache_*');
+    }
+
+
+    /** Search links in the a page
+     */
+    private static function findLinks($line, $groupname)
+    {
+        $links = array();
+        if (preg_match_all('@\[\[([^~][^\]\|\?#]*)((\?|#)[^\]\|]+)?(\\|[^\]]+)?\]\]@', $line, $matches, PREG_OFFSET_CAPTURE)) {
+            foreach ($matches[1] as $j => $link) if (!preg_match('@http://@', $link[0])) {
+                $mylink = str_replace('/','.',trim($link[0]));
+                $sup = trim(substr($matches[2][$j][0],1));
+                $alt = trim(substr($matches[4][$j][0],1));
+                $newlink = str_replace(' ','',ucwords($mylink));
+                if (strpos($newlink,'.') === false) {
+                    $newlink = $groupname.'.'.$newlink;
+                }
+                if (!$alt && $mylink != $newlink) {
+                    $alt = trim($link[0]);
+                }
+                $links[] = array(
+                  'pos' => $matches[0][$j][1],
+                  'size' => strlen($matches[0][$j][0]),
+                  'href' => $newlink,
+                  'sup' => $sup,
+                  'alt' => $alt,
+                  'group' => substr($mylink, 0, strpos($mylink, '.')));
+            }
+        }
+        return $links;
+    }
+
+    public function rename($newname, $changeLinks = true)
+    {
+        $newpage = new PlWikiPage(str_replace('/', '.', $newname));
+
+        list($groupname, ) = explode('.', $this->name);
+        list($newgroupname, ) = explode('.', $newpage->name);
+
+        $file    = $this->filename();
+        $newfile = $newpage->filename();
+        if (!is_file($file)) {
+            // old page doesn't exist
+            return false;
+        }
+        if (!rename($file, $newfile)) {
+            // impossible to renama page
+            return false;
+        }
+
+        if (!$changeLinks) {
+            $this->name = $newpage->name;
+            $this->path = $newpage->path;
+            return true;
+        }
+
+        $changedLinks = 0;
+        // change name inside this folder and ingroup links if changing group
+        $lines = explode("\n", file_get_contents($newfile));
+        $changed = false;
+        foreach ($lines as $i => $line) {
+            list($k, $v) = explode('=', $line, 2);
+            if ($k == 'name' && $v == $pagename_dots) {
+                $lines[$i] = 'name=' . $newpage->name;
+                $changed = true;
+            } else if ($groupname != $newgroupname) {
+                $links =  self::findLinks($line, $groupname);
+                $newline = '';
+                $last = 0;
+                foreach ($links as $link) {
+                    if ($link['group'] == $groupname) {
+                        $newline .= substr($line, $last, $link['pos']);
+                        $newline .= '[['.$link['href'].$link['sup'].($link['alt']?(' |'.$link['alt']):'').']]';
+                        $last = $link['pos']+$link['size'];
+                        $changedLinks++;
+                    }
+                }
+                if ($last != 0) {
+                    $newline .= substr($line, $last);
+                    $lines[$i] = $newline;
+                    $changed = true;
+                }
+            }
+        }
+        file_put_contents($newfile, join("\n", $lines));
+
+        // change wiki links in all wiki pages
+        $endname = substr($pagename_dots, strpos($this->name, '.') + 1);
+        $pages = array();
+        exec('grep ' . $endname . '  ' . self::workDir() . '/* -sc', $pages);
+        foreach($pages as $line) {
+            if (preg_match('%/([^/:]+):([0-9]+)$%', $line, $vals) && $vals[2] > 0) {
+                $inpage = $vals[1];
+                $lines = explode("\n", file_get_contents(self::workDir().'/'.$inpage));
+                $changed = false;
+                // find all wiki links in page and change if linked to this page
+                foreach ($lines as $i => $line) {
+                    $links = self::findLinks($line, substr($inpage, 0, strpos($inpage, '.')));
+                    $newline = '';
+                    $last = 0;
+                    foreach ($links as $link) {
+                        if ($link['href'] == $pagename_dots) {
+                            $newline .= substr($line, $last, $link['pos']);
+                            $newline .= '[[' . $newname_dots . $link['sup'] . ($link['alt'] ? (' |' . $link['alt']) : '') . ']]';
+                            $last = $link['pos'] + $link['size'];
+                            $changedLinks++;
+                        }
+                    }
+                    if ($last != 0) {
+                        $newline .= substr($line, $last);
+                        $lines[$i] = $newline;
+                        $changed = true;
+                    }
+                }
+                if ($changed) {
+                    file_put_contents(self::workDir() . '/' . $inpage, join("\n", $lines));
+                }
+            }
+        }
+        if ($changedLinks > 0) {
+            return $changedLinks;
+        }
+        $this->name = $newpage->name;
+        $this->path = $newpage->path;
+        return true;
+    }
+
+    /** Return the authentication level translation table.
+     */
+    public static function permOptions()
+    {
+        return array('public' => 'Public',
+                     'logged' => 'Connecté',
+                     'mdp'    => 'Authentifié',
+                     'admin'  => 'Admin');
+    }
+
+    /** Check permissions.
+     */
+    public static function havePerms($perm)
+    {
+        switch ($perm) {
+          case 'public':
+            return true;
+          case 'logged':
+          case 'mdp':
+            return S::logged();
+          case 'admin':
+            return S::has_perms();
+          default:
+            return false;
+        }
+    }
+
+    /** Apply permissions.
+     */
+    public static function applyPerms($perm)
+    {
+        switch ($perm) {
+          case 'public':
+            return;
+          case 'logged':
+            Platal::session()->start(AUTH_PUBLIC + 1);
+            return;
+          default:
+            Platal::session()->start(Platal::session()->sureLevel());
+            return;
+        }
+    }
+
+    /** Return the current page.
+     */
+    public static function currentPage()
+    {
+        if (!Get::v('n')) {
+            return null;
+        }
+
+        $words = explode('/', trim(Get::v('n'), '/'));
+        if (count($words) == 2) {
+            return new PlWikiPage(join('.', $words));
+        }
+
+        // We are on NameSpace.Page, redirect to NameSpace/Page
+        array_unshift($words, $words[0]);
+        $b = array_pop($words);
+        $a = array_pop($words);
+
+        pl_redirect($a . '/' . $b);
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>