]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/IncludePage.php
Better test that a given revision exists
[SourceForge/phpwiki.git] / lib / plugin / IncludePage.php
1 <?php // -*-php-*-
2 // rcs_id('$Id$');
3 /*
4  * Copyright 1999, 2000, 2001, 2002 $ThePhpWikiProgrammingTeam
5  * Copyright 2008-2009 Marc-Etienne Vargenau, Alcatel-Lucent
6  *
7  * This file is part of PhpWiki.
8  *
9  * PhpWiki is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * PhpWiki is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with PhpWiki; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 /**
25  * IncludePage:  include text from another wiki page in this one
26  * usage:   <<IncludePage page=OtherPage rev=6 quiet=1 words=50 lines=6>>
27  * author:  Joe Edelman <joe@orbis-tertius.net>
28  */
29
30 class WikiPlugin_IncludePage
31 extends WikiPlugin
32 {
33     function getName() {
34         return _("IncludePage");
35     }
36
37     function getDescription() {
38         return _("Include text from another wiki page.");
39     }
40
41     function getDefaultArguments() {
42         return array( 'page'    => false, // the page to include
43                       'rev'     => false, // the revision (defaults to most recent)
44                       'version' => false, // same as "rev"
45                       'quiet'   => false, // if set, inclusion appears as normal content
46                       'bytes'   => false, // maximum number of bytes to include
47                       'words'   => false, // maximum number of words to include
48                       'lines'   => false, // maximum number of lines to include
49                       'sections' => false, // maximum number of sections to include
50                       'section' => false, // include a named section
51                       'sectionhead' => false // when including a named section show the heading
52                       );
53     }
54
55     function getWikiPageLinks($argstr, $basepage) {
56         extract($this->getArgs($argstr));
57
58         if (!isset($page))
59             return false;
60         if ($page) {
61             // Expand relative page names.
62             $page = new WikiPageName($page, $basepage);
63         }
64         if (!$page or !$page->name)
65             return false;
66         return array(array('linkto' => $page->name, 'relation' => 0));
67     }
68
69     function run($dbi, $argstr, &$request, $basepage) {
70         $args = $this->getArgs($argstr, $request);
71         extract($args);
72
73         if ($version && $rev) {
74             return $this->error(_("Choose only one of 'version' or 'rev' parameters."));
75         } elseif ($version) {
76             $rev = $version;
77         }
78
79         if ($page) {
80             // Expand relative page names.
81             $page = new WikiPageName($page, $basepage);
82             $page = $page->name;
83         }
84         if (!$page) {
85             return $this->error(_("no page specified"));
86         }
87
88         // A page can include itself once (this is needed, e.g.,  when editing
89         // TextFormattingRules).
90         static $included_pages = array();
91         if (in_array($page, $included_pages)) {
92             return $this->error(sprintf(_("recursive inclusion of page %s ignored"),
93                                         $page));
94         }
95
96         // Check if page exists
97         if (!($dbi->isWikiPage($page))) {
98             return $this->error(sprintf(_("Page '%s' does not exist"), $page));
99         }
100
101         // Check if user is allowed to get the Page.
102         if (!mayAccessPage ('view', $page)) {
103             return $this->error(sprintf(_("Illegal inclusion of page %s: no read access"),
104                                         $page));
105         }
106
107         $p = $dbi->getPage($page);
108         if ($rev) {
109             $r = $p->getRevision($rev);
110             if ((!$r) || ($r->hasDefaultContents())) {
111                 return $this->error(sprintf(_("%s: no such revision %d."),
112                                             $page, $rev));
113             }
114         } else {
115             $r = $p->getCurrentRevision();
116         }
117         $c = $r->getContent();
118
119         // follow redirects
120         if ((preg_match('/<'.'\?plugin\s+RedirectTo\s+page=(\S+)\s*\?'.'>/', implode("\n", $c), $m))
121           or (preg_match('/<'.'\?plugin\s+RedirectTo\s+page=(.*?)\s*\?'.'>/', implode("\n", $c), $m))
122           or (preg_match('/<<\s*RedirectTo\s+page=(\S+)\s*>>/', implode("\n", $c), $m))
123           or (preg_match('/<<\s*RedirectTo\s+page="(.*?)"\s*>>/', implode("\n", $c), $m)))
124         {
125             // Strip quotes (simple or double) from page name if any
126             if ((string_starts_with($m[1], "'"))
127               or (string_starts_with($m[1], "\""))) {
128                 $m[1] = substr($m[1], 1, -1);
129             }
130             // trap recursive redirects
131             if (in_array($m[1], $included_pages)) {
132                 return $this->error(sprintf(_("recursive inclusion of page %s ignored"),
133                                                 $page.' => '.$m[1]));
134             }
135             $page = $m[1];
136             $p = $dbi->getPage($page);
137             $r = $p->getCurrentRevision();
138             $c = $r->getContent();   // array of lines
139         }
140
141         $ct = $this->extractParts ($c, $page, $args);
142
143         // exclude from expansion
144         if (preg_match('/<noinclude>.+<\/noinclude>/s', $ct)) {
145             $ct = preg_replace("/<noinclude>.+?<\/noinclude>/s", "", $ct);
146         }
147         // only in expansion
148         $ct = preg_replace("/<includeonly>(.+)<\/includeonly>/s", "\\1", $ct);
149
150         array_push($included_pages, $page);
151
152         include_once('lib/BlockParser.php');
153         $content = TransformText($ct, $r->get('markup'), $page);
154
155         array_pop($included_pages);
156
157         if ($quiet)
158             return $content;
159
160         return HTML(HTML::p(array('class' => 'transclusion-title'),
161                             fmt("Included from %s", WikiLink($page))),
162
163                     HTML::div(array('class' => 'transclusion'),
164                               false, $content));
165     }
166
167     /**
168      * handles the arguments: section, sectionhead, lines, words, bytes,
169      * for UnfoldSubpages, IncludePage, ...
170      */
171     function extractParts ($c, $pagename, $args) {
172         extract($args);
173
174         if ($section) {
175             if ($sections) {
176                 $c = extractSection($section, $c, $pagename, $quiet, 1);
177             } else {
178                 $c = extractSection($section, $c, $pagename, $quiet, $sectionhead);
179             }
180         }
181         if ($sections) {
182             $c = extractSections($sections, $c, $pagename, $quiet, 1);
183         }
184         if ($lines) {
185             $c = array_slice($c, 0, $lines);
186             $c[] = sprintf(_(" ... first %d lines"), $lines);
187         }
188         if ($words) {
189             $c = firstNWordsOfContent($words, $c);
190         }
191         if ($bytes) {
192             $ct = implode("\n", $c); // one string
193             if (strlen($ct) > $bytes) {
194                 $ct = substr($c, 0, $bytes);
195                 $c = array($ct, sprintf(_(" ... first %d bytes"), $bytes));
196             }
197         }
198         $ct = implode("\n", $c); // one string
199         return $ct;
200     }
201 };
202
203 // This is an excerpt from the css file I use:
204 //
205 // .transclusion-title {
206 //   font-style: oblique;
207 //   font-size: 0.75em;
208 //   text-decoration: underline;
209 //   text-align: right;
210 // }
211 //
212 // DIV.transclusion {
213 //   background: lightgreen;
214 //   border: thin;
215 //   border-style: solid;
216 //   padding-left: 0.8em;
217 //   padding-right: 0.8em;
218 //   padding-top: 0px;
219 //   padding-bottom: 0px;
220 //   margin: 0.5ex 0px;
221 // }
222
223 // Local Variables:
224 // mode: php
225 // tab-width: 8
226 // c-basic-offset: 4
227 // c-hanging-comment-ender-p: nil
228 // indent-tabs-mode: nil
229 // End:
230 ?>