2 rcs_id('$Id: WikiBlog.php,v 1.21 2004-12-14 21:35:15 rurban Exp $');
4 Copyright 2002, 2003 $ThePhpWikiProgrammingTeam
6 This file is part of PhpWiki.
8 PhpWiki is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 PhpWiki is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with PhpWiki; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * @author: MichaelVanDam, major refactor by JeffDairiki
26 require_once('lib/TextSearchQuery.php');
29 * This plugin shows 'blogs' (comments/news) associated with a
30 * particular page and provides an input form for adding a new blog.
32 * Now it is also the base class for all attachable pagetypes:
33 * wikiblog, comment and wikiforum
37 * To have comments show up on a separate page:
39 * <?plugin WikiBlog mode=add?>
40 * Create TopPage/Comments with:
41 * <?plugin WikiBlog page=TopPage mode=show?>
45 * It also works as an action-page if you create a page called 'WikiBlog'
46 * containing this plugin. This allows adding comments to any page
47 * by linking "PageName?action=WikiBlog". Maybe a nice feature in
48 * lib/display.php would be to automatically check if there are
49 * blogs for the given page, then provide a link to them somewhere on
50 * the page. Or maybe this just creates a huge mess...
52 * Maybe it would be a good idea to ENABLE blogging of only certain
53 * pages by setting metadata or something...? If a page is non-bloggable
54 * the plugin is ignored (perhaps with a warning message).
56 * Should blogs be by default filtered out of RecentChanges et al???
58 * Think of better name for this module: Blog? WikiLog? WebLog? WikiDot?
60 * Have other 'styles' for the plugin?... e.g. 'quiet'. Display only
61 * 'This page has 23 associated comments. Click here to view / add.'
63 * For admin user, put checkboxes beside comments to allow for bulk removal.
65 * Permissions for who can add blogs? Display entry box only if
66 * user meets these requirements...?
68 * Code cleanup: break into functions, use templates (or at least remove CSS)
71 class WikiPlugin_WikiBlog
78 function getDescription () {
79 return sprintf(_("Show and add blogs for %s"),'[pagename]');
82 function getVersion() {
83 return preg_replace("/[Revision: $]/", '',
84 "\$Revision: 1.21 $");
88 // page - page which is blogged to (default current page)
90 // order - 'normal' - place in chronological order
91 // - 'reverse' - place in reverse chronological order
93 // mode - 'show' - only show old blogs
94 // 'add' - only show entry box for new blog
95 // 'show,add' - show old blogs then entry box
96 // 'add,show' - show entry box followed by old blogs
100 // - arguments to allow selection of time range to display
101 // - arguments to display only XX blogs per page (can this 'paging'
102 // co-exist with the wiki?? difficult)
103 // - arguments to allow comments outside this range to be
104 // display as e.g. June 2002 archive, July 2002 archive, etc..
105 // - captions for 'show' and 'add' sections
108 function getDefaultArguments() {
109 return array('pagename' => '[pagename]',
111 'mode' => 'show,add',
116 function run($dbi, $argstr, &$request, $basepage) {
117 $args = $this->getArgs($argstr, $request);
118 // allow empty pagenames for ADMIN_USER style blogs: "Blogs/day"
119 //if (!$args['pagename'])
120 // return $this->error(_("No pagename specified"));
122 // Get our form args.
123 $blog = $request->getArg("blog");
124 $request->setArg('blog', false);
126 if ($request->isPost() and !empty($blog['addblog'])) {
127 $this->add($request, $blog); // noreturn
130 // Now we display previous comments and/or provide entry box
133 foreach (explode(',', $args['mode']) as $show) {
134 if (!empty($seen[$show]))
140 $html->pushContent($this->showAll($request, $args));
143 $html->pushContent($this->showForm($request, $args));
146 return $this->error(sprintf("Bad mode ('%s')", $show));
152 function add (&$request, $blog, $type='wikiblog') {
153 $parent = $blog['pagename'];
154 if (empty($parent)) {
155 $prefix = ""; // allow empty parent for default "Blogs/day"
158 $prefix = $parent . SUBPAGE_SEPARATOR;
160 //$request->finish(fmt("No pagename specified for %s",$type));
163 $dbi = $request->getDbh();
164 $user = $request->getUser();
167 * Page^H^H^H^H Blog meta-data
168 * This method is reused for all attachable pagetypes: wikiblog, comment and wikiforum
170 * This is info that won't change for each revision.
171 * Nevertheless, it's now stored in the revision meta-data.
173 * o It's more convenient to have all information required
174 * to render a page revision in the revision meta-data.
175 * o We can avoid a race condition, since version meta-data
176 * updates are atomic with the version creation.
179 $blog_meta = array('ctime' => $now,
180 'creator' => $user->getId(),
181 'creator_id' => $user->getAuthenticatedId(),
186 $summary = trim($blog['summary']);
187 $version_meta = array('author' => $blog_meta['creator'],
188 'author_id' => $blog_meta['creator_id'],
189 'markup' => 2.0, // assume new markup
190 'summary' => $summary ? $summary : _("New comment."),
195 if ($type == 'comment')
196 unset($version_meta['summary']);
199 $body = trim($blog['body']);
203 // Generate the page name. For now, we use the format:
204 // Rootname/Blog/2003-01-11/14:03:02+00:00
205 // This gives us natural chronological order when sorted
208 $time = Iso8601DateTime();
209 if ($type == 'wikiblog')
211 elseif ($type == 'comment')
212 $pagename = "Comment";
213 elseif ($type == 'wikiforum')
214 $pagename = substr($summary,0,12);
216 // Check intermediate pages. If not existing they should RedirectTo the parent page.
217 // Maybe add the BlogArchives plugin instead for new interim subpage.
218 $redirected = $prefix . $pagename;
219 if (!$dbi->isWikiPage($redirected)) {
220 require_once('lib/loadsave.php');
221 $pageinfo = array('pagename' => $redirected,
222 'content' => '<?plugin RedirectTo page='.$parent.' ?>',
223 'pagedata' => array(),
224 'versiondata' => array('author' => $blog_meta['creator']),
226 SavePage($request, $pageinfo, '', '');
228 $redirected = $prefix . $pagename . SUBPAGE_SEPARATOR . preg_replace("/T.*/", "", "$time");
229 if (!$dbi->isWikiPage($redirected)) {
230 require_once('lib/loadsave.php');
231 $pageinfo = array('pagename' => $redirected,
232 'content' => '<?plugin RedirectTo page='.$parent.' ?>',
233 'pagedata' => array(),
234 'versiondata' => array('author' => $blog_meta['creator']),
236 SavePage($request, $pageinfo, '', '');
239 $p = $dbi->getPage($prefix . $pagename . SUBPAGE_SEPARATOR
240 . str_replace("T", SUBPAGE_SEPARATOR, "$time"));
241 $pr = $p->getCurrentRevision();
243 // Version should be zero. If not, page already exists
244 // so increment timestamp and try again.
245 if ($pr->getVersion() > 0) {
250 // FIXME: there's a slight, but currently unimportant
251 // race condition here. If someone else happens to
252 // have just created a blog with the same name,
253 // we'll have locked it before we discover that the name
256 * FIXME: For now all blogs are locked. It would be
257 * nice to allow only the 'creator' to edit by default.
259 $p->set('locked', true); //lock by default
260 $saved = $p->save($body, 1, $version_meta);
266 $request->redirect($request->getURLtoSelf()); // noreturn
268 // FIXME: when submit a comment from preview mode,
269 // adds the comment properly but jumps to browse mode.
270 // Any way to jump back to preview mode???
273 function showAll (&$request, $args, $type="wikiblog") {
274 // FIXME: currently blogSearch uses WikiDB->titleSearch to
275 // get results, so results are in alphabetical order.
276 // When PageTypes fully implemented, could have smarter
277 // blogSearch implementation / naming scheme.
279 $dbi = $request->getDbh();
281 $parent = $args['pagename'];
282 $blogs = $this->findBlogs($dbi, $parent, $type);
286 usort($blogs, array("WikiPlugin_WikiBlog",
288 if ($args['order'] == 'reverse')
289 $blogs = array_reverse($blogs);
291 $name = $this->_blogPrefix($type);
292 if (!$args['noheader'])
293 $html->pushContent(HTML::h4(array('class' => "$type-heading"),
294 fmt("%s on %s:", $name, WikiLink($parent))));
295 foreach ($blogs as $rev) {
296 if (!$rev->get($type)) {
297 // Ack! this is an old-style blog with data ctime in page meta-data.
298 $content = $this->_transformOldFormatBlog($rev, $type);
301 $content = $rev->getTransformedContent($type);
303 $html->pushContent($content);
310 // all Blogs/Forum/Comment entries are subpages under this pagename, to find them faster.
311 function _blogPrefix($type='wikiblog') {
312 if ($type == 'wikiblog')
314 elseif ($type == 'comment')
315 $name = _("Comments");
316 elseif ($type == 'wikiforum')
317 $name = _("Messages");
321 function _transformOldFormatBlog($rev, $type='wikiblog') {
322 $page = $rev->getPage();
324 foreach (array('ctime', 'creator', 'creator_id') as $key)
325 $metadata[$key] = $page->get($key);
326 if (empty($metadata) and $type != 'wikiblog')
327 $metadata[$key] = $page->get('wikiblog');
328 $meta = $rev->getMetaData();
329 $meta[$type] = $metadata;
330 return new TransformedText($page, $rev->getPackedContent(), $meta, $type);
333 function findBlogs (&$dbi, $parent, $type='wikiblog') {
334 $prefix = (empty($parent) ? "" : $parent . SUBPAGE_SEPARATOR) . $this->_blogPrefix($type);
335 $pages = $dbi->titleSearch(new TextSearchQuery("^".$prefix, true, 'posix'));
338 while ($page = $pages->next()) {
339 if (!string_starts_with($page->getName(), $prefix))
341 $current = $page->getCurrentRevision();
342 if ($current->get('pagetype') == $type) {
349 function cmp($a, $b) {
350 return(strcmp($a->get('mtime'),
354 function showForm (&$request, $args, $template='blogform') {
355 // Show blog-entry form.
356 return new Template($template, $request,
357 array('PAGENAME' => $args['pagename']));
361 // $Log: not supported by cvs2svn $
362 // Revision 1.20 2004/12/13 13:22:57 rurban
363 // new BlogArchives plugin for the new blog theme. enable default box method
364 // for all plugins. Minor search improvement.
366 // Revision 1.19 2004/11/26 18:39:02 rurban
367 // new regex search parser and SQL backends (90% complete, glob and pcre backends missing)
369 // Revision 1.18 2004/05/14 20:55:04 rurban
370 // simplified RecentComments
372 // Revision 1.17 2004/05/14 17:33:12 rurban
373 // new plugin RecentChanges
375 // Revision 1.16 2004/04/19 18:27:46 rurban
376 // Prevent from some PHP5 warnings (ref args, no :: object init)
377 // php5 runs now through, just one wrong XmlElement object init missing
378 // Removed unneccesary UpgradeUser lines
379 // Changed WikiLink to omit version if current (RecentChanges)
381 // Revision 1.15 2004/04/18 05:42:17 rurban
382 // more fixes for page="0"
383 // better WikiForum support
385 // Revision 1.14 2004/03/29 21:33:32 rurban
386 // possible fix for problem reported by Whit Blauvelt
387 // Message-ID: <20040327211707.GA22374@free.transpect.com>
388 // create intermediate redirect subpages for blog/comment/forum
390 // Revision 1.13 2004/03/15 10:59:40 rurban
391 // fix also early attach type bug, attached as wikiblog pagetype
393 // Revision 1.11 2004/03/12 20:59:31 rurban
394 // important cookie fix by Konstantin Zadorozhny
395 // new editpage feature: JS_SEARCHREPLACE
397 // Revision 1.10 2004/03/12 17:32:41 rurban
398 // new base class PageType_attach as base class for WikiBlog, Comment, and WikiForum.
399 // new plugin AddComment, which is a WikiBlog with different pagetype and template,
400 // based on WikiBlog. WikiForum comes later.
402 // Revision 1.9 2004/02/27 02:10:50 rurban
403 // Patch #891133 by pablom517
404 // "WikiBlog Plugin now sorts logs correctly"
406 // Revision 1.8 2004/02/17 12:11:36 rurban
407 // added missing 4th basepage arg at plugin->run() to almost all plugins. This caused no harm so far, because it was silently dropped on normal usage. However on plugin internal ->run invocations it failed. (InterWikiSearch, IncludeSiteMap, ...)
409 // Revision 1.7 2003/11/17 16:23:55 carstenklapp
410 // Switched to Iso8601DateTime and more use of SUBPAGE_SEPARATOR. This
411 // allows plugin UnfoldSubpages (for example) to be added to page
412 // XxYy/Blog/ where desired, for a view of all Blogs in one day. This
413 // change should not break existing BLOGs, we are only checking for
414 // pagetype == 'wikiblog' now instead of relying on the subpage name to
415 // collect blog subpages. (** WARNING: Do not add UnfoldSubpages to both
416 // XxYy/Blog/ and XxYy/Blog/2003-11/16/ pages, due to recursion bug in
417 // UnfoldSubpages plugin.)
419 // Revision 1.6 2003/02/21 04:20:09 dairiki
420 // Big refactor. Formatting now done by the stuff in PageType.php.
421 // Split the template into two separate ones: one for the add comment form,
422 // one for comment display.
424 // Revision 1.5 2003/02/16 19:47:17 dairiki
425 // Update WikiDB timestamp when editing or deleting pages.
427 // Revision 1.4 2003/01/11 22:23:00 carstenklapp
428 // More refactoring to use templated output. Use page meta "summary" field.
430 // Revision 1.3 2003/01/06 02:29:02 carstenklapp
431 // New: use blog.tmpl template to format output. Some cosmetic
432 // issues, it mostly works but code still needs cleanup. Added
433 // getVersion() for PluginManager.
441 // c-hanging-comment-ender-p: nil
442 // indent-tabs-mode: nil