2 rcs_id('$Id: WikiBlog.php,v 1.29 2007-09-12 19:56:21 rurban Exp $');
4 Copyright 2002,2003,2007 $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 (as AddComment)
24 * @author: Changed as baseclass to AddComment and WikiForum and EditToolbar integration by ReiniUrban.
27 require_once('lib/TextSearchQuery.php');
30 * This plugin shows 'blogs' (comments/news) associated with a
31 * particular page and provides an input form for adding a new blog.
34 * Add <?plugin WikiBlog ?> at your PersonalPage and BlogArchive and
35 * BlogJournal will find the Blog entries automatically.
37 * Now it is also the base class for all attachable pagetypes:
38 * "wikiblog", "comment" and "wikiforum"
42 * To have the blog show up on a seperate page:
44 * <?plugin WikiBlog mode=add?>
45 * Create TopPage/Blog with this page as actionpage:
46 * <?plugin WikiBlog pagename=TopPage mode=show?>
48 * To have the main ADMIN_USER Blog appear under Blog and not under WikiBlog/Blog
49 * or UserName/Blog as for other users blogs,
50 * define BLOG_DEFAULT_EMPTY_PREFIX=true
51 * use the page Blog as basepage
52 * and user="" (as default for ADMIN or current user) and pagename="Blog"
53 * in the various blog plugins (BlogArchives, BlogJournal)
57 * It also works as an action-page if you create a page called 'WikiBlog'
58 * containing this plugin. This allows adding comments to any page
59 * by linking "PageName?action=WikiBlog". Maybe a nice feature in
60 * lib/display.php would be to automatically check if there are
61 * blogs for the given page, then provide a link to them somewhere on
62 * the page. Or maybe this just creates a huge mess...
64 * Maybe it would be a good idea to ENABLE blogging of only certain
65 * pages by setting metadata or something...? If a page is non-bloggable
66 * the plugin is ignored (perhaps with a warning message).
68 * Should blogs be by default filtered out of RecentChanges et al???
70 * Think of better name for this module: Blog? WikiLog? WebLog? WikiDot?
72 * Have other 'styles' for the plugin?... e.g. 'quiet'. Display only
73 * 'This page has 23 associated comments. Click here to view / add.'
75 * For admin user, put checkboxes beside comments to allow for bulk removal.
77 * Permissions for who can add blogs? Display entry box only if
78 * user meets these requirements...?
80 * Code cleanup: break into functions, use templates (or at least remove CSS)
83 class WikiPlugin_WikiBlog
90 function getDescription () {
91 return sprintf(_("Show and add blogs for %s"),'[pagename]');
94 function getVersion() {
95 return preg_replace("/[Revision: $]/", '',
96 "\$Revision: 1.29 $");
100 // page - page which is blogged to (default current page)
102 // order - 'normal' - place in chronological order
103 // - 'reverse' - place in reverse chronological order
105 // mode - 'show' - only show old blogs
106 // 'add' - only show entry box for new blog
107 // 'show,add' - show old blogs then entry box
108 // 'add,show' - show entry box followed by old blogs
112 // - arguments to allow selection of time range to display
113 // - arguments to display only XX blogs per page (can this 'paging'
114 // co-exist with the wiki?? difficult)
115 // - arguments to allow comments outside this range to be
116 // display as e.g. June 2002 archive, July 2002 archive, etc..
117 // - captions for 'show' and 'add' sections
120 function getDefaultArguments() {
121 return array('pagename' => '[pagename]',
123 'mode' => 'show,add',
128 function run($dbi, $argstr, &$request, $basepage) {
129 $args = $this->getArgs($argstr, $request);
130 // allow empty pagenames for ADMIN_USER style blogs: "Blog/day"
131 //if (!$args['pagename'])
132 // return $this->error(_("No pagename specified"));
134 // Get our form args.
135 $blog = $request->getArg("edit");
136 $request->setArg("edit", false);
138 if ($request->isPost() and !empty($blog['save'])) {
139 $this->add($request, $blog, 'wikiblog', $basepage); // noreturn
143 // Now we display previous comments and/or provide entry box
146 foreach (explode(',', $args['mode']) as $show) {
147 if (!empty($seen[$show]))
153 $html->pushContent($this->showAll($request, $args));
156 $html->pushContent($this->showForm($request, $args));
159 return $this->error(sprintf("Bad mode ('%s')", $show));
166 * posted: required: pagename, content. optional: summary
168 function add (&$request, $posted, $type='wikiblog') {
169 // This is similar to editpage. Shouldn't we use just this for preview?
170 $parent = $posted['pagename'];
171 if (empty($parent)) {
172 $prefix = ""; // allow empty parent for default "Blog/day"
174 } elseif (($parent == 'Blog' or $parent == 'WikiBlog') and $type == 'wikiblog')
175 { // avoid Blog/Blog/2003-01-11/14:03:02+00:00
177 $parent = ''; // 'Blog';
178 } elseif ($parent == 'Comment' and $type == "comment")
181 $parent = ''; // 'Comment';
182 } elseif ($parent == 'Forum' and $type == "wikiforum")
185 $parent = ''; // 'Forum';
187 $prefix = $parent . SUBPAGE_SEPARATOR;
189 //$request->finish(fmt("No pagename specified for %s",$type));
192 $dbi = $request->getDbh();
193 $user = $request->getUser();
196 * Page^H^H^H^H Blog meta-data
197 * This method is reused for all attachable pagetypes: wikiblog, comment and wikiforum
199 * This is info that won't change for each revision.
200 * Nevertheless, it's now stored in the revision meta-data.
202 * o It's more convenient to have all information required
203 * to render a page revision in the revision meta-data.
204 * o We can avoid a race condition, since version meta-data
205 * updates are atomic with the version creation.
208 $blog_meta = array('ctime' => $now,
209 'creator' => $user->getId(),
210 'creator_id' => $user->getAuthenticatedId(),
215 $summary = trim($posted['summary']);
216 $version_meta = array('author' => $blog_meta['creator'],
217 'author_id' => $blog_meta['creator_id'],
218 'markup' => 2.0, // assume new markup
219 'summary' => $summary ? $summary : _("New comment."),
224 if ($type == 'comment')
225 unset($version_meta['summary']);
228 $body = trim($posted['content']);
231 if ($type != 'wikiforum')
232 $pagename = $this->_blogPrefix($type);
234 $pagename = substr($summary,0,12);
235 if (empty($pagename)) {
237 trigger_error("Empty title", E_USER_WARNING);
241 // Generate the page name. For now, we use the format:
242 // Rootname/Blog/2003-01-11/14:03:02+00:00
243 // Rootname = $prefix, Blog = $pagename,
244 // This gives us natural chronological order when sorted
245 // alphabetically. "Rootname/" is optional.
246 // Esp. if Rootname is named Blog, it is omitted.
248 $time = Iso8601DateTime();
249 // Check intermediate pages. If not existing they should RedirectTo the parent page.
250 // Maybe add the BlogArchives plugin instead for the new interim subpage.
251 $redirected = $prefix . $pagename;
252 if (!$dbi->isWikiPage($redirected)) {
253 if (!$parent) $parent = HOME_PAGE;
254 require_once('lib/loadsave.php');
255 $pageinfo = array('pagename' => $redirected,
256 'content' => '<?plugin RedirectTo page="'.$parent.'" ?>',
257 'pagedata' => array(),
258 'versiondata' => array('author' => $blog_meta['creator'], 'is_minor_edit' => 1),
260 SavePage($request, $pageinfo, '', '');
262 $redirected = $prefix . $pagename . SUBPAGE_SEPARATOR . preg_replace("/T.*/", "", "$time");
263 if (!$dbi->isWikiPage($redirected)) {
264 if (!$parent) $parent = HOME_PAGE;
265 require_once('lib/loadsave.php');
266 $pageinfo = array('pagename' => $redirected,
267 'content' => '<?plugin RedirectTo page="'.$parent.'" ?>',
268 'pagedata' => array(),
269 'versiondata' => array('author' => $blog_meta['creator'], 'is_minor_edit' => 1),
271 SavePage($request, $pageinfo, '', '');
274 $p = $dbi->getPage($prefix . $pagename . SUBPAGE_SEPARATOR
275 . str_replace("T", SUBPAGE_SEPARATOR, "$time"));
276 $pr = $p->getCurrentRevision();
278 // Version should be zero. If not, page already exists
279 // so increment timestamp and try again.
280 if ($pr->getVersion() > 0) {
285 // FIXME: there's a slight, but currently unimportant
286 // race condition here. If someone else happens to
287 // have just created a blog with the same name,
288 // we'll have locked it before we discover that the name
291 * FIXME: For now all blogs are locked. It would be
292 * nice to allow only the 'creator' to edit by default.
294 $p->set('locked', true); //lock by default
295 // TOOD: use ACL perms
296 $saved = $p->save($body, 1, $version_meta);
302 $request->setArg("mode", "show");
303 $request->redirect($request->getURLtoSelf()); // noreturn
305 // FIXME: when submit a comment from preview mode,
306 // adds the comment properly but jumps to browse mode.
307 // Any way to jump back to preview mode???
310 function showAll (&$request, $args, $type="wikiblog") {
311 // FIXME: currently blogSearch uses WikiDB->titleSearch to
312 // get results, so results are in alphabetical order.
313 // When PageTypes fully implemented, could have smarter
314 // blogSearch implementation / naming scheme.
316 $dbi = $request->getDbh();
317 $basepage = $args['pagename'];
318 $blogs = $this->findBlogs($dbi, $basepage, $type);
322 usort($blogs, array("WikiPlugin_WikiBlog",
324 if ($args['order'] == 'reverse')
325 $blogs = array_reverse($blogs);
327 $name = $this->_blogPrefix($type);
328 if (!$args['noheader'])
329 $html->pushContent(HTML::h4(array('class' => "$type-heading"),
330 fmt("%s on %s:", $name, WikiLink($basepage))));
331 foreach ($blogs as $rev) {
332 if (!$rev->get($type)) {
333 // Ack! this is an old-style blog with data ctime in page meta-data.
334 $content = $this->_transformOldFormatBlog($rev, $type);
337 $content = $rev->getTransformedContent($type);
339 $html->pushContent($content);
346 // Subpage for the basepage. All Blogs/Forum/Comment entries are
347 // Subpages under this pagename, to find them faster.
348 function _blogPrefix($type='wikiblog') {
349 if ($type == 'wikiblog')
351 elseif ($type == 'comment')
352 $basepage = "Comment";
353 elseif ($type == 'wikiforum')
354 $basepage = substr($summary,0,12);
355 //$basepage = _("Message"); // FIXME: we use now the first 12 chars of the summary
359 function _transformOldFormatBlog($rev, $type='wikiblog') {
360 $page = $rev->getPage();
362 foreach (array('ctime', 'creator', 'creator_id') as $key)
363 $metadata[$key] = $page->get($key);
364 if (empty($metadata) and $type != 'wikiblog')
365 $metadata[$key] = $page->get('wikiblog');
366 $meta = $rev->getMetaData();
367 $meta[$type] = $metadata;
368 return new TransformedText($page, $rev->getPackedContent(), $meta, $type);
371 function findBlogs (&$dbi, $basepage='', $type='wikiblog') {
372 $prefix = (empty($basepage)
374 : $basepage . SUBPAGE_SEPARATOR) . $this->_blogPrefix($type);
375 $pages = $dbi->titleSearch(new TextSearchQuery('"'.$prefix.'"', true, 'none'));
378 while ($page = $pages->next()) {
379 if (!string_starts_with($page->getName(), $prefix))
381 $current = $page->getCurrentRevision();
382 if ($current->get('pagetype') == $type) {
389 function cmp($a, $b) {
390 return(strcmp($a->get('mtime'),
394 function showForm (&$request, $args, $template='blogform') {
395 // Show blog-entry form.
396 $args = array('PAGENAME' => $args['pagename'],
398 HiddenInputs($request->getArgs()));
399 if (ENABLE_EDIT_TOOLBAR and !ENABLE_WYSIWYG and ($template != 'addcomment')) {
400 include_once("lib/EditToolbar.php");
401 $toolbar = new EditToolbar();
402 $args = array_merge($args, $toolbar->getTokens());
404 return new Template($template, $request, $args);
407 // "2004-12" => "December 2004"
408 function _monthTitle($month){
409 if (!$month) $month = strftime("%Y-%m");
410 //list($year,$mon) = explode("-",$month);
411 return strftime("%B %Y", strtotime($month."-01"));
414 // "UserName/Blog/2004-12-13/12:28:50+01:00" => array('month' => "2004-12", ...)
415 function _blog($rev_or_page) {
416 $pagename = $rev_or_page->getName();
417 if (preg_match("/^(.*Blog)\/(\d\d\d\d-\d\d)-(\d\d)\/(.*)/", $pagename, $m))
418 list(,$prefix,$month,$day,$time) = $m;
419 return array('pagename' => $pagename,
420 // page (list pages per month) or revision (list months)?
421 //'title' => isa($rev_or_page,'WikiDB_PageRevision') ? $rev_or_page->get('summary') : '',
422 //'monthtitle' => $this->_monthTitle($month),
426 'prefix' => $prefix);
429 function _nonDefaultArgs($args) {
430 return array_diff_assoc($args, $this->getDefaultArguments());
435 // $Log: not supported by cvs2svn $
436 // Revision 1.28 2007/07/14 12:05:22 rurban
437 // create interim pages as minor for RecentChanges
439 // Revision 1.27 2007/06/01 06:39:07 rurban
440 // no edittoolbar for comments
442 // Revision 1.26 2007/02/17 14:17:03 rurban
445 // Revision 1.25 2007/01/20 11:23:37 rurban
446 // Fix forum parent. Fix addcomment header.
448 // Revision 1.24 2007/01/07 18:46:40 rurban
449 // Add EditToolbar support. Omit Blog/Blog/
451 // Revision 1.23 2005/10/29 09:06:37 rurban
452 // move common blog methods to WikiBlog
454 // Revision 1.22 2004/12/15 15:33:18 rurban
457 // Revision 1.21 2004/12/14 21:35:15 rurban
458 // support new BLOG_EMPTY_DEFAULT_PREFIX
460 // Revision 1.20 2004/12/13 13:22:57 rurban
461 // new BlogArchives plugin for the new blog theme. enable default box method
462 // for all plugins. Minor search improvement.
464 // Revision 1.19 2004/11/26 18:39:02 rurban
465 // new regex search parser and SQL backends (90% complete, glob and pcre backends missing)
467 // Revision 1.18 2004/05/14 20:55:04 rurban
468 // simplified RecentComments
470 // Revision 1.17 2004/05/14 17:33:12 rurban
471 // new plugin RecentChanges
473 // Revision 1.16 2004/04/19 18:27:46 rurban
474 // Prevent from some PHP5 warnings (ref args, no :: object init)
475 // php5 runs now through, just one wrong XmlElement object init missing
476 // Removed unneccesary UpgradeUser lines
477 // Changed WikiLink to omit version if current (RecentChanges)
479 // Revision 1.15 2004/04/18 05:42:17 rurban
480 // more fixes for page="0"
481 // better WikiForum support
483 // Revision 1.14 2004/03/29 21:33:32 rurban
484 // possible fix for problem reported by Whit Blauvelt
485 // Message-ID: <20040327211707.GA22374@free.transpect.com>
486 // create intermediate redirect subpages for blog/comment/forum
488 // Revision 1.13 2004/03/15 10:59:40 rurban
489 // fix also early attach type bug, attached as wikiblog pagetype
491 // Revision 1.11 2004/03/12 20:59:31 rurban
492 // important cookie fix by Konstantin Zadorozhny
493 // new editpage feature: JS_SEARCHREPLACE
495 // Revision 1.10 2004/03/12 17:32:41 rurban
496 // new base class PageType_attach as base class for WikiBlog, Comment, and WikiForum.
497 // new plugin AddComment, which is a WikiBlog with different pagetype and template,
498 // based on WikiBlog. WikiForum comes later.
500 // Revision 1.9 2004/02/27 02:10:50 rurban
501 // Patch #891133 by pablom517
502 // "WikiBlog Plugin now sorts logs correctly"
504 // Revision 1.8 2004/02/17 12:11:36 rurban
505 // 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, ...)
507 // Revision 1.7 2003/11/17 16:23:55 carstenklapp
508 // Switched to Iso8601DateTime and more use of SUBPAGE_SEPARATOR. This
509 // allows plugin UnfoldSubpages (for example) to be added to page
510 // XxYy/Blog/ where desired, for a view of all Blogs in one day. This
511 // change should not break existing BLOGs, we are only checking for
512 // pagetype == 'wikiblog' now instead of relying on the subpage name to
513 // collect blog subpages. (** WARNING: Do not add UnfoldSubpages to both
514 // XxYy/Blog/ and XxYy/Blog/2003-11/16/ pages, due to recursion bug in
515 // UnfoldSubpages plugin.)
517 // Revision 1.6 2003/02/21 04:20:09 dairiki
518 // Big refactor. Formatting now done by the stuff in PageType.php.
519 // Split the template into two separate ones: one for the add comment form,
520 // one for comment display.
522 // Revision 1.5 2003/02/16 19:47:17 dairiki
523 // Update WikiDB timestamp when editing or deleting pages.
525 // Revision 1.4 2003/01/11 22:23:00 carstenklapp
526 // More refactoring to use templated output. Use page meta "summary" field.
528 // Revision 1.3 2003/01/06 02:29:02 carstenklapp
529 // New: use blog.tmpl template to format output. Some cosmetic
530 // issues, it mostly works but code still needs cleanup. Added
531 // getVersion() for PluginManager.
539 // c-hanging-comment-ender-p: nil
540 // indent-tabs-mode: nil