diff options
author | Evan Prodromou <evan@controlyourself.ca> | 2009-05-21 11:43:28 -0400 |
---|---|---|
committer | Evan Prodromou <evan@controlyourself.ca> | 2009-05-21 11:43:28 -0400 |
commit | 966f1c6169a2d1202e1b69860b975792ca6b9149 (patch) | |
tree | 6d96f15d5e9bcb5136ad51658f390f212cb7a499 | |
parent | 8cc8f9fd0c0ad8d1c38bd0c113f9f0a4d7918256 (diff) | |
parent | 62711ae2babf29203e818efa832902ffeab1363f (diff) |
Merge branch 'conversationtree' into 0.8.x
-rw-r--r-- | actions/conversation.php | 203 | ||||
-rw-r--r-- | lib/searchaction.php | 2 | ||||
-rw-r--r-- | plugins/WikiHashtagsPlugin.php | 109 |
3 files changed, 307 insertions, 7 deletions
diff --git a/actions/conversation.php b/actions/conversation.php index 05cfb76e3..ef189016a 100644 --- a/actions/conversation.php +++ b/actions/conversation.php @@ -11,7 +11,7 @@ * @link http://laconi.ca/ * * Laconica - a distributed open-source microblogging tool - * Copyright (C) 2008, Controlez-Vous, Inc. + * Copyright (C) 2009, Control Yourself, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -31,7 +31,7 @@ if (!defined('LACONICA')) { exit(1); } -require_once(INSTALLDIR.'/lib/noticelist.php'); +require_once INSTALLDIR.'/lib/noticelist.php'; /** * Conversation tree in the browser @@ -42,9 +42,10 @@ require_once(INSTALLDIR.'/lib/noticelist.php'); * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @link http://laconi.ca/ */ + class ConversationAction extends Action { - var $id = null; + var $id = null; var $page = null; /** @@ -69,24 +70,47 @@ class ConversationAction extends Action return true; } + /** + * Handle the action + * + * @param array $args Web and URL arguments + * + * @return void + */ + function handle($args) { parent::handle($args); $this->showPage(); } + /** + * Returns the page title + * + * @return string page title + */ + function title() { return _("Conversation"); } + /** + * Show content. + * + * Display a hierarchical unordered list in the content area. + * Uses ConversationTree to do most of the heavy lifting. + * + * @return void + */ + function showContent() { // FIXME this needs to be a tree, not a list $qry = 'SELECT * FROM notice WHERE conversation = %s '; - $offset = ($this->page-1)*NOTICES_PER_PAGE; + $offset = ($this->page-1) * NOTICES_PER_PAGE; $limit = NOTICES_PER_PAGE + 1; $txt = sprintf($qry, $this->id); @@ -95,9 +119,9 @@ class ConversationAction extends Action 'notice:conversation:'.$this->id, $offset, $limit); - $nl = new NoticeList($notices, $this); + $ct = new ConversationTree($notices, $this); - $cnt = $nl->show(); + $cnt = $ct->show(); $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'conversation', array('id' => $this->id)); @@ -105,3 +129,170 @@ class ConversationAction extends Action } +/** + * Conversation tree + * + * The widget class for displaying a hierarchical list of notices. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou <evan@controlyourself.ca> + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ + +class ConversationTree extends NoticeList +{ + var $tree = null; + var $table = null; + + /** + * Show the tree of notices + * + * @return void + */ + + function show() + { + $cnt = 0; + + $this->tree = array(); + $this->table = array(); + + while ($this->notice->fetch()) { + + $cnt++; + + $id = $this->notice->id; + $notice = clone($this->notice); + + $this->table[$id] = $notice; + + if (is_null($notice->reply_to)) { + $this->tree['root'] = array($notice->id); + } else if (array_key_exists($notice->reply_to, $this->tree)) { + $this->tree[$notice->reply_to][] = $notice->id; + } else { + $this->tree[$notice->reply_to] = array($notice->id); + } + } + + $this->out->elementStart('div', array('id' =>'notices_primary')); + $this->out->element('h2', null, _('Notices')); + $this->out->elementStart('ul', array('class' => 'notices')); + + if (array_key_exists('root', $this->tree)) { + $rootid = $this->tree['root'][0]; + $this->showNoticePlus($rootid); + } + + $this->out->elementEnd('ul'); + $this->out->elementEnd('div'); + + return $cnt; + } + + /** + * Shows a notice plus its list of children. + * + * @param integer $id ID of the notice to show + * + * @return void + */ + + function showNoticePlus($id) + { + $notice = $this->table[$id]; + + // We take responsibility for doing the li + + $this->out->elementStart('li', array('class' => 'hentry notice', + 'id' => 'notice-' . $this->notice->id)); + + $item = $this->newListItem($notice); + $item->show(); + + if (array_key_exists($id, $this->tree)) { + $children = $this->tree[$id]; + + $this->out->elementStart('ul', array('class' => 'notices')); + + foreach ($children as $child) { + $this->showNoticePlus($child); + } + + $this->out->elementEnd('ul'); + } + + $this->out->elementEnd('li'); + } + + /** + * Override parent class to return our preferred item. + * + * @param Notice $notice Notice to display + * + * @return NoticeListItem a list item to show + */ + + function newListItem($notice) + { + return new ConversationTreeItem($notice, $this->out); + } +} + +/** + * Conversation tree list item + * + * Special class of NoticeListItem for use inside conversation trees. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou <evan@controlyourself.ca> + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ + +class ConversationTreeItem extends NoticeListItem +{ + /** + * start a single notice. + * + * The default creates the <li>; we skip, since the ConversationTree + * takes care of that. + * + * @return void + */ + + function showStart() + { + return; + } + + /** + * finish the notice + * + * The default closes the <li>; we skip, since the ConversationTree + * takes care of that. + * + * @return void + */ + + function showEnd() + { + return; + } + + /** + * show link to notice conversation page + * + * Since we're only used on the conversation page, we skip this + * + * @return void + */ + + function showContext() + { + return; + } +}
\ No newline at end of file diff --git a/lib/searchaction.php b/lib/searchaction.php index e7ad4affd..e74450e11 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -51,7 +51,7 @@ class SearchAction extends Action * * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/plugins/WikiHashtagsPlugin.php b/plugins/WikiHashtagsPlugin.php new file mode 100644 index 000000000..6d186a5fe --- /dev/null +++ b/plugins/WikiHashtagsPlugin.php @@ -0,0 +1,109 @@ +<?php +/** + * Laconica, the distributed open-source microblogging tool + * + * Plugin to show WikiHashtags content in the sidebar + * + * PHP version 5 + * + * LICENCE: This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @category Plugin + * @package Laconica + * @author Evan Prodromou <evan@controlyourself.ca> + * @copyright 2008 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +define('WIKIHASHTAGSPLUGIN_VERSION', '0.1'); + +/** + * Plugin to use WikiHashtags + * + * @category Plugin + * @package Laconica + * @author Evan Prodromou <evan@controlyourself.ca> + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + * @see Event + */ + +class WikiHashtagsPlugin extends Plugin +{ + function __construct($code=null) + { + parent::__construct(); + } + + function onStartShowSections($action) + { + $name = $action->trimmed('action'); + + if ($name == 'tag') { + + $taginput = $action->trimmed('tag'); + $tag = common_canonical_tag($taginput); + + if (!empty($tag)) { + + $url = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=render', + urlencode($tag)); + $editurl = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=edit', + urlencode($tag)); + + $context = stream_context_create(array('http' => array('method' => "GET", + 'header' => + "User-Agent: " . $this->userAgent()))); + $html = @file_get_contents($url, false, $context); + + $action->elementStart('div', array('id' => 'wikihashtags', 'class' => 'section')); + + if (!empty($html)) { + $action->element('style', null, + "span.editsection { display: none }\n". + "table.toc { display: none }"); + $action->raw($html); + $action->elementStart('p'); + $action->element('a', array('href' => $editurl, + 'title' => sprintf(_('Edit the article for #%s on WikiHashtags'), $tag)), + _('Edit')); + $action->element('a', array('href' => 'http://www.gnu.org/copyleft/fdl.html', + 'title' => _('Shared under the terms of the GNU Free Documentation License'), + 'rel' => 'license'), + 'GNU FDL'); + $action->elementEnd('p'); + } else { + $action->element('a', array('href' => $editurl), + sprintf(_('Start the article for #%s on WikiHashtags'), $tag)); + } + + $action->elementEnd('div'); + } + } + + return true; + } + + function userAgent() + { + return 'WikiHashtagsPlugin/'.WIKIHASHTAGSPLUGIN_VERSION . + ' Laconica/' . LACONICA_VERSION; + } +} |