]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/WikiBlog.php
Update WikiDB timestamp when editing or deleting pages.
[SourceForge/phpwiki.git] / lib / plugin / WikiBlog.php
1 <?php // -*-php-*-
2 rcs_id('$Id: WikiBlog.php,v 1.5 2003-02-16 19:47:17 dairiki Exp $');
3 /**
4  * Author: MichaelVanDam
5  */
6
7 require_once('lib/TextSearchQuery.php');
8 //require_once('lib/plugin/IncludePage.php');
9
10 /**
11  * This plugin shows 'blogs' (comments/news) associated with a
12  * particular page and provides an input form for adding a new blog.
13  *
14  * TODO:
15  *
16  * It also works as an action-page if you create a page called 'WikiBlog'
17  * containing this plugin.  This allows adding comments to any page
18  * by linking "PageName?action=WikiBlog".  Maybe a nice feature in
19  * lib/displaypage.php would be to automatically check if there are
20  * blogs for the given page, then provide a link to them somewhere on
21  * the page.  Or maybe this just creates a huge mess...
22  *
23  * Maybe it would be a good idea to ENABLE blogging of only certain
24  * pages by setting metadata or something...?  If a page is non-bloggable
25  * the plugin is ignored (perhaps with a warning message).
26  *
27  * Should blogs be by default filtered out of RecentChanges et al???
28  *
29  * Think of better name for this module: Blog? WikiLog? WebLog? WikiDot?
30  *
31  * Have other 'styles' for the plugin?... e.g. 'quiet'.  Display only
32  * 'This page has 23 associated comments. Click here to view / add.'
33  *
34  * For admin user, put checkboxes beside comments to allow for bulk removal.
35  *
36  * Permissions for who can add blogs?  Display entry box only if
37  * user meets these requirements...?
38  *
39  * Code cleanup: break into functions, use templates (or at least remove CSS)
40  *
41  */
42
43
44 class WikiPlugin_WikiBlog
45 extends WikiPlugin
46 {
47     function getName () {
48         return _("WikiBlog");
49     }
50
51     function getDescription () {
52         return sprintf(_("Show and add blogs for %s"),'[pagename]');
53     }
54
55     function getVersion() {
56         return preg_replace("/[Revision: $]/", '',
57                             "\$Revision: 1.5 $");
58     }
59
60     // Arguments:
61     //
62     //  page - page which is blogged to (default current page)
63     //
64     //  order - 'normal' - place in chronological order
65     //        - 'reverse' - place in reverse chronological order
66     //
67     //  mode - 'show' - only show old blogs
68     //         'add' - only show entry box for new blog
69     //         'show,add' - show old blogs then entry box
70     //         'add,show' - show entry box followed by old blogs
71     //
72     // TODO:
73     //
74     // - arguments to allow selection of time range to display
75     // - arguments to display only XX blogs per page (can this 'paging'
76     //    co-exist with the wiki??  difficult)
77     // - arguments to allow comments outside this range to be
78     //    display as e.g. June 2002 archive, July 2002 archive, etc..
79     // - captions for 'show' and 'add' sections
80
81
82     function getDefaultArguments() {
83         return array('page'       => '[pagename]',
84                      'order'      => 'normal',
85                      'mode'       => 'show,add',
86                      'noheader'   => false
87                     );
88     }
89
90
91     function run($dbi, $argstr, $request) {
92         $this->_args = $this->getArgs($argstr, $request);
93         extract($this->_args);
94         if (!$page)
95             return '';
96
97
98         // Look at arguments to see if blog was submitted.  If so,
99         // process this before displaying anything.
100
101         if ($request->getArg('addblog')) {
102
103             // TODO: change args to blog[page], blog[summary], blog[body] etc
104
105             $blog_page = $request->getArg('blog[page]');
106
107
108             // Generate the page name.  For now, we use the format:
109             //   Rootname/Blog-YYYYMMDDHHMMSS
110             // This gives us natural chronological order when sorted
111             // alphabetically.
112             // This is inside a loop because there is a small
113             // chance that another user could add a blog with
114             // the same timestamp.  If such a conflict is
115             // detected, increment timestamp by 1 second until
116             // a unique name is found.
117
118             $now = time();
119
120             $p = false;  // will store our page
121             $time = false; // will store our timestamp
122
123             $saved = false;
124             while (!$saved) {
125
126 //change to ISO formatted time? 2003-01-11T24:03:02
127                 $time = strftime ('%Y%m%d%H%M%S', $now);
128
129 //add a subpage between, to allow one to create a page containing only all the blogs of the parent page
130 //                $p = $dbi->getPage($blog_page . SUBPAGE_SEPARATOR . _("Comments") . SUBPAGE_SEPARATOR . "Blog-$time");
131                 $p = $dbi->getPage($blog_page . SUBPAGE_SEPARATOR . "Blog-$time");
132
133                 $pr = $p->getCurrentRevision();
134
135                 // Version should be zero.  If not, page already exists
136                 // so increment timestamp and try again.
137
138                 if ($pr->getVersion() > 0) $now ++;
139                 else $saved = true;
140
141             }
142
143
144             // Generate meta-data for page
145             // This is info that won't change for each revision:
146             //   ctime (time of creation), creator, and creator_id.
147             // Create-date is really the relevant date for a blog,
148             // not the last-modified date.
149
150             // FIXME:  For now all blogs are locked.  It would be
151             // nice to allow only the 'creator' to edit by default.
152
153             $user = $request->getUser();
154             $user_id = $user->getId();
155             $user_auth_id = $user->getAuthenticatedId();
156
157             $p->set ('ctime', $now);
158             $p->set ('creator', $user_id);
159             $p->set ('creator_id', $user_auth_id);
160             $p->set ('locked', true);  // lock by default
161             $p->set ('pagetype', 'wikiblog');
162
163             // Generate meta-data for page revision
164
165             $meta = array('author' => $user_id,
166                           'author_id' => $user_auth_id,
167                           'markup' => 2.0,   // assume new markup
168                           'summary' => _("New comment."),
169                           );
170
171             // FIXME: For now the page format is:
172             //
173             //   __Summary__
174             //   Body
175             //
176             // This helps during editing (using standard editor)
177             // when the page/revision metadata is not available
178             // to the user.  If we had a pagetype-specific editor
179             // then we could put the Summary into meta-data and
180             // still make it available for editing.
181             // Also, it helps for now during rendering because we
182             // don't need to create a new PageType class just yet...
183
184             // FIXME: move summary into the page's summary field
185             // PageType now displays the summary field when viewing
186             // an individual blog page
187             $summary = trim($request->getArg('blog[summary]'));
188             $body = trim($request->getArg('blog[body]'));
189
190             if ($summary)
191                 $meta['summary'] = $summary;
192
193             $pr = $p->createRevision($pr->getVersion()+1,
194                                      $body,
195                                      $meta,
196                                      ExtractWikiPageLinks($body));
197
198             // FIXME: Detect if !$pr ??  How to handle errors?
199
200             $dbi->touch();
201
202             // Save was successful.  Unset all the arguments and
203             // redirect to page that user was viewing before.
204             // Unsetting arguments will prevent double-submitting
205             // problem and will clear out the text-boxes.
206
207             $request->setArg('addblog', false);
208             $request->setArg('blog[page]', false);
209             $request->setArg('blog[body]', false);
210             $request->setArg('blog[summary]', false);
211
212             $url = $request->getURLtoSelf();
213             $request->redirect($url);
214
215             // FIXME: when submit a comment from preview mode,
216             // adds the comment properly but jumps to browse mode.
217             // Any way to jump back to preview mode???
218
219
220             // The rest of the output will not be seen due to
221             // the redirect.
222         }
223
224         // Now we display previous comments and/or provide entry box
225         // for new comments
226
227         $showblogs = true;
228         $showblogform = true;
229
230         switch ($mode) {
231
232             case 'show':
233                 $showblogform = false;
234
235             case 'add':
236                 $showblogs = false;
237
238             case 'show,add':
239             case 'add,show':
240             default:
241
242             // TODO: implement ordering show,add vs add,show !
243
244         }
245
246
247         $html = HTML();
248
249         if ($showblogs) {
250             $html->pushContent($this->showBlogs ($dbi, $request, $page, $order));
251         }
252
253         if ($showblogform) {
254             $html->pushContent($this->showBlogForm ($dbi, $request, $page));
255         }
256
257         return $html;
258
259     }
260
261
262     function showBlogs ($dbi, $request, $page, $order) {
263
264         // Display comments:
265
266         // FIXME: currently blogSearch uses WikiDB->titleSearch to
267         // get results, so results are in alphabetical order.
268         // When PageTypes fully implemented, could have smarter
269         // blogSearch implementation / naming scheme.
270
271         $pages = $dbi->blogSearch($page, $order);
272
273         $all_comments = HTML();
274
275         while ($p = $pages->next()) {
276
277             // FIXME:
278             // Verify that it is a blog page.  If not, go to next page.
279             // When we proper blogSearch implementation this will not
280             // be necessary.  Non-blog pages will not be returned by
281             // blogSearch.
282
283             $name = $p->getName();
284             // If page contains '/', we must escape them
285             // FIXME: only works for '/' SUBPAGE_SEPARATOR
286             $escpage = preg_replace ("/\//", '\/', $page);
287             if (!preg_match("/^$escpage\/Blog-([[:digit:]]{14})$/", $name, $matches))
288                 continue;
289
290             // Display contents:
291
292             // TODO: ultimately have a function in PageType to handle
293             // display of blog entries...
294
295             // If we want to use IncludePage plugin to display blog:
296             // $i = new WikiPlugin_IncludePage;
297             // $html->pushContent($i->run($dbi, "page=$name", $request));
298
299             global $WikiNameRegexp;
300             global $Theme;
301
302             $ctime = $p->get('ctime');
303             $ctime = $Theme->formatDateTime($ctime);
304
305             $creator = $p->get('creator');
306             $creator_id = $p->get('creator_id');
307             $creator_orig = $creator;
308
309             if (preg_match("/^$WikiNameRegexp\$/", $creator)
310                                && $dbi->isWikiPage($creator))
311                 $creator = WikiLink($creator);
312
313             $pr = $p->getCurrentRevision();
314
315             $modified = ($pr->getVersion() > 1);
316
317             $mtime = $pr->get('mtime');
318             $mtime = $Theme->formatDateTime($mtime);
319
320             $author    = $pr->get('author');
321             $author_id = $pr->get('author_id');
322             $author_orig = $author;
323
324             $summary = $pr->get('summary');
325
326             if (preg_match("/^$WikiNameRegexp\$/", $author)
327                                && $dbi->isWikiPage($author))
328                 $authorlink = WikiLink($author);
329
330             $browseaction = WikiURL($name);
331             $editaction = WikiURL($name, array('action' => 'edit'));
332             $removeaction = WikiURL($name, array('action' => 'remove'));
333
334             $browselink = HTML::a(array('href' => $browseaction,
335                                         'class'=>'wiki'), $ctime);
336             $editlink = HTML::a(array('href' => $editaction,
337                                       'class' => 'wikiaction'), 'Edit');
338             $removelink = HTML::a(array('href' => $removeaction,
339                                         'class'=>'wikiadmin'), 'Delete');
340
341             // FIXME if necessary:
342             $creator_id_string = (strcmp($creator_orig, $creator_id) == 0) ? '' : ' (' . $creator_id . ')';
343
344             // FIXME if necessary:
345             $author_id_string = (strcmp($author_orig, $author_id) == 0) ? '' : ' (' . $author_id . ')';
346
347             // FIXME: for now we just show all links on all entries.
348             // This should be customizable.
349
350             @$blognumber++; //hackish fixme                                              
351             $args['SHOWHEADER'] = (! $this->_args['noheader'])
352                                   && ($blognumber == 1);
353             $args['SHOWBLOGFORM'] = false;
354             $args['SHOWBLOG'] = true;
355
356             $args['PAGELINK'] = WikiLink($page);
357             $args['PAGENAME'] = $page;
358             $args['AUTHOR'] = $author;
359
360              // FIXME: use $request's api to get user
361             $isadmin = $request->_user->isadmin();
362             $isauthor = $request->_user->getId() == $author;
363
364             $args['EDITLINK'] = ($isadmin) || ($isauthor) ? $editlink : "";
365             $args['REMOVELINK'] = ($isadmin) ? $removelink : "";
366             $args['AUTHORLINK'] = $authorlink;
367             $args['SUMMARY'] = $summary;
368             $args['CONTENT'] = TransformInline($pr->getPackedContent());
369             $args['DATELINK'] = $browselink;
370
371             $args['datemodified'] = $modified ? $mtime : '';
372             $args['authormodified'] = $pr->get('author');
373             $blogformtemplate = new Template('blog', $request, $args);
374             $all_comments->pushContent($blogformtemplate);
375         }
376         return $all_comments;
377     }
378
379     function showBlogForm ($dbi, $request, $page) {
380         // Show blog-entry form.
381             $args['PAGENAME'] = $page;
382             $args['SHOWHEADER'] = false;
383             $args['SHOWBLOGFORM'] = true;
384             $args['SHOWBLOG'] = false;
385             $blogformtemplate = new Template('blog', $request, $args);
386             return $blogformtemplate;
387     }
388 };
389
390 // $Log: not supported by cvs2svn $
391 // Revision 1.4  2003/01/11 22:23:00  carstenklapp
392 // More refactoring to use templated output. Use page meta "summary" field.
393 //
394 // Revision 1.3  2003/01/06 02:29:02  carstenklapp
395 // New: use blog.tmpl template to format output. Some cosmetic
396 // issues, it mostly works but code still needs cleanup. Added
397 // getVersion() for PluginManager.
398 //
399
400 // For emacs users
401 // Local Variables:
402 // mode: php
403 // tab-width: 8
404 // c-basic-offset: 4
405 // c-hanging-comment-ender-p: nil
406 // indent-tabs-mode: nil
407 // End:
408 ?>