+++ /dev/null
-<?php
-/**
- * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file LICENSE for license information (BSD). If you
- * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
- *
- * @author Jan Schneider <jan@horde.org>
- */
-
-require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
-
-function _getLinks($id, $subid, $name, $title)
-{
- $url = Horde::url('channels/aggregate.php');
- $url = Horde_Util::addParameter($url, 'channel_id', $id);
- $url = Horde_Util::addParameter($url, 'subchannel_id', $subid);
- $edit = array('url' => Horde_Util::addParameter($url,'action', 'edit'), 'text' => sprintf(_("Edit channel \"%s\""), $name), 'title' => $title);
- $delete = array('url' => Horde_Util::addParameter($url, 'action', 'delete'), 'text' => sprintf(_("Remove channel \"%s\""), $name), 'title' => $title);
- return array($edit, $delete);
-}
-
-$news = Jonah_News::factory();
-$renderer = new Horde_Form_Renderer();
-$vars = Horde_Variables::getDefaultVariables();
-
-/* Set up some variables. */
-$channel_id = $vars->get('channel_id');
-$channel = $news->getChannel($channel_id);
-if ($channel instanceof PEAR_Error) {
- throw new Jonah_Exception($channel);
-}
-$channel_name = $channel['channel_name'];
-$ids = preg_split('/:/', $channel['channel_url'], -1, PREG_SPLIT_NO_EMPTY);
-
-/* Get the vars for channel type. */
-$channel_type = $channel['channel_type'];
-if ($channel_type != Jonah::AGGREGATED_CHANNEL) {
- $notification->push(_("This is no aggregated channel."), 'horde.error');
- Horde::url('channels/edit.php', true)
- ->add('channel_id', $channel_id)
- ->redirect();
-}
-
-/* Check permissions and deny if not allowed. */
-if (!Jonah::checkPermissions(Jonah::typeToPermName($channel_type), Horde_Perms::EDIT, $channel_id)) {
- $notification->push(_("You are not authorised for this action."), 'horde.warning');
- Horde::authenticationFailureRedirect();
-}
-
-/* Set up the form. */
-$form = new Horde_Form($vars, sprintf(_("Aggregated channels for channel \"%s\""), $channel_name), 'channel_aggregate');
-$form->setButtons(_("Add"));
-$form->addHidden('', 'channel_id', 'int', false);
-$form->addVariable(_("Channel Name"), 'channel_name', 'text', true);
-$form->addVariable(_("Source URL"), 'channel_url', 'text', true, false, _("The url to use to fetch the stories, for example 'http://www.example.com/stories.rss'"));
-$form->addVariable(_("Link"), 'channel_link', 'text', false);
-$form->addVariable(_("Image"), 'channel_img', 'text', false);
-
-if ($form->validate($vars)) {
- $subchannel = array('channel_url' => $vars->get('channel_url'),
- 'channel_name' => $vars->get('channel_name'),
- 'channel_link' => $vars->get('channel_link'),
- 'channel_img' => $vars->get('channel_img'),
- 'channel_type' => Jonah::EXTERNAL_CHANNEL);
- if ($vars->get('subchannel_id')) {
- $subchannel['channel_id'] = $vars->get('subchannel_id');
- }
- $save = $news->saveChannel($subchannel);
- if (is_a($save, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error saving the channel: %s"), $save->getMessage()), 'horde.error');
- } else {
- $notification->push(sprintf(_("The channel \"%s\" has been saved."), $vars->get('channel_name')), 'horde.success');
- if (!$vars->get('subchannel_id')) {
- $ids[] = $save;
- $channel['channel_url'] = implode(':', $ids);
- $save = $news->saveChannel($channel);
- if (is_a($save, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error updating the channel: %s"), $save->getMessage()), 'horde.error');
- } else {
- $notification->push(sprintf(_("The channel \"%s\" has been updated."), $channel['channel_name']), 'horde.success');
- }
- }
-
- Horde::url('channels/aggregate.php', true)
- ->add('channel_id', $channel_id)
- ->redirect();
- }
-} elseif ($vars->get('action') == 'delete') {
- $subchannel = $news->getChannel($vars->get('subchannel_id'));
- $result = $news->deleteChannel($vars->get('subchannel_id'));
- if (is_a($result, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error removing the channel: %s"), $result->getMessage()), 'horde.error');
- } else {
- $notification->push(sprintf(_("The channel \"%s\" has been removed."), $subchannel['channel_name']), 'horde.success');
- array_splice($ids, array_search($subchannel['channel_id'], $ids), 1);
- $channel['channel_url'] = implode(':', $ids);
- $save = $news->saveChannel($channel);
- if (is_a($save, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error updating the channel: %s"), $save->getMessage()), 'horde.error');
- } else {
- $notification->push(sprintf(_("The channel \"%s\" has been updated."), $channel['channel_name']), 'horde.success');
- }
- }
-
- Horde::url('channels/aggregate.php', true)
- ->add('channel_id', $channel_id)
- ->redirect();
-} elseif ($vars->get('action') == 'edit') {
- $form->addHidden('', 'subchannel_id', 'int', false);
- $form->setButtons(_("Update"));
- $subchannel = $news->getChannel($vars->get('subchannel_id'));
- $vars->set('channel_name', $subchannel['channel_name']);
- $vars->set('channel_url', $subchannel['channel_url']);
- $vars->set('channel_link', $subchannel['channel_link']);
- $vars->set('channel_img', $subchannel['channel_img']);
-}
-
-foreach ($ids as $id) {
- $subchannel = $news->getChannel($id);
- if (is_a($subchannel, 'PEAR_Error')) {
- $name = $subchannel->getMessage();
- $url = '';
- } elseif (empty($subchannel['channel_name'])) {
- $name = $subchannel['channel_url'];
- $url = $subchannel['channel_url'];
- } else {
- $name = $subchannel['channel_name'];
- $url = $subchannel['channel_url'];
- }
- $form->insertVariableBefore('channel_name', '', 'subchannel' . $id, 'link', false, false, null, array(_getLinks($channel_id, $id, $name, $url)));
-}
-
-Horde::startBuffer();
-$form->renderActive($renderer, $vars, 'aggregate.php', 'post');
-$main = Horde::endBuffer();
-
-$template = new Horde_Template();
-$template->set('main', $main);
-$template->set('menu', Horde::menu());
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
-
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/main/main.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
- *
- * $Horde: jonah/channels/delete.php,v 1.36 2009/11/24 04:15:37 chuck Exp $
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
*/
-
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
-require_once 'Horde/Form.php';
-require_once 'Horde/Form/Renderer.php';
-
-$news = Jonah_News::factory();
+Horde_Registry::appInit('jonah');
/* Set up the form variables and the form. */
-$vars = Horde_Variables::getDefaultVariables();
-$form_submit = $vars->get('submitbutton');
-$channel_id = $vars->get('channel_id');
-
-$channel = $news->getChannel($channel_id);
-if (is_a($channel, 'PEAR_Error')) {
- $notification->push(_("Invalid channel specified for deletion."), 'horde.message');
- Horde::url('channels/index.php', true)->redirect();
-}
-
-/* Check permissions and deny if not allowed. */
-if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::DELETE, $channel_id)) {
- $notification->push(_("You are not authorised for this action."), 'horde.warning');
- Horde::authenticationFailureRedirect();
-}
-
-/* If not yet submitted set up the form vars from the fetched
- * channel. */
-if (empty($form_submit)) {
- $vars = new Horde_Variables($channel);
-}
-
-$title = sprintf(_("Delete News Channel \"%s\"?"), $vars->get('channel_name'));
-$form = new Horde_Form($vars, $title);
-
-$form->setButtons(array(_("Delete"), _("Do not delete")));
-$form->addHidden('', 'channel_id', 'int', true, true);
-
-$msg = _("Really delete this News Channel?");
-if ($vars->get('channel_type') == Jonah::INTERNAL_CHANNEL) {
- $msg .= ' ' . _("All stories created in this channel will be lost!");
-} else {
- $msg .= ' ' . _("Any cached stories for this channel will be lost!");
-}
-$form->addVariable($msg, 'confirm', 'description', false);
-
-if ($form_submit == _("Delete")) {
- if ($form->validate($vars)) {
- $form->getInfo($vars, $info);
- $delete = $news->deleteChannel($info);
- if (is_a($delete, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error deleting the channel: %s"), $delete->getMessage()), 'horde.error');
- } else {
- $notification->push(_("The channel has been deleted."), 'horde.success');
- Horde::url('channels/index.php', true)->redirect();
- }
- }
-} elseif (!empty($form_submit)) {
- $notification->push(_("Channel has not been deleted."), 'horde.message');
- Horde::url('channels/index.php', true)->redirect();
-}
-
-$template = new Horde_Template();
-
-// Buffer the main form and send to the template
-Horde::startBuffer();
-$form->renderActive(null, $vars, 'delete.php', 'post');
-$template->set('main', Horde::endBuffer());
-$template->set('menu', Horde::menu());
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
+$params = array('vars' => Horde_Variables::getDefaultVariables(),
+ 'registry' => &$registry,
+ 'notification' => &$notification);
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/main/main.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+$view = new Jonah_View_ChannelDelete($params);
+$view->run();
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
- *
- * $Horde: jonah/channels/edit.php,v 1.37 2009/11/24 04:15:37 chuck Exp $
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
*/
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
-require_once JONAH_BASE . '/lib/Forms/Feed.php';
-require_once 'Horde/Form/Renderer.php';
-
-$news = Jonah_News::factory();
-
-/* Set up the form variables and the form. */
-$vars = Horde_Variables::getDefaultVariables();
-$form = new FeedForm($vars);
-
-/* Set up some variables. */
-$formname = $vars->get('formname');
-$channel_id = $vars->get('channel_id');
-
-/* Form not yet submitted and is being edited. */
-if (!$formname && $channel_id) {
- $vars = new Horde_Variables($news->getChannel($channel_id));
-}
-
-/* Get the vars for channel type. */
-$channel_type = $vars->get('channel_type');
-$old_channel_type = $vars->get('old_channel_type');
-$changed_type = false;
-
-/* Check permissions and deny if not allowed. */
-if (!Jonah::checkPermissions(Jonah::typeToPermName($channel_type), Horde_Perms::EDIT, $channel_id)) {
- $notification->push(_("You are not authorised for this action."), 'horde.warning');
- Horde::authenticationFailureRedirect();
-}
-
-/* If this is null then new form, so set both to default. */
-if (is_null($channel_type)) {
- $channel_type = Jonah_News::getDefaultType();
- $old_channel_type = $channel_type;
-}
-
-/* Check if channel type has been changed and notify. */
-if ($channel_type != $old_channel_type && $formname) {
- $changed_type = true;
- $notification->push(_("Feed type changed."), 'horde.message');
-}
-$vars->set('old_channel_type', $channel_type);
-
-/* Output the extra fields required for this channel type. */
-$form->setExtraFields($channel_type, $channel_id);
-
-if ($formname && !$changed_type) {
- if ($form->validate($vars)) {
- $form->getInfo($vars, $info);
- $save = $news->saveChannel($info);
- if (is_a($save, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error saving the feed: %s"), $save->getMessage()), 'horde.error');
- } else {
- $notification->push(sprintf(_("The feed \"%s\" has been saved."), $info['channel_name']), 'horde.success');
- if ($channel_type == Jonah::AGGREGATED_CHANNEL) {
- $notification->push(_("You can now edit the sub-feeds."), 'horde.message');
- } else {
- Horde::url('channels/index.php', true)->redirect();
- }
- }
- }
-}
-
-$renderer = new Horde_Form_Renderer();
-Horde::startBuffer();
-$form->renderActive($renderer, $vars, 'edit.php', 'post');
-$main = Horde::endBuffer();
-
-$template = new Horde_Template();
-$template->set('main', $main);
-$template->set('menu', Horde::menu());
+Horde_Registry::appInit('jonah');
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
+$params = array('vars' => Horde_Variables::getDefaultVariables(),
+ 'registry' => &$registry,
+ 'notification' => &$notification);
-$title = $form->getTitle();
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/main/main.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+$view = new Jonah_View_ChannelEdit($params);
+$view->run();
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
- *
- * $Horde: jonah/channels/index.php,v 1.49 2009/11/24 04:15:37 chuck Exp $
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
*/
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
+Horde_Registry::appInit('jonah');
if (!Jonah::checkPermissions('jonah:news', Horde_Perms::EDIT)) {
$notification->push(_("You are not authorised for this action."), 'horde.warning');
$registry->authenticateFailure();
}
-$have_news = Jonah_News::getAvailableTypes();
+$have_news = Jonah::getAvailableTypes();
if (empty($have_news)) {
$notification->push(_("News is not enabled."), 'horde.warning');
- Horde::url('index.php', true)->redirect();
-}
-
-$news = Jonah_News::factory();
-
-$channels = $news->getChannels(array_keys($have_news));
-if (is_a($channels, 'PEAR_Error')) {
- $notification->push(sprintf(_("An error occurred fetching channels: %s"), $channels->getMessage()), 'horde.error');
- $channels = false;
-} elseif ($channels) {
- $channels = Jonah::checkPermissions('channels', Horde_Perms::SHOW, $channels);
- /* Build channel specific fields. */
- foreach ($channels as $key => $channel) {
- /* Edit channel link. */
- $url = Horde::url('channels/edit.php');
- $url = Horde_Util::addParameter($url, 'channel_id', $channel['channel_id']);
- $channels[$key]['edit_link'] = Horde::link($url, _("Edit channel"), '', '', '', _("Edit channel")) . Horde::img('edit.png') . '</a>';
-
- /* Delete channel link. */
- $url = Horde::url('channels/delete.php');
- $url = Horde_Util::addParameter($url, 'channel_id', $channel['channel_id']);
- $channels[$key]['delete_link'] = Horde::link($url, _("Delete channel"), '', '', '', _("Delete channel")) . Horde::img('delete.png') . '</a>';
- /* View stories link. */
- $url = Horde::url('stories/index.php');
- $url = Horde_Util::addParameter($url, 'channel_id', $channel['channel_id']);
- $channels[$key]['stories_url'] = $url;
-
- /* Channel type specific links. */
- $channels[$key]['addstory_link'] = '';
- $channels[$key]['refresh_link'] = '';
-
- switch ($channel['channel_type']) {
- case Jonah::INTERNAL_CHANNEL:
- /* Add story link. */
- $url = Horde::url('stories/edit.php');
- $url = Horde_Util::addParameter($url, 'channel_id', $channel['channel_id']);
- $channels[$key]['addstory_link'] = Horde::link($url, _("Add story"), '', '', '', _("Add story")) . Horde::img('new.png') . '</a>';
- break;
-
- case Jonah::EXTERNAL_CHANNEL:
- case Jonah::AGGREGATED_CHANNEL:
- /* Refresh cache link. */
- $url = Horde::url('stories/index.php');
- $url = Horde_Util::addParameter($url, array('channel_id' => $channel['channel_id'], 'refresh' => '1', 'url' => Horde::selfUrl()));
- $channels[$key]['refresh_link'] = Horde::link($url, _("Refresh channel"), '', '', '', _("Refresh channel")) . Horde::img('reload.png') . '</a>';
- break;
- }
-
- $channels[$key]['channel_type'] = Jonah::getChannelTypeLabel($channel['channel_type']);
- /* TODO: pref setting for date display. */
- $channels[$key]['channel_updated'] = ($channel['channel_updated'] ? date('M d, Y H:i', (int)$channel['channel_updated']) : '-');
- }
+ $url = Horde::url('index.php');
+ header('Location: ' . $url);
+ exit;
}
-$template = new Horde_Template();
-$template->set('header', _("Manage Feeds"));
-$template->set('listheaders', array(array('attrs' => ' class="sortdown"', 'label' => _("Name")),
- array('attrs' => '', 'label' => _("Type")),
- array('attrs' => '', 'label' => _("Last Update"))));
-$template->set('channels', $channels, true);
-$template->set('menu', Horde::menu());
-$template->set('search_img', Horde::img('search.png'));
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
+$params = array('notification' => &$notification,
+ 'prefs' => &$prefs,
+ 'registry' => &$registry
+ );
-$title = _("Feeds");
-Horde::addScriptFile('tables.js', 'horde', true);
-Horde::addScriptFile('quickfinder.js', 'horde', true);
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/channels/index.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+$view = new Jonah_View_ChannelList($params);
+$view->run();
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Setup default routes
+ */
+$m->connect('Admin', '/admin/:section/:page', array(
+ 'controller' => 'admin',
+ 'section' => '',
+ 'page' => '',
+));
+
+// Valid filter names are "author", "tag" and "date"
+// @TODO represent those with route requirements
+$m->connect('Default', '/feeds/:feed/:filter/:value', array(
+ 'controller' => 'feed',
+ 'feed' => '',
+ 'filter' => '',
+ 'value' => '',
+));
+
+// api endpoint for getting post counts?
+//$m->connect('/feeds/:feed/-/posts/count', array(
+// 'controller' => 'api',
+// 'action' => 'count'));
+
+
+// Local route overrides
+if (file_exists(dirname(__FILE__) . '/routes.local.php')) {
+ include dirname(__FILE__) . '/routes.local.php';
+}
/**
* Script to handle requests for html delivery of stories.
*
- * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you did not
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
'authentication' => 'none',
'session_control' => 'readonly'
));
-require JONAH_BASE . '/config/templates.php';
-
-// TODO - check if a user, have button to add channel to their
-// personal aggregated channel.
-
-$news = Jonah_News::factory();
/* Get the id and format of the channel to display. */
$criteria = Horde_Util::nonInputVar('criteria');
if (!$criteria) {
- $criteria['channel_id'] = Horde_Util::getFormData('channel_id');
- $criteria['channel_format'] = Horde_Util::getFormData('format');
+ $criteria['feed'] = Horde_Util::getFormData('channel_id');
+ $criteria['format'] = Horde_Util::getFormData('format');
}
-
-if (empty($criteria['channel_format'])) {
+if (empty($criteria['format'])) {
// Select the default channel format
- $criteria['channel_format'] = key($templates);
-}
-
-/* Get requested channel. */
-$channel = $news->getChannel($criteria['channel_id']);
-if (is_a($channel, 'PEAR_Error')) {
- Horde::logMessage($channel, 'ERR');
- $notification->push(_("Invalid channel."), 'horde.error');
- Horde::url('delivery/index.php', true)->redirect();
+ // TODO: FIXME
+ $criteria['format'] = 'standard';
}
-$title = sprintf(_("HTML Delivery for \"%s\""), $channel['channel_name']);
-
-$options = array();
-foreach ($templates as $key => $info) {
- $options[] = '<option value="' . $key . '"' . ($key == $criteria['channel_format'] ? ' selected="selected"' : '') . '>' . $info['name'] . '</option>';
-}
-
-$template = new Horde_Template();
-$template->setOption('gettext', 'true');
-$template->set('url', Horde::selfUrl());
-$template->set('session', Horde_Util::formInput());
-$template->set('channel_id', $criteria['channel_id']);
-$template->set('channel_name', $channel['channel_name']);
-$template->set('format', $criteria['channel_format']);
-$template->set('options', $options);
-$template->set('stories', $news->renderChannel($criteria['channel_id'], $criteria['channel_format']));
-$template->set('menu', Horde::menu());
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
-
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/delivery/html.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+$params = array('registry' => &$registry,
+ 'notification' => &$notification,
+ 'conf' => &$conf,
+ 'criteria' => &$criteria);
+$view = new Jonah_View_DeliveryHtml($params);
+$view->run();
<?php
/**
- * $Horde: jonah/delivery/index.php,v 1.27 2009/06/10 05:24:47 slusarz Exp $
*
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you did
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Ben Klang <ben@alkaloid.net>
*/
-
$parts = explode('/', Horde_Util::getPathInfo());
$lastpart = null;
$deliveryType = null;
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you did
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
*/
-
require_once dirname(__FILE__) . '/../lib/Application.php';
$jonah = Horde_Registry::appInit('jonah', array(
'authentication' => 'none',
'session_control' => 'readonly'
));
-$news = Jonah_News::factory();
+$driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
-// See if the criteria has already been loaded by the index page
+/* See if the criteria has already been loaded by the index page */
$criteria = Horde_Util::nonInputVar('criteria');
if (!$criteria) {
- $criteria = array();
- $criteria['channel_id'] = Horde_Util::getFormData('channel_id');
- $criteria['tag_id'] = Horde_Util::getFormData('tag_id');
- $criteria['feed_type'] = basename(Horde_Util::getFormData('type'));
+ $criteria = array(
+ 'channel_id' => Horde_Util::getFormData('channel_id'),
+ 'tag_id' => Horde_Util::getFormData('tag_id'),
+ 'feed_type' => basename(Horde_Util::getFormData('type'))
+ );
}
+/* Default to RSS2 */
if (empty($criteria['feed_type'])) {
- // If not specified, default to RSS2
$criteria['feed_type'] = 'rss2';
}
/* Fetch the channel info and the story list and check they are both valid.
* Do a simple exit in case of errors. */
-
-
-$channel = $news->getChannel($criteria['channel_id']);
-if (is_a($channel, 'PEAR_Error')) {
- Horde::logMessage($channel, 'ERR');
+try {
+ $channel = $driver->getChannel($criteria['channel_id']);
+} catch (Exception $e) {
+ Horde::logMessage($e, 'ERR');
header('HTTP/1.0 404 Not Found');
echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
exit;
}
-/* Check for a tag search. */
+/* Build search array */
+$search = array('channel_id' => $criteria['channel_id'],
+ 'tags' => array($criteria['tag_id'],
+ 'limit' => 10));
+
+/* Used in template for channel name */
if (!empty($criteria['tag_id'])) {
- $tag_name = array_shift($news->getTagNames(array($criteria['tag_id'])));
- $stories = $news->searchTagsById(array($criteria['tag_id']), 10, 0, array($criteria['channel_id']));
-} else {
- $stories = $news->getStories($criteria['channel_id'], 10, 0, false, time());
+ $tag_name = array_shift($driver->getTagNames(array($criteria['tag_id'])));
}
-if (is_a($stories, 'PEAR_Error')) {
- Horde::logMessage($stories, 'ERR');
+
+/* Fetch stories */
+try {
+ $stories = $driver->getStories($criteria);
+} catch (Exception $e) {
+ Horde::logMessage($e, 'ERR');
$stories = array();
}
-
+/* Build the template (@TODO: Use Horde_View) */
$template = new Horde_Template();
$template->set('charset', $GLOBALS['registry']->getCharset());
$template->set('jonah', 'Jonah ' . $registry->getVersion() . ' (http://www.horde.org/jonah/)');
$template->set('channel_rss', htmlspecialchars(Horde_Util::addParameter(Horde::url('delivery/rss.php', true, -1), array('type' => 'rss', 'channel_id' => $channel['channel_id']))));
$template->set('channel_rss2', htmlspecialchars(Horde_Util::addParameter(Horde::url('delivery/rss.php', true, -1), array('type' => 'rss2', 'channel_id' => $channel['channel_id']))));
foreach ($stories as &$story) {
- $story['story_title'] = @htmlspecialchars($story['story_title'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
- $story['story_desc'] = @htmlspecialchars($story['story_desc'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
- $story['story_link'] = htmlspecialchars($story['story_link']);
- $story['story_permalink'] = (isset($story['story_permalink']) ? htmlspecialchars($story['story_permalink']) : '');
- $story['story_published'] = htmlspecialchars(date('r', $story['story_published']));
- if (!empty($story['story_body_type']) && $story['story_body_type'] == 'text') {
- $story['story_body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
+ $story['title'] = @htmlspecialchars($story['title'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ $story['description'] = @htmlspecialchars($story['description'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ $story['permalink'] = htmlspecialchars($story['permalink']);
+ $story['published'] = htmlspecialchars(date('r', $story['published']));
+ if (!empty($story['body_type']) && $story['body_type'] == 'text') {
+ $story['body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
}
}
$template->set('stories', $stories);
* @author Ben Klang <ben@alkaloid.net>
*/
-require_once dirname(__FILE__) . '/../lib/Application.php';
+require_once dirname(__FILE__) . '/lib/Application.php';
$jonah = Horde_Registry::appInit('jonah', array(
'authentication' => 'none',
'session_control' => 'readonly'
));
-$jonah = Horde_Registry::appInit('jonah');
+$m = new Horde_Routes_Mapper();
+
+require JONAH_BASE . '/config/routes.php';
require JONAH_BASE . '/config/templates.php';
// Grab, and hopefully match, the URL
-$url = Horde_Util::getPathInfo();
-parse_str($_SERVER['QUERY_STRING'], $args);
-Horde_Util::dispelMagicQuotes($args);
+$request = new Horde_Controller_Request_Http();
+$url = $request->getPath();
+
+$args = $request->getGetParams();
+$result = $m->match('/' . $url);
$criteria = array();
-$result = $m->match($url);
-if (isset($result['controller']) && $result['controller'] == 'admin') {
- // Insert admin controllers here.
-} elseif (isset($result['feed'])) {
+// @TODO: This should be handled by controller objects, but for now just use
+// a switch conditional until we move to Horde_Controller
+switch ($result['controller']) {
+case 'admin':
+ // TODO:
+ exit;
+case 'feed':
// Default settings
$defaults = array(
'format' => 'html',
break;
}
+ // @TODO: These will be implemented as GData's categories, not as
+ // part of the route proper.
case 'tag':
$criteria['tags'] = array($result['value']);
break;
}
// Preserve remaining args
+ // @TODO: Don't think we need to preserve the query string once we get here.
$criteria = array_merge($defaults, $args, $criteria);
-
- require dirname(__FILE__) . '/feed.php';
+ $class = 'Jonah_View_Delivery' . $criteria['format'];
+
+ //@TODO: FIXME - format (html/rss/pdf) is dealt with by the view object we
+ // instantiate but html _currently_ needs a format. Think we'll just have to
+ // pick a default format to render when requested this way.
+ $criteria['format'] = 'standard';
+ $params = array('registry' => &$registry,
+ 'notification' => &$notification,
+ 'conf' => &$conf,
+ 'criteria' => &$criteria);
+ $view = new $class($params);
+ $view->run();
+ break;
}
--- /dev/null
+## This file should be reviewed prior to inclusion in your lighttpd
+## configuration. Specifically, if you have jonah somewhere other than
+## /horde/jonah you will need to edit the following rules to match your server
+## configuration.
+
+## This file should be included in your lighttpd.conf file with the "include"
+## directive. Example:
+## include "path/to/lighttpd-jonah.conf"
+## The exact path you use will of course depend on your specific configuration.
+
+## Rules for handling restful delivery requests
+url.rewrite-once += (
+ "^/horde/jonah/feeds/(.*)\?(.*)$" => "/horde/jonah/dispatcher.php?$2",
+ "^/horde/jonah/feeds/(.*)$" => "/horde/jonah/dispatcher.php"
+)
\ No newline at end of file
* This file defines Jonah's external API interface. Other
* applications can interact with Jonah through this API.
*
+ * Copyright 2002-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
* @package Jonah
*/
class Jonah_Api extends Horde_Registry_Api
/**
* Get a list of stored channels.
*
- * @param integer $type The type of channel to filter for. Possible
- * values are either Jonah::INTERNAL_CHANNEL
- * to fetch only a list of internal channels,
- * or Jonah::EXTERNAL_CHANNEL for only external.
- * If null both channel types are returned.
- *
- * @return mixed An array of channels or PEAR_Error on error.
+ * @return array An array of channels
*/
- public function listFeeds($type = null)
+ public function listFeeds()
{
- $news = Jonah_News::factory();
- $channels = $news->getChannels($type);
-
- return $channels;
+ return $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannels();
}
/**
* Return the requested stories
*
- * @param int $channel_id The channel to get the stories from.
- * @param int $max_stories The maximum number of stories to get.
- * @param int $start_at The story number to start retrieving.
- * @param int $order How to order the results.
+ * @param integer $channel_id The channel to get the stories from.
+ * @param array $filter Additional, optional filters.
+ * <pre>
+ * max_stories The maximum number of stories to get.
+ * start_at The story number to start retrieving.
+ * order How to order the results.
+ * </pre>
*
- * @return An array of story information | PEAR_Error
+ * @return array An array of story information
*/
- public function stories($channel_id, $max_stories = 10, $start_at = 0,
- $order = 0)
+ public function stories($channel_id, $filter = array())
{
- $news = Jonah_News::factory();
- $stories = $news->getStories($channel_id, $max_stories, $start_at, false,
- time(), false, $order);
+ $filter = new Horde_Support_Array($filter);
+
+ $stories = $GLOBALS['injector']
+ ->getInstance('Jonah_Driver')
+ ->getStories(
+ array(
+ 'channel_id' => $channel_id,
+ 'limit' => $filter->get('max_stories', 10),
+ 'startnumber' => $filter->get('start_at', 0),
+ 'published' => true,
+ ),
+ $order
+ );
foreach (array_keys($stories) as $s) {
- if (empty($stories[$s]['story_body_type']) || $stories[$s]['story_body_type'] == 'text') {
- $stories[$s]['story_body_html'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($stories[$s]['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
+ if (empty($stories[$s]['body_type']) || $stories[$s]['body_type'] == 'text') {
+ $stories[$s]['body_html'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($stories[$s]['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
} else {
- $stories[$s]['story_body_html'] = $stories[$s]['story_body'];
+ $stories[$s]['body_html'] = $stories[$s]['body'];
}
}
* @param integer $story_id The story id to fetch.
* @param boolean $read Whether to update the read count.
*
- * @return mixed An array of story data | PEAR_Error
+ * @return array An array of story data
*/
public function story($channel_id, $story_id, $read = true)
{
- $news = Jonah_News::factory();
- $story = $news->getStory($channel_id, $story_id, $read);
- if (is_a($story, 'PEAR_Error')) {
- Horde::logMessage($story, 'ERR');
- return false;
- }
- if (empty($story['story_body_type']) || $story['story_body_type'] == 'text') {
- $story['story_body_html'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
+ $story = $GLOBALS['injector']->getInstance('Jonah_Driver')->getStory($channel_id, $story_id, $read);
+ if (empty($story['body_type']) || $story['body_type'] == 'text') {
+ $story['body_html'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
} else {
- $story['story_body_html'] = $story['story_body'];
+ $story['body_html'] = $story['body'];
}
return $story;
if (!$GLOBALS['conf']['comments']['allow']) {
return false;
}
+ $story = $GLOBALS['injector']->getInstance('Jonah_Driver')->getStory(null, $story_id);
- $news = Jonah_News::factory();
- $story = $news->getStory(null, $story_id);
- if (is_a($story, 'PEAR_Error')) {
- return false;
- }
-
- return $story['story_title'];
+ return $story['title'];
}
/**
*
* @param array $channel_id An optional array of channel_ids.
*
- * @return mixed An array containing tag_name, and total | PEAR_Error
+ * @return array An array containing tag_name, and total
*/
public function listTagInfo($tags = array(), $channel_id = null)
{
- $news = Jonah_News::factory();
- return $news->listTagInfo($tags, $channel_id);
+ return $GLOBALS['injector']->getInstance('Jonah_Driver')->listTagInfo($tags, $channel_id);
}
/**
*
* @param array $names An array of names to search for
*
- * @return mixed An array of tag_name => tag_ids | PEAR_Error
+ * @return Array An array of tag_name => tag_ids
*/
public function getTagIds($names)
{
- $news = Jonah_News::factory();
- return $news->getTagIds($names);
+ return $GLOBALS['injector']->getInstance('Jonah_Driver')->getTagIds($names);
}
/**
* Searches internal channels for stories tagged with all requested tags.
* Returns an application-agnostic array (useful for when doing a tag search
- * across multiple applications) containing the following keys:
- * <pre>
- * 'title' - The title for this resource.
- * 'desc' - A terse description of this resource.
- * 'view_url' - The URL to view this resource.
- * 'app' - The Horde application this resource belongs to.
- * </pre>
+ * across multiple applications).
+ *
*
* The 'raw' story array can be returned instead by setting $raw = true.
*
- * @param array $names An array of tag_names to search for (AND'd together).
- * @param integer $max The maximum number of stories to return.
- * @param integer $from The number of the story to start with.
- * @param array $channel_id An array of channel_ids to limit the search to.
- * @param integer $order How to order the results (a Jonah::ORDER_* constant)
+ * @param array $names An array of tag_names to search for
+ * (AND'd together).
+ * @param array $filter An array of optional filter parameters.
+ * <pre>
+ * max The maximum number of stories to return.
+ * from The number of the story to start with.
+ * channel_id An array of channel_ids to limit the search to.
+ * order How to order the results (a Jonah::ORDER_* constant)
+ * </pre>
* @param boolean $raw Return the raw story data?
*
- * @return mixed An array of results | PEAR_Error
+ * @return An array of results with the following structure:
+ * <pre>
+ * 'title' - The title for this resource.
+ * 'desc' - A terse description of this resource.
+ * 'view_url' - The URL to view this resource.
+ * 'app' - The Horde application this resource belongs to.
+ * </pre>
*/
- public function searchTags($names, $max = 10, $from = 0, $channel_id = array(),
- $order = 0, $raw = false)
+ public function searchTags($names, $filter = array(), $raw = false)
{
global $registry;
- $news = Jonah_News::factory();
- $results = $news->searchTags($names, $max, $from, $channel_id, $order);
- if (is_a($results, 'PEAR_Error')) {
- return $results;
- }
+ // @TODO: Refactor when moving tag to content_tagger
+ $filter = new Horde_Support_Array($filter);
+ $results = $GLOBALS['injector']
+ ->getInstance('Jonah_Driver')
+ ->searchTags($names, $filter->max, $filter->from, $filter->channel_id, $filter->order);
+
$return = array();
if ($raw) {
// Requesting the raw story information as returned from searchTags,
// find useful.
$comments = $GLOBALS['conf']['comments']['allow'] && $registry->hasMethod('forums/numMessages');
foreach ($results as $story) {
- if (empty($story['story_body_type']) || $story['story_body_type'] == 'text') {
- $story['story_body_html'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
+ if (empty($story['body_type']) || $story['body_type'] == 'text') {
+ $story['body_html'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
} else {
- $story['story_body_html'] = $story['story_body'];
+ $story['body_html'] = $story['body'];
}
if ($comments) {
$story['num_comments'] = $registry->call('forums/numMessages',
- array($story['story_id'],
+ array($story['id'],
$registry->getApp()));
}
- $return[$story['story_id']] = $story;
+ $return[$story['id']] = $story;
}
} else {
foreach($results as $story) {
if (!empty($story)) {
- $return[] = array('title' => $story['story_title'],
- 'desc' => $story['story_desc'],
- 'view_url' => $story['story_link'],
+ $return[] = array('title' => $story['title'],
+ 'desc' => $story['desc'],
+ 'view_url' => $story['link'],
'app' => 'jonah');
}
}
*/
public function storyCount($channel_id)
{
- global $registry;
-
- $results = $GLOBALS['injector']->getInstance('Jonah_Driver')->getStoryCount($channel_id);
- if (is_a($results, 'PEAR_Error')) {
- return 0;
- }
-
- return $results;
+ return $GLOBALS['injector']->getInstance('Jonah_Driver')->getStoryCount($channel_id);
}
}
'news' => array(
'title' => _("News")
),
- 'news:internal_channels' => array(
- 'title' => _("Internal Channels")
- ),
- 'news:external_channels' => array(
- 'title' => _("External Channels")
+ 'news:channels' => array(
+ 'title' => _("Channels")
)
);
/* Loop through internal channels and add them to the perms
* titles. */
- $news = Jonah_News::factory();
- $channels = $news->getChannels(Jonah::INTERNAL_CHANNEL);
-
- foreach ($channels as $channel) {
- $perms['news:internal_channels:' . $channel['channel_id']] = array(
- 'title' => $channel['channel_name']
- );
- }
-
- /* Loop through external channels and add their ids to the
- * perms. */
- $channels = $news->getChannels(Jonah::EXTERNAL_CHANNEL);
+ $channels = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannels();
foreach ($channels as $channel) {
- $perms['news:external_channels:' . $channel['channel_id']] = array(
+ $perms['news:channels:' . $channel['channel_id']] = array(
'title' => $channel['channel_name']
);
}
}
$url = Horde::url('stories/');
- $news = Jonah_News::factory();
- $channels = $news->getChannels('internal');
- if ($channels instanceof PEAR_Error) {
+ $driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
+
+ try {
+ $channels = $driver->getChannels('internal');
+ } catch (Jonah_Exception $e) {
+ var_dump($e);
return;
}
- $channels = Jonah::checkPermissions('channels', Horde_Perms::SHOW, $channels);
+ $channels = Jonah::checkPermissions('channels', Horde_Perms::SHOW, $channels);
foreach ($channels as $channel) {
$tree->addNode(
$parent . $channel['channel_id'],
*/
function _params()
{
- return array(
- 'results_url' => array(
- 'name' => _("Results URL"),
- 'type' => 'text',
- 'default' => Horde::url('stories/results.php?tag_id=@id@')));
+ return array();
+
}
function _title()
function _content()
{
- $news = Jonah_News::factory();
-
/* Get the tags */
- $tags = $news->listTagInfo();
+ $tags = $GLOBALS['injector']->getInstance('Jonah_Driver')->listTagInfo();
if (count($tags)) {
- $cloud = new Horde_Core_Ui_TagCloud();
+ $url = Horde::url('stories/results.php');
+ $cloud = new Horde_Ui_TagCloud();
foreach ($tags as $id => $tag) {
- $cloud->addElement($tag['tag_name'], str_replace(array('@id@', '@tag@'), array($id, $tag['tag_name']), $this->_params['results_url']), $tag['total']);
+ $cloud->addElement($tag['tag_name'], $url->copy()->add('tag_id', $id), $tag['total']);
}
$html = $cloud->buildHTML();
} else {
$html = '';
}
+
return $html;
}
* This class extends Horde_Block:: to provide a list of deliverable internal
* channels.
*
- * Copyright 2004-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
* This class extends Horde_Block:: to provide the api to embed news
* in other Horde applications.
*
- * Copyright 2002-2007 Roel Gloudemans <roel@gloudemans.info>
+ * Copyright 2002-2010 Roel Gloudemans <roel@gloudemans.info>
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Roel Gloudemans <roel@gloudemans.info>
- * @package Horde_Block
+ * @package Jonah
*/
-class Horde_Block_Jonah_latest extends Horde_Block {
-
+class Horde_Block_Jonah_latest extends Horde_Block
+{
var $_app = 'jonah';
-
var $_story = null;
/**
'type' => 'enum',
'values' => array());
- $news = Jonah_News::factory();
- $channels = $news->getChannels(Jonah::INTERNAL_CHANNEL);
+ $channels = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannels();
foreach ($channels as $channel) {
$params['source']['values'][$channel['channel_id']] = $channel['channel_name'];
}
return _("Latest News");
}
- $story = $this->_fetch();
- return is_a($story, 'PEAR_Error')
- ? @htmlspecialchars($story->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset())
- : '<span class="storyDate">'
- . @htmlspecialchars($story['story_updated_date'], ENT_COMPAT, $GLOBALS['registry']->getCharset())
- . '</span> '
- . @htmlspecialchars($story['story_title'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ try {
+ $story = $this->_fetch();
+ } catch (Exception $e) {
+ return @htmlspecialchars($e->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ }
+
+ return '<span class="storyDate">'
+ . @htmlspecialchars($story['updated_date'], ENT_COMPAT, $GLOBALS['registry']->getCharset())
+ . '</span> '
+ . @htmlspecialchars($story['title'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
}
/**
return _("No channel specified.");
}
- $story = $this->_fetch();
- if (is_a($story, 'PEAR_Error')) {
- return sprintf(_("Error fetching story: %s"), $story->getMessage());
+ try {
+ $story = $this->_fetch();
+ } catch (Exception $e) {
+ return sprintf(_("Error fetching story: %s"), $e->getMessage());
}
- if (empty($story['story_body_type']) || $story['story_body_type'] == 'text') {
- $story['story_body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
+ if (empty($story['body_type']) || $story['body_type'] == 'text') {
+ $story['body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
}
- return '<p class="storySubtitle">' . htmlspecialchars($story['story_desc']) .
- '</p><div class="storyBody">' . $story['story_body'] . '</div>';
+ return '<p class="storySubtitle">' . htmlspecialchars($story['description']) . '</p><div class="storyBody">' . $story['body'] . '</div>';
}
/**
}
if (is_null($this->_story)) {
- $news = Jonah_News::factory();
- $this->_story = $news->getStory($this->_params['source'],
- $news->getLatestStoryId($this->_params['source']),
+ $driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
+ $this->_story = $driver->getStory($this->_params['source'],
+ $driver->getLatestStoryId($this->_params['source']),
!empty($this->_params['countReads']));
}
'type' => 'enum',
'values' => array());
- $news = Jonah_News::factory();
- $channels = $news->getChannels();
+ $channels = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannels();
foreach ($channels as $channel) {
$params['source']['values'][$channel['channel_id']] = $channel['channel_name'];
}
function _title()
{
- $news = Jonah_News::factory();
- $channel = $news->getChannel($this->_params['source']);
- if (is_a($channel, 'PEAR_Error')) {
- return @htmlspecialchars($channel->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ try {
+ $channel = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannel($this->_params['source']);
+ } catch (Jonah_Exception $e) {
+ return @htmlspecialchars($e->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset());
}
if (!empty($channel['channel_link'])) {
return _("No feed specified.");
}
- $news = Jonah_News::factory();
- $params = $this->_params();
-
$view = isset($this->_params['view']) ? $this->_params['view'] : 'standard';
- if (!isset($this->_params['max'])) {
- $this->_params['max'] = $params['max']['default'];
- }
- if (!isset($this->_params['from'])) {
- $this->_params['from'] = $params['from']['default'];
- }
- return $news->renderChannel($this->_params['source'], $view, $this->_params['max'], $this->_params['from']);
+ return $GLOBALS['injector']->getInstance('Jonah_Driver')->renderChannel(
+ $this->_params['source'],
+ $view,
+ $this->_params['max'],
+ $this->_params['from']);
}
}
'type' => 'enum',
'values' => array());
- $news = Jonah_News::factory();
- $channels = $news->getChannels();
+ $channels = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannels();
foreach ($channels as $channel) {
if ($channel['channel_type'] == Jonah::INTERNAL_CHANNEL) {
$params['source']['values'][$channel['channel_id']] = $channel['channel_name'];
function _title()
{
- $news = Jonah_News::factory();
- $channel = $news->getChannel($this->_params['source']);
- if (is_a($channel, 'PEAR_Error')) {
- return @htmlspecialchars($channel->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ try {
+ $channel = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannel($this->_params['source']);
+ } catch (Exception $e) {
+ return @htmlspecialchars($e->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset());
}
if (!empty($channel['channel_link'])) {
return _("No feed specified.");
}
- $news = Jonah_News::factory();
$params = $this->_params();
$view = isset($this->_params['view']) ? $this->_params['view'] : 'standard';
}
- return $news->renderChannel($this->_params['source'], $view, $this->_params['max'], 0, Jonah::ORDER_READ);
+ return $GLOBALS['injector']->getInstance('Jonah_Driver')->renderChannel($this->_params['source'], $view, $this->_params['max'], 0, Jonah::ORDER_READ);
}
}
*/
function _params()
{
- $news = Jonah_News::factory();
- $channels = $news->getChannels(Jonah::INTERNAL_CHANNEL);
+ $channels = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannels();
$channel_choices = array();
foreach ($channels as $channel) {
$channel_choices[$channel['channel_id']] = $channel['channel_name'];
return _("Story");
}
- $story = $this->_fetch();
- return is_a($story, 'PEAR_Error')
- ? @htmlspecialchars($story->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset())
- : '<span class="storyDate">'
- . @htmlspecialchars($story['story_updated_date'], ENT_COMPAT, $GLOBALS['registry']->getCharset())
+ try {
+ $story = $this->_fetch();
+ } catch (Jonah_Exception $e) {
+ return htmlspecialchars($e->getMessage(), ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ }
+ return '<span class="storyDate">'
+ . htmlspecialchars($story['updated_date'], ENT_COMPAT,$GLOBALS['registry']->getCharset())
. '</span> '
- . @htmlspecialchars($story['story_title'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
+ . htmlspecialchars($story['title'], ENT_COMPAT, $GLOBALS['registry']->getCharset());
}
/**
return _("No story is selected.");
}
- $story = $this->_fetch();
- if (is_a($story, 'PEAR_Error')) {
- return sprintf(_("Error fetching story: %s"), $story->getMessage());
+ try {
+ $story = $this->_fetch();
+ } catch (Jonah_Exception $e) {
+ return sprintf(_("Error fetching story: %s"), $e->getMessage());
}
- if (empty($story['story_body_type']) || $story['story_body_type'] == 'text') {
- $story['story_body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
+ if (empty($story['body_type']) || $story['body_type'] == 'text') {
+ $story['body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
}
$tag_html = array();
- foreach ($story['story_tags'] as $id => $tag) {
- $link = Horde_Util::addParameter('results.php', array('tag_id' => $id, 'channel_id' => $this->_params['source']));
- $tag_html[] = Horde::link($link) . $tag . '</a>';
+ foreach ($story['tags'] as $id => $tag) {
+ $tag_html[] = Horde::url('results.php')->add(array('tag_id' => $id, 'channel_id' => $this->_prams['source']))->link() . $tag . '</a>';
}
return '<p class="storyTags">' . _("Tags: ")
- . implode(', ', $story['story_tags'])
+ . implode(', ', $story['tags'])
. '</p><p class="storySubtitle">'
- . htmlspecialchars($story['story_desc'])
- . '</p><div class="storyBody">' . $story['story_body']
+ . htmlspecialchars($story['desc'])
+ . '</p><div class="storyBody">' . $story['body']
. '</div>';
}
function _fetch()
{
if (is_null($this->_story)) {
- $news = Jonah_News::factory();
- $this->_story = $news->getStory($this->_params['source'],
- $this->_params['story'],
- $this->_params['countReads']);
+ $this->_story = $GLOBALS['injector']->getInstance('Jonah_Driver')->getStory(
+ $this->_params['source'],
+ $this->_params['story'],
+ !empty($this->_params['countReads']));
}
return $this->_story;
* stories from the given channel.
* @throws InvalidArgumentException
*/
- public function getStories($criteria)
+ public function getStories($criteria, $order = Jonah::ORDER_PUBLISHED)
{
// Convert a channel slug into a channel ID if necessary
if (isset($criteria['channel']) && !isset($criteria['channel_id'])) {
$criteria['tagIDs'] = array_merge($criteria['tagIDs'], $this->getTagIds($criteria['alltags']));
}
- return $this->_getStories($criteria);
- }
-
- /**
- * Returns the most recent or all stories from a channel.
- * This method is deprecated.
- *
- * @param integer $channel_id The news channel to get stories from.
- * @param integer $max The maximum number of stories to get. If
- * null, all stories will be returned.
- * @param integer $from The number of the story to start with.
- * @param boolean $refresh Force a refresh of stories in case this is
- * an external channel.
- * @param integer $date The timestamp of the date to start with.
- * @param boolean $unreleased Return stories that have not yet been
- * published?
- * Defaults to false - only published stories.
- * @param integer $order How to order the results for internal
- * channels. Possible values are the
- * Jonah::ORDER_* constants.
- *
- * @return array The specified number (or less, if there are fewer) of
- * stories from the given channel.
- */
- public function legacyGetStories($channel, $max = 10, $from = 0, $refresh = false,
- $date = null, $unreleased = false,
- $order = Jonah::ORDER_PUBLISHED)
- {
- global $conf, $registry;
-
- $channel['channel_link'] = Horde::url('delivery/html.php', true, -1)->add('channel_id', $channel['channel_id']);
- $stories = $this->_legacyGetStories($channel['channel_id'], $max, $from, $date, $unreleased, $order);
- $date_format = $GLOBALS['prefs']->getValue('date_format');
- $comments = $conf['comments']['allow'] && $registry->hasMethod('forums/numMessages');
- foreach ($stories as $key => $story) {
- $stories[$key]['story_link'] = $this->getStoryLink($channel, $story);
- $stories[$key]['story_updated'] = $story['story_updated'];
- $stories[$key]['story_updated_date'] = strftime($date_format, $story['story_updated']);
- if ($comments) {
- try {
- $stories[$key]['num_comments'] = $registry->call('forums/numMessages', array($story['story_id'], $registry->getApp()));
- } catch (Horde_Exception $e) {
- Horde::logMessage($e->getMessage(), 'ERR');
- $stories[$key]['num_comments'] = null;
- }
- }
- $stories[$key] = array_merge($channel, $stories[$key]);
- }
-
- return $stories;
+ return $this->_getStories($criteria, $order);
}
/**
* Save the provided story to storage.
*
* @param array $info The story information array. Passed by reference so
- * we can add/change the story_id when saved.
+ * we can add/change the id when saved.
*/
public function saveStory(&$info)
{
- /* Used for checking whether to send out delivery or not. */
- if (empty($info['story_published'])) {
- /* Story is not being released. */
- $deliver = false;
- } elseif (empty($info['story_id'])) {
- /* Story is new. */
- $deliver = true;
- } else {
- /* Story is old, has it been released already? */
- $oldstory = $this->getStory(null, $info['story_id']);
- if ((empty($oldstory['story_published']) ||
- $oldstory['story_published'] > $oldstory['story_updated']) &&
- $info['story_published'] <= time()) {
- $deliver = true;
- } else {
- $deliver = false;
- }
- }
$this->_saveStory($info);
}
$story = $this->_getStory($story_id, $read);
/* Format story link. */
- $story['story_link'] = $this->getStoryLink($channel, $story);
+ $story['link'] = $this->getStoryLink($channel, $story);
/* Format dates. */
$date_format = $GLOBALS['prefs']->getValue('date_format');
- $story['story_updated_date'] = strftime($date_format, $story['story_updated']);
- if (!empty($story['story_published'])) {
- $story['story_published_date'] = strftime($date_format, $story['story_published']);
+ $story['updated_date'] = strftime($date_format, $story['updated']);
+ if (!empty($story['published'])) {
+ $story['published_date'] = strftime($date_format, $story['published']);
}
return $story;
*/
public function getStoryLink($channel, $story)
{
- if ((empty($story['story_url']) || !empty($story['story_body'])) &&
+ if ((empty($story['url']) || !empty($story['body'])) &&
!empty($channel['channel_story_url'])) {
$url = $channel['channel_story_url'];
} else {
- $url = Horde::url('stories/view.php', true, -1)->add(array('channel_id' => '%c', 'story_id' => '%s'))->setRaw(false);
+ $url = Horde::url('stories/view.php', true, -1)->add(array('channel_id' => '%c', 'id' => '%s'))->setRaw(false);
}
return new Horde_Url(str_replace(array('%25c', '%25s', '%c', '%s'),
- array('%c', '%s', $channel['channel_id'], $story['story_id']),
+ array('%c', '%s', $channel['channel_id'], $story['id']),
$url));
}
*/
public function getChecksum($story)
{
- return md5($story['story_title'] . $story['story_desc']);
+ return md5($story['title'] . $story['description']);
}
/**
*
* @TODO: This doesn't belong in a storage driver class. Move it to a
* view or possible a static method in Jonah::?
- *
+ *
* @return string The rendered story listing.
*/
public function renderChannel($channel_id, $tpl, $max = 10, $from = 0, $order = Jonah::ORDER_PUBLISHED)
{
$channel = $this->getChannel($channel_id);
- if (is_a($channel, 'PEAR_Error')) {
- return sprintf(_("Error fetching feed: %s"), $channel->getMessage());
- }
include JONAH_BASE . '/config/templates.php';
- $escape = !isset($templates[$tpl]['escape']) ||
- !empty($templates[$tpl]['escape']);
+ $escape = !isset($templates[$tpl]['escape']) || !empty($templates[$tpl]['escape']);
$template = new Horde_Template();
if ($escape) {
}
$template->set('channel', $channel, true);
- /* Get one story more than requested to see if there are more
- * stories. */
+ /* Get one story more than requested to see if there are more stories. */
if ($max !== null) {
- $stories = $this->getStories($channel_id, $max + 1, $from, false, time(), false, $order);
- if (is_a($stories, 'PEAR_Error')) {
- return $stories->getMessage();
- }
+ $stories = $this->getStories(
+ array('channel_id' => $channel_id,
+ 'published' => true),
+ $order);
} else {
- $stories = $this->getStories($channel_id, null, 0, false, time(), false, $order);
- if (is_a($stories, 'PEAR_Error')) {
- return $stories->getMessage();
- }
+ $stories = $this->getStories(array('channel_id' => $channel_id,
+ 'published' => true),
+ $order);
$max = count($stories);
}
*/
protected function _escapeStories(&$value, $key)
{
- $value['story_title'] = htmlspecialchars($value['story_title']);
- $value['story_desc'] = htmlspecialchars($value['story_desc']);
- if (isset($value['story_link'])) {
- $value['story_link'] = htmlspecialchars($value['story_link']);
+ $value['title'] = htmlspecialchars($value['title']);
+ $value['description'] = htmlspecialchars($value['description']);
+ if (isset($value['link'])) {
+ $value['link'] = htmlspecialchars($value['link']);
}
- if (empty($value['story_body_type']) || $value['story_body_type'] != 'richtext') {
- $value['story_body'] = htmlspecialchars($value['story_body']);
+ if (empty($value['body_type']) || $value['body_type'] != 'richtext') {
+ $value['body'] = htmlspecialchars($value['body']);
}
}
*/
protected function _escapeStoryDescriptions(&$value, $key)
{
- $value['story_desc'] = nl2br($value['story_desc']);
+ $value['description'] = nl2br($value['description']);
}
/**
require_once 'Horde/MIME/Part.php';
/* Add the story to the message based on the story's body type. */
- switch ($story['story_body_type']) {
+ switch ($story['body_type']) {
case 'richtext':
/* Get a plain text version of a richtext story. */
- $body_html = $story['story_body'];
+ $body_html = $story['body'];
$body_text = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($body_html, 'html2text');
/* Add description. */
- $body_html = '<p>' . $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_desc'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO, 'callback' => null)) . "</p>\n" . $body_html;
- $body_text = Horde_String::wrap(' ' . $story['story_desc'], 70) . "\n\n" . $body_text;
+ $body_html = '<p>' . $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['desc'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO, 'callback' => null)) . "</p>\n" . $body_html;
+ $body_text = Horde_String::wrap(' ' . $story['description'], 70) . "\n\n" . $body_text;
/* Add the text version of the story to the base message. */
$message_text = new MIME_Part('text/plain');
case 'text':
/* This is just a plain text story. */
$message_text = new MIME_Part('text/plain');
- $message_text->setContents($message_text->replaceEOL($story['story_desc'] . "\n\n" . $story['story_body']));
+ $message_text->setContents($message_text->replaceEOL($story['description'] . "\n\n" . $story['body']));
$message_text->setCharset($GLOBALS['registry']->getCharset());
return $message_text;
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Jan Schneider <jan@horde.org>
* @author Ben Klang <ben@alkaloid.net>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
* @package Jonah
*/
class Jonah_Driver_Sql extends Jonah_Driver
*/
protected $_connected = false;
+
+ public function __construct($params = array())
+ {
+ parent::__construct($params);
+ $this->_connect();
+ }
+
/**
* Saves a channel to the backend.
*
* 'channel_image' A channel image.
* </pre>
*
- * @return int|PEAR_Error The channel ID on success, PEAR_Error on
- * failure.
+ * @return integer The channel ID.
+ * @throws Jonah_Exception
*/
public function saveChannel(&$info)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
if (empty($info['channel_id'])) {
$info['channel_id'] = $this->_db->nextId('jonah_channels');
- if (is_a($info['channel_id'], 'PEAR_Error')) {
+ if ($info['channel_id'] instanceof PEAR_Error) {
Horde::logMessage($info['channel_id'], 'ERR');
- return $info['channel_id'];
+ throw new Jonah_Exception($info['channel_id']);
}
$sql = 'INSERT INTO jonah_channels' .
' (channel_id, channel_name, channel_type, channel_desc, channel_interval, channel_url, channel_link, channel_page_link, channel_story_url, channel_img)' .
isset($info['channel_img']) ? $info['channel_img'] : null);
Horde::logMessage('SQL Query by Jonah_Driver_sql::saveChannel(): ' . $sql, 'DEBUG');
$result = $this->_db->query($sql, $values);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
- return $result;
+ throw new Jonah_Exception($result);
}
return $info['channel_id'];
/**
* Get a list of stored channels.
*
- * @return mixed An array of channels or PEAR_Error on error.
+ * @return mixed An array of channels.
* @throws Jonah_Exception
*/
public function getChannels()
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- throw new Jonah_Exception($result);
- }
-
- // @TODO: Remove the channel_type clause when we get rid of external channels
- $wsql = 'WHERE channel_type = ' . Jonah::INTERNAL_CHANNEL;
- $sql = sprintf('SELECT channel_id, channel_name, channel_type, channel_updated FROM jonah_channels WHERE channel_type = ' . Jonah::INTERNAL_CHANNEL . ' ORDER BY channel_name', $wsql);
+ // @TODO: Remove channel_type filter when tables are updated.
+ $sql = 'SELECT channel_id, channel_name, channel_type, channel_updated FROM jonah_channels WHERE channel_type = ' . Jonah::INTERNAL_CHANNEL . ' ORDER BY channel_name';
Horde::logMessage('SQL Query by Jonah_Driver_sql::getChannels(): ' . $sql, 'DEBUG');
$result = $this->_db->getAll($sql, DB_FETCHMODE_ASSOC);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
throw new Jonah_Exception($result);
}
}
/**
+ * Retrieve a single channel definition from storage.
+ *
+ * @return array The channel definition array.
+ * @throws Jonah_Exception
+ * @throws Horde_Exception_NotFound
*/
protected function _getChannel($channel_id)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = 'SELECT * FROM jonah_channels WHERE channel_id = ' . (int)$channel_id;
Horde::logMessage('SQL Query by Jonah_Driver_sql::_getChannel(): ' . $sql, 'DEBUG');
$result = $this->_db->getRow($sql, DB_FETCHMODE_ASSOC);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
- return $result;
+ throw new Jonah_Exception($result);
} elseif (empty($result)) {
- return PEAR::raiseError(sprintf(_("Channel id \"%s\" not found."), $channel_id));
- }
-
- $result['channel_name'] = Horde_String::convertCharset($result['channel_name'], $this->_params['charset']);
- if ($result['channel_type'] == Jonah::COMPOSITE_CHANNEL) {
- $channels = explode(':', $result['channel_url']);
- if (count($channels)) {
- $sql = 'SELECT MAX(channel_updated) FROM jonah_channels WHERE channel_id IN (' . implode(',', $channels) . ')';
- Horde::logMessage('SQL Query by Jonah_Driver_sql::_getChannel(): ' . $sql, 'DEBUG');
- $updated = $this->_db->getOne($sql);
- if (is_a($updated, 'PEAR_Error')) {
- Horde::logMessage($result, 'ERR');
- } else {
- $result['channel_updated'] = $updated;
- $this->_timestampChannel($channel_id, $updated);
- }
- }
+ throw new Horde_Exception_NotFound(sprintf(_("Channel id \"%s\" not found."), $channel_id));
}
return $result;
}
/**
+ * Update the channel's timestamp
+ *
+ * @param integer $channel_id The channel id.
+ * @param integer $timestamp The new timestamp.
+ *
+ * @return boolean
+ * @throws Jonah_Exception
*/
protected function _timestampChannel($channel_id, $timestamp)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = sprintf('UPDATE jonah_channels SET channel_updated = %s WHERE channel_id = %s',
(int)$timestamp,
(int)$channel_id);
Horde::logMessage('SQL Query by Jonah_Driver_sql::_timestampChannel(): ' . $sql, 'DEBUG');
$result = $this->_db->query($sql);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
+ throw new Jonah_Exception($result);
}
+
return $result;
}
/**
+ * Increment the story's read count.
+ *
+ * @param integer $story_id The story_id to increment.
+ * @throws Jonah_Exception
*/
protected function _readStory($story_id)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = 'UPDATE jonah_stories SET story_read = story_read + 1 WHERE story_id = ' . (int)$story_id;
Horde::logMessage('SQL Query by Jonah_Driver_sql::_readStory(): ' . $sql, 'DEBUG');
$result = $this->_db->query($sql);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
+ throw new Jonah_Exception($result);
}
+
return $result;
}
/**
+ * Remove a channel from storage.
+ *
+ * @param integer $channel_id The channel to remove.
+ *
+ * @return boolean.
+ * @throws Jonah_Exception
+ *
*/
protected function _deleteChannel($channel_id)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = 'DELETE FROM jonah_channels WHERE channel_id = ?';
$values = array($channel_id);
Horde::logMessage('SQL Query by Jonah_Driver_sql::deleteChannel(): ' . $sql, 'DEBUG');
$result = $this->_db->query($sql, $values);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
+ throw new Jonah_Exception($result);
}
return $result;
}
/**
- * @param array &$info
+ * Save a story to storage.
+ *
+ * @param array &$info The story info array.
+ * @throws Jonah_Exception
*/
protected function _saveStory(&$info)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
- if (empty($info['story_id'])) {
- $info['story_id'] = $this->_db->nextId('jonah_stories');
- if (is_a($info['story_id'], 'PEAR_Error')) {
- Horde::logMessage($info['story_id'], 'ERR');
- return $info['story_id'];
+ if (empty($info['id'])) {
+ $info['id'] = $this->_db->nextId('jonah_stories');
+ if ($info['id'] instanceof PEAR_Error) {
+ Horde::logMessage($info['id'], 'ERR');
+ throw new Jonah_Exception($info['id']);
}
$channel = $this->getChannel($info['channel_id']);
$permalink = $this->getStoryLink($channel, $info);
$values = array($permalink);
} else {
$sql = 'UPDATE jonah_stories SET story_id = ?, channel_id = ?, story_title = ?, story_desc = ?, story_body_type = ?, story_body = ?, story_url = ?, story_published = ?, story_updated = ?, story_read = ? WHERE story_id = ?';
- $values = array((int)$info['story_id']);
+ $values = array((int)$info['id']);
}
- if (empty($info['story_read'])) {
- $info['story_read'] = 0;
+ if (empty($info['read'])) {
+ $info['read'] = 0;
}
/* Deal with any tags */
- if (!empty($info['story_tags'])) {
- $tags = explode(',', $info['story_tags']);
+ if (!empty($info['tags'])) {
+ $tags = explode(',', $info['tags']);
} else {
$tags = array();
}
- $this->writeTags($info['story_id'], $info['channel_id'], $tags);
+ $this->writeTags($info['id'], $info['channel_id'], $tags);
array_unshift($values,
- (int)$info['story_id'],
+ (int)$info['id'],
(int)$info['channel_id'],
- Horde_String::convertCharset($info['story_title'], $GLOBALS['registry']->getCharset(), $this->_params['charset']),
- Horde_String::convertCharset($info['story_desc'], $GLOBALS['registry']->getCharset(), $this->_params['charset']),
- $info['story_body_type'],
- isset($info['story_body']) ? Horde_String::convertCharset($info['story_body'], $GLOBALS['registry']->getCharset(), $this->_params['charset']) : null,
- isset($info['story_url']) ? $info['story_url'] : null,
- isset($info['story_published']) ? (int)$info['story_published'] : null,
+ Horde_String::convertCharset($info['title'], $GLOBALS['registry']->getCharset(), $this->_params['charset']),
+ Horde_String::convertCharset($info['description'], $GLOBALS['registry']->getCharset(), $this->_params['charset']),
+ $info['body_type'],
+ isset($info['body']) ? Horde_String::convertCharset($info['body'], $GLOBALS['registry']->getCharset(), $this->_params['charset']) : null,
+ isset($info['url']) ? $info['url'] : null,
+ isset($info['published']) ? (int)$info['published'] : null,
time(),
- (int)$info['story_read']);
+ (int)$info['read']);
Horde::logMessage('SQL Query by Jonah_Driver_sql::_saveStory(): ' . $sql, 'DEBUG');
$result = $this->_db->query($sql, $values);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
- return $result;
+ throw new Jonah_Exception($result);
}
+ $this->_timestampChannel($info['id'], time());
- $this->_timestampChannel($info['channel_id'], time());
return true;
}
*/
protected function _convertFromBackend($story)
{
- $story['story_title'] = Horde_String::convertCharset($story['story_title'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
- $story['story_desc'] = Horde_String::convertCharset($story['story_desc'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
- if (isset($story['story_body'])) {
- $story['story_body'] = Horde_String::convertCharset($story['story_body'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
+ $story['title'] = Horde_String::convertCharset($story['title'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
+ $story['description'] = Horde_String::convertCharset($story['description'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
+ if (isset($story['body'])) {
+ $story['body'] = Horde_String::convertCharset($story['body'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
}
- if (isset($story['story_tags'])) {
- $story['story_tags'] = Horde_String::convertCharset($story['story_tags'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
+ if (isset($story['tags'])) {
+ $story['tags'] = Horde_String::convertCharset($story['tags'], $this->_params['charset'], $GLOBALS['registry']->getCharset());
}
+
return $story;
}
*/
public function getChannelId($channel)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = 'SELECT channel_id FROM jonah_channels WHERE channel_slug = ?';
$values = array($channel);
$result = $this->_db->getOne($sql, $values);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
+ if ($result instanceof PEAR_Error) {
+ throw new Jonah_Exception($result);
}
return $result;
}
/**
- * Returns the total number of stories in the specified
- * channel
+ * Returns the total number of stories in the specified channel.
*
- * @param int $channel_id The Channel ID
+ * @param integer $channel_id The Channel Id
*
- * @return mixed The count || PEAR_Error
+ * @return integer The count
*/
public function getStoryCount($channel_id)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = 'SELECT count(*) FROM jonah_stories WHERE channel_id = ?';
$result = $this->_db->getOne($sql, $channel_id);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
+ if ($result instanceof PEAR_Error) {
+ throw new Jonah_Exception($result);
}
return (int)$result;
* arbitrary criteria.
* NOTE: $criteria['channel_id'] MUST be set for this method to work.
*
- * @param string $channel
* @param array $criteria
*
* @return array
*
* @see Jonah_Driver#getStories
*/
- protected function _getStories($criteria)
+ protected function _getStories($criteria, $order = Jonah::ORDER_PUBLISHED)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
- $sql = 'SELECT DISTINCT(tags.story_id) AS id, ' .
- 'stories.story_author AS author, ' .
- 'stories.story_title AS title, ' .
- 'stories.story_desc AS description, ' .
- 'stories.story_body_type AS body_type, ' .
- 'stories.story_body AS body, ' .
- 'stories.story_url AS url, ' .
- 'stories.story_permalink AS permalink, ' .
- 'stories.story_published AS published, ' .
- 'stories.story_updated AS updated, ' .
- 'stories.story_read AS readcount ' .
- 'FROM jonah_stories_tags AS tags ' .
- 'LEFT JOIN jonah_stories AS stories ON ' .
- 'tags.story_id = stories.story_id ' .
- 'WHERE stories.channel_id=?';
+ // Assuming this was to save the extra tag queries, but this will not
+ // work, it will only return stories that have been tagged.
+// $sql = 'SELECT DISTINCT(tags.story_id) AS id, ' .
+// 'stories.channel_id, ' .
+// 'stories.story_author AS author, ' .
+// 'stories.story_title AS title, ' .
+// 'stories.story_desc AS description, ' .
+// 'stories.story_body_type AS body_type, ' .
+// 'stories.story_body AS body, ' .
+// 'stories.story_url AS url, ' .
+// 'stories.story_permalink AS permalink, ' .
+// 'stories.story_published AS published, ' .
+// 'stories.story_updated AS updated, ' .
+// 'stories.story_read AS readcount ' .
+// 'FROM jonah_stories_tags AS tags ' .
+// 'LEFT JOIN jonah_stories AS stories ON ' .
+// 'tags.story_id = stories.story_id ' .
+// 'WHERE stories.channel_id=?';
+
+ $sql = 'SELECT stories.story_id AS id, ' .
+ 'stories.channel_id, ' .
+ 'stories.story_author AS author, ' .
+ 'stories.story_title AS title, ' .
+ 'stories.story_desc AS description, ' .
+ 'stories.story_body_type AS body_type, ' .
+ 'stories.story_body AS body, ' .
+ 'stories.story_url AS url, ' .
+ 'stories.story_permalink AS permalink, ' .
+ 'stories.story_published AS published, ' .
+ 'stories.story_updated AS updated, ' .
+ 'stories.story_read AS readcount ' .
+ 'FROM jonah_stories AS stories ' .
+ 'WHERE stories.channel_id=?';
+
$values = array($criteria['channel_id']);
// Apply date filtering
}
}
- Horde::logMessage('SQL Query by Jonah_Driver_sql::_getStories(): ' . $sql, 'DEBUG');
- $results = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
- if (is_a($results, 'PEAR_Error')) {
- return $results;
- }
-
- return $results;
- }
-
- protected function _getIdBySlug($slug)
- {
- return $slug;
- }
-
- /**
- * Returns the most recent or all stories from a channel.
- * This method is deprecated.
- *
- * @param integer $channel_id The news channel to get stories from.
- * @param integer $max The maximum number of stories to get.
- * @param integer $from The number of the story to start with.
- * @param integer $date The timestamp of the date to start with.
- * @param boolean $unreleased Whether to return not yet released stories.
- * @param integer $order How to order the results for internal
- * channels. Possible values are the
- * JONAH_ORDER_* constants.
- *
- * @return array The specified number (or less, if there are fewer) of
- * stories from the given channel.
- */
- protected function _legacyGetStories($channel_id, $max, $from = 0, $date = null,
- $unreleased = false, $order = Jonah::ORDER_PUBLISHED)
- {
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
- $sql = 'SELECT * FROM jonah_stories WHERE channel_id = ?';
- $values = array((int)$channel_id);
-
- if ($unreleased) {
- if ($date !== null) {
- $sql .= ' AND story_published <= ?';
- $values[] = $date;
- }
- } else {
- if ($date === null) {
- $date = time();
- } else {
- $date = max($date, time());
- }
- $sql .= ' AND story_published <= ?';
- $values[] = $date;
- }
-
switch ($order) {
case Jonah::ORDER_PUBLISHED:
$sql .= ' ORDER BY story_published DESC';
break;
}
- if (!is_null($max)) {
- $sql = $this->_db->modifyLimitQuery($sql, (int)$from, (int)$max, $values);
- }
+ Horde::logMessage('SQL Query by Jonah_Driver_sql::_getStories(): ' . $sql, 'DEBUG');
+ $results = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
- Horde::logMessage('SQL Query by Jonah_Driver_sql::_legacyGetStories(): ' . $sql, 'DEBUG');
- $result = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
+ if ($results instanceof PEAR_Error) {
+ throw new Jonah_Exception($results);
}
- for ($i = 0; $i < count($result); $i++) {
- $result[$i] = $this->_convertFromBackend($result[$i]);
- if (empty($result[$i]['story_permalink'])) {
- $this->_addPermalink($result[$i]);
- }
- $tags = $this->readTags($result[$i]['story_id']);
- if (is_a($tags, 'PEAR_Error')) {
- return $tags;
- }
- $result[$i]['story_tags'] = $tags;
- }
- return $result;
+
+ return $results;
}
/**
+ * Obtain a channel id from a slug
+ *
+ * @param string $slug The slug to search for.
+ *
+ * @return integer The channel id.
*/
- protected function _getStory($story_id, $read = false)
+ protected function _getIdBySlug($slug)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
- $sql = 'SELECT * FROM jonah_stories WHERE story_id = ?';
- $values = array((int)$story_id);
-
- Horde::logMessage('SQL Query by Jonah_Driver_sql::_getStory(): ' . $sql, 'DEBUG');
- $result = $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC);
- if (is_a($result, 'PEAR_Error')) {
- Horde::logMessage($result, 'ERR');
- return $result;
- } elseif (empty($result)) {
- return PEAR::raiseError(sprintf(_("Story id \"%s\" not found."), $story_id));
- }
- $result['story_tags'] = $this->readTags($story_id);
- $result = $this->_convertFromBackend($result);
- if (empty($result['story_permalink'])) {
- $this->_addPermalink($result);
- }
- if ($read) {
- $this->_readStory($story_id);
- }
-
- return $result;
+ // @TODO
+ throw new Jonah_Exception('Not implemented yet.');
}
/**
+ * Retrieve a story from storage.
+ *
+ * @param integer $story_id They story id.
+ * @param boolean $read Increment the read counter?
+ *
+ * @return The story array.
+ * @throws Horde_Exception_NotFound
+ * @throws Jonah_Exception
+ *
*/
- protected function _getStoryByUrl($channel_id, $story_url)
+ protected function _getStory($story_id, $read = false)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
+ $sql = 'SELECT stories.story_id as id, ' .
+ 'stories.channel_id, ' .
+ 'stories.story_author AS author, ' .
+ 'stories.story_title AS title, ' .
+ 'stories.story_desc AS description, ' .
+ 'stories.story_body_type AS body_type, ' .
+ 'stories.story_body AS body, ' .
+ 'stories.story_url AS url, ' .
+ 'stories.story_permalink AS permalink, ' .
+ 'stories.story_published AS published, ' .
+ 'stories.story_updated AS updated, ' .
+ 'stories.story_read AS readcount ' .
+ 'FROM jonah_stories AS stories WHERE stories.story_id=?';
- $sql = 'SELECT * FROM jonah_stories' .
- ' WHERE channel_id = ? AND story_url = ?';
- $values = array((int)$channel_id, $story_url);
+ $values = array((int)$story_id);
- Horde::logMessage('SQL Query by Jonah_Driver_sql::_getStoryByUrl(): ' . $sql, 'DEBUG');
+ Horde::logMessage('SQL Query by Jonah_Driver_sql::_getStory(): ' . $sql, 'DEBUG');
$result = $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
- return $result;
+ throw new Jonah_Exception($result);
} elseif (empty($result)) {
- return PEAR::raiseError(sprintf(_("Story URL \"%s\" not found."), $story_url));
+ throw new Horde_Exception_NotFound(sprintf(_("Story id \"%s\" not found."), $story_id));
}
+ $result['tags'] = $this->readTags($story_id);
$result = $this->_convertFromBackend($result);
- if (empty($result['story_permalink'])) {
- $this->_addPermalink($result);
+ if ($read) {
+ $this->_readStory($story_id);
}
return $result;
* Adds a missing permalink to a story.
*
* @param array $story A story hash.
+ * @throws Jonah_Exception
*/
protected function _addPermalink(&$story)
{
$channel = $this->getChannel($story['channel_id']);
- if (is_a($channel, 'PEAR_Error')) {
- return;
- }
$sql = 'UPDATE jonah_stories SET story_permalink = ? WHERE story_id = ?';
- $values = array($this->getStoryLink($channel, $story), $story['story_id']);
+ $values = array($this->getStoryLink($channel, $story), $story['id']);
Horde::logMessage('SQL Query by Jonah_Driver_sql::_addPermalink(): ' . $sql, 'DEBUG');
$result = $this->_db->query($sql, $values);
- if (!is_a($result, 'PEAR_Error')) {
- $story['story_permalink'] = $values[0];
+ if ($result instanceof PEAR_Error) {
+ throw new Jonah_Exception($result);
}
+ $story['permalink'] = $values[0];
}
/**
* @param int $channel_id The channel id.
*
* @return int The story id.
+ * @throws Jonah_Exception
+ * @throws Horde_Exception_NotFound
*/
public function getLatestStoryId($channel_id)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = 'SELECT story_id FROM jonah_stories' .
' WHERE channel_id = ? AND story_published <= ?' .
' ORDER BY story_updated DESC';
Horde::logMessage('SQL Query by Jonah_Driver_sql::getLatestStoryId(): ' . $sql, 'DEBUG');
$result = $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result, 'ERR');
- return $result;
+ throw new Jonah_Exception($result);
} elseif (empty($result)) {
- return PEAR::raiseError(sprintf(_("Channel \"%s\" not found."), $channel_id));
+ return Horde_Exception_NotFound(sprintf(_("Channel \"%s\" not found."), $channel_id));
}
return $result['story_id'];
*/
public function deleteStory($channel_id, $story_id)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
$sql = 'DELETE FROM jonah_stories' .
' WHERE channel_id = ? AND story_id = ?';
$values = array((int)$channel_id, (int)$story_id);
Horde::logMessage('SQL Query by Jonah_Driver_sql::deleteStory(): ' . $sql, 'DEBUG');
$result = $this->_db->query($sql, $values);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result->getMessage(), 'ERR');
- return $result;
+ throw new Jonah_Exception($result);
}
$sql = 'DELETE FROM jonah_stories_tags ' .
'WHERE channel_id = ? AND story_id = ?';
$result = $this->_db->query($sql, $values);
- if (is_a($result, 'PEAR_Error')) {
+ if ($result instanceof PEAR_Error) {
Horde::logMessage($result->getMessage(), 'ERR');
- return $result;
+ throw new Jonah_Exception($result);
}
return true;
* @param int $channel_id The channel id for the story we are tagging
* @param array $tags An array of tags.
*
- * @return mixed True | PEAR_Error
+ * @TODO: Move this to a tagger class that uses Content_Tagger
+ * @return boolean
+ * @throws Jonah_Exception
*/
public function writeTags($resource_id, $channel_id, $tags)
{
global $conf;
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
// First, make sure all tag names exist in the DB.
$tagkeys = array();
$insert = $this->_db->prepare('INSERT INTO jonah_tags (tag_id, tag_name) VALUES(?, ?)');
foreach ($tags as $tag) {
$tag = Horde_String::lower(trim($tag));
$results = $this->_db->execute($query, $this->_db->escapeSimple($tag));
- if (is_a($results, 'PEAR_Error')) {
- return $results;
+ if ($results instanceof PEAR_Error) {
+ throw new Jonah_Exception($results);
} elseif ($results->numRows() == 0) {
$id = $this->_db->nextId('jonah_tags');
$result = $this->_db->execute($insert, array($id, $tag));
$sql = 'DELETE FROM jonah_stories_tags WHERE story_id = ' . (int)$resource_id;
$query = $this->_db->prepare('INSERT INTO jonah_stories_tags (story_id, channel_id, tag_id) VALUES(?, ?, ?)');
-
- Horde::logMessage('SQL query by Jonah_Driver_sql::writeTags: ' . $sql,
- 'DEBUG');
-
+ Horde::logMessage('SQL query by Jonah_Driver_sql::writeTags: ' . $sql, 'DEBUG');
$this->_db->query($sql);
foreach ($tagkeys as $key) {
$this->_db->execute($query, array($resource_id, $channel_id, $key));
/**
* Retrieve the tags for a specified resource.
*
- * @param int $resource_id The resource to get tags for.
+ * @TODO: Move this to a tagger class that uses content_tagger
*
- * @return mixed An array of tags | PEAR_Error
+ * @param integer $resource_id The resource to get tags for.
+ *
+ * @return array An array of tags
*/
public function readTags($resource_id)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
$sql = 'SELECT jonah_tags.tag_id, tag_name FROM jonah_tags INNER JOIN jonah_stories_tags ON jonah_stories_tags.tag_id = jonah_tags.tag_id WHERE jonah_stories_tags.story_id = ?';
-
- Horde::logMessage('SQL query by Jonah_Driver_sql::readTags ' . $sql,
- 'DEBUG');
-
+ Horde::logMessage('SQL query by Jonah_Driver_sql::readTags ' . $sql, 'DEBUG');
$tags = $this->_db->getAssoc($sql, false, array($resource_id), false);
+
return $tags;
}
*
* @param array $channel_id An optional array of channel_ids.
*
- * @return mixed An array containing tag_name, and total | PEAR_Error
+ * @return array An array containing tag_name, and total
*/
public function listTagInfo($tags = array(), $channel_id = null)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
-
if (!is_array($channel_id) && is_numeric($channel_id)) {
$channel_id = array($channel_id);
}
$channels = array();
foreach ($channel_id as $cid) {
$c = $this->_getChannel($cid);
- if ($c['channel_type'] == Jonah::COMPOSITE_CHANNEL) {
- $channels = array_merge($channels, explode(':', $c['channel_url']));
- }
}
$channel_id = array_merge($channel_id, $channels);
$sql .= ' t.channel_id IN (' . implode(', ', $channel_id) . ')';
}
$sql .= ' GROUP BY tn.tag_id, tag_name ORDER BY total DESC;';
$results = $this->_db->getAssoc($sql,true, array(), DB_FETCHMODE_ASSOC, false);
+ if ($results instanceof PEAR_Error) {
+ throw new Jonah_Exception($results);
+ }
$cache->set($cache_key, serialize($results));
+
return $results;
}
* channels. Possible values are the
* JONAH_ORDER_* constants.
*
- * @return mixed Array of stories| PEAR_Error
+ * @return mixed Array of stories
*/
- public function searchTagsById($ids, $max = 10, $from = 0, $channel_id = array(),
- $order = Jonah::ORDER_PUBLISHED)
+ public function searchTagsById($ids, $max = 10, $from = 0, $channel_id = array(), $order = Jonah::ORDER_PUBLISHED)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
if (!is_array($ids) || !count($ids)) {
$stories[] = array();
} else {
$channels = array();
foreach ($channel_id as $cid) {
$c = $this->_getChannel($cid);
- if ($c['channel_type'] == Jonah::COMPOSITE_CHANNEL) {
- $temp = explode(':', $c['channel_url']);
- // Save a map of channels that are from composites.
- foreach ($temp as $t) {
- $cchannels[$t] = $cid;
- }
- $channels = array_merge($channels, $temp);
- }
}
$channels = array_merge($channel_id, $channels);
$timestamp = time();
}
Horde::logMessage('SQL query by Jonah_Driver_sql::searchTags: ' . $sql, 'DEBUG');
$results = $this->_db->limitQuery($sql, $from, $max);
- if (is_a($results, 'PEAR_Error')) {
- return $results;
+ if ($results instanceof PEAR_Error) {
+ throw new Jonah_Exception($results);
}
for ($i = 0; $i < $results->numRows(); $i++) {
}
/* Format story link. */
- $story['story_link'] = $this->getStoryLink($channel, $story);
+ $story['link'] = $this->getStoryLink($channel, $story);
$story = array_merge($story, $channel);
+
/* Format dates. */
$date_format = $GLOBALS['prefs']->getValue('date_format');
- $story['story_updated_date'] = strftime($date_format, $story['story_updated']);
- if (!empty($story['story_published'])) {
- $story['story_published_date'] = strftime($date_format, $story['story_published']);
+ $story['updated_date'] = strftime($date_format, $story['updated']);
+ if (!empty($story['published'])) {
+ $story['published_date'] = strftime($date_format, $story['published']);
}
$stories[] = $story;
$order = Jonah::ORDER_PUBLISHED)
{
$ids = $this->getTagIds($names);
- if (is_a($ids, 'PEAR_Error')) {
- return $ids;
+ if ($ids instanceof PEAR_Error) {
+ throw new Jonah_Exception($ids);
}
+
return $this->searchTagsById(array_values($ids), $max, $from, $channel_id, $order);
}
*/
public function getTagNames($ids)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
- $sql = 'SELECT t.tag_name FROM jonah_tags as t WHERE t.tag_id IN(';
- $needComma = false;
- foreach ($ids as $id) {
- $sql .= ($needComma ? ',' : '') . '\'' . $id . '\'';
- $needComma = true;
- }
- $sql .= ')';
+ $sql = 'SELECT t.tag_name FROM jonah_tags as t WHERE t.tag_id IN(' . str_repeat('?,', count($ids) - 1) . '?)';
$tags = $this->_db->getCol($sql);
+ if ($tags instanceof PEAR_Error) {
+ throw new Jonah_Exception($tags);
+ }
+
return $tags;
}
*/
public function getTagIds($names)
{
- if (is_a(($result = $this->_connect()), 'PEAR_Error')) {
- return $result;
- }
- $sql = 'SELECT t.tag_name, t.tag_id FROM jonah_tags as t WHERE t.tag_name IN(';
- $needComma = false;
- foreach ($names as $name) {
- $sql .= ($needComma ? ',' : '') . '\'' . $name . '\'';
- $needComma = true;
- }
- $sql .= ')';
+ $sql = 'SELECT t.tag_name, t.tag_id FROM jonah_tags as t WHERE t.tag_name IN(' . str_repeat('?,', count($names) - 1) . '?)';
$tags = $this->_db->getAssoc($sql);
+ if ($tags instanceof PEAR_Error) {
+ throw new Jonah_Exception($tags);
+ }
+
return $tags;
}
/**
* Attempts to open a persistent connection to the SQL server.
*
- * @return boolean True on success; PEAR_Error on failure.
+ * @TODO: This class needs to be refactored to use Horde_Db
+ *
+ * @return boolean True on success.
+ * @throws Jonah_Exception
*/
protected function _connect()
{
} catch (Horde_Exception $e) {
return PEAR::raiseError($e->getMessage());
}
-
$this->_connected = true;
return true;
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
+ * @deprecated Will be removed once the Aggregator app (Hippo) is started.
+ *
* @author Chuck Hagenbuch <chuck@horde.org>
* @package Jonah
*/
--- /dev/null
+<?php
+/**
+ * This class extends Horde_Form to provide the form to add/edit
+ * feeds.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @package Jonah
+ */
+class Jonah_Form_Feed extends Horde_Form
+{
+ /**
+ */
+ function __construct(&$vars)
+ {
+ $channel_id = $vars->get('channel_id');
+ $editing = (!empty($channel_id));
+
+ parent::Horde_Form($vars, ($editing ? _("Edit Feed") : _("New Feed")));
+
+ $this->addHidden('', 'channel_id', 'int', false);
+ $this->addHidden('', 'old_channel_type', 'text', false);
+
+ $select_type =& $this->addVariable(_("Type"), 'channel_type', 'enum', true, false, null, array(Jonah::getAvailableTypes()));
+ $select_type->setDefault(Jonah::INTERNAL_CHANNEL);
+ $select_type->setHelp('feed-type');
+ $select_type->setAction(Horde_Form_Action::factory('submit'));
+
+ $this->addVariable(_("Name"), 'channel_name', 'text', true);
+ $this->addVariable(_("Extra information for this feed type"), 'extra_info', 'header', false);
+ }
+
+ /**
+ */
+ function setExtraFields($channel_id = null)
+ {
+ $this->addVariable(_("Description"), 'channel_desc', 'text', false);
+ $this->addVariable(
+ _("Channel Slug"), 'channel_slug', 'text', true, false,
+ sprintf(_("Slugs allows direct access to this channel's content by visiting: %s. <br /> Slug names may contain only letters, numbers or the _ (underscore) character."),
+ Horde::url('slugname')),
+ array('/^[a-zA-Z1-9_]*$/'));
+
+ $this->addVariable(_("Include full story content in syndicated feeds?"), 'channel_full_feed', 'boolean', false);
+ $this->addVariable(_("Channel URL if not the default one. %c gets replaced by the feed ID."), 'channel_link', 'text', false);
+ $this->addVariable(_("Channel URL for further pages, if not the default one. %c gets replaced by the feed ID, %n by the story offset."), 'channel_page_link', 'text', false);
+ $this->addVariable(_("Story URL if not the default one. %c gets replaced by the feed ID, %s by the story ID."), 'channel_story_url', 'text', false);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Form for editing a new Story.
+ *
+ * @package Jonah
+ */
+/**
+ * Horde_Form_Action
+ */
+require_once 'Horde/Form/Action.php';
+
+/**
+ * This class extends Horde_Form to provide the form to add/edit
+ * stories.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @package Jonah
+ */
+class Jonah_Form_Story extends Horde_Form
+{
+ /**
+ */
+ function __construct(&$vars)
+ {
+ parent::Horde_Form($vars, $vars->get('id') ? _("Edit Story") : _("Add New Story"));
+
+ $this->setButtons(_("Save"), true);
+ $channel_id = $this->addHidden('', 'channel_id', 'int', false);
+ $channel = $vars->get('channel_id');
+ if ($channel) {
+ $channel_id->setDefault($channel_id);
+ }
+ $this->addHidden('', 'id', 'int', false);
+ $this->addHidden('', 'read', 'int', false);
+ $this->addVariable(_("Story Title (Headline)"), 'title', 'text', true);
+ $this->addVariable(_("Short Description"), 'description', 'longtext', true, false, null, array(2, 80));
+ $this->addVariable(_("Publish Now?"), 'publish_now', 'boolean', false);
+
+ $published = $vars->get('published');
+ if ($published) {
+ $date_params = array(min(date('Y', $published), date('Y')),
+ max(date('Y', $published), date('Y') + 10));
+ } else {
+ $date_params = array();
+ }
+
+ $d = &$this->addVariable(_("Or publish on this date:"), 'publish_date', 'monthdayyear', false, false, null, $date_params);
+ $d->setDefault($published);
+
+ $t = &$this->addVariable('', 'publish_time', 'hourminutesecond', false);
+ $t->setDefault($published);
+
+ $v = &$this->addVariable(_("Story body type"), 'body_type', 'enum', false, false, null, array(Jonah::getBodyTypes()));
+ $v->setAction(Horde_Form_Action::factory('submit'));
+ $v->setOption('trackchange', true);
+
+ /* If no body type specified, default to one. */
+ $body_type = $vars->get('body_type');
+ if (empty($body_type)) {
+ $body_type = Jonah::getDefaultBodyType();
+ $vars->set('body_type', $body_type);
+ }
+
+ /* Set up the fields according to what the type of body requested. */
+ if ($body_type == 'text') {
+ $this->addVariable(_("Full Story Text"), 'body', 'longtext', false, false, null, array(15, 80));
+ } elseif ($body_type == 'richtext') {
+ $this->addVariable(_("Full Story Text"), 'body', 'longtext', false, false, null, array(20, 80, array('rte')));
+ }
+
+ $this->addVariable(_("Tags"), 'tags', 'text', false, false, _("Enter keywords to tag this story, separated by commas"));
+ /* Only show URL insertion if it has been enabled in config. */
+ if (in_array('links', $GLOBALS['conf']['news']['story_types'])) {
+ $this->addVariable(_("Story URL"), 'url', 'text', false, false, _("If you enter a URL without a full story text, clicking on the story will send the reader straight to the URL, otherwise it will be shown at the end of the full story."));
+ }
+ }
+
+ /**
+ */
+ function getInfo(&$vars, &$info)
+ {
+ parent::getInfo($vars, $info);
+
+ /* Build release date. */
+ if (!empty($info['publish_now'])) {
+ $info['published'] = time();
+ } elseif (!empty($info['publish_date'])) {
+ $info['published'] = mktime(
+ (int)$info['publish_time']['hour'],
+ (int)$info['publish_time']['minute'],
+ 0,
+ date('n', $info['publish_date']),
+ date('j', $info['publish_date']),
+ date('Y', $info['publish_date']));
+ } else {
+ $info['published'] = null;
+ }
+
+ unset($info['publish_now']);
+ unset($info['publish_date']);
+ unset($info['publish_time']);
+ }
+
+}
+++ /dev/null
-<?php
-/**
- * @package Jonah
- */
-
-/**
- * Horde_Form
- */
-require_once 'Horde/Form.php';
-
-/**
- * Horde_Form_Action
- */
-require_once 'Horde/Form/Action.php';
-
-/**
- * This class extends Horde_Form to provide the form to add/edit
- * feeds.
- *
- * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file LICENSE for license information (BSD). If you
- * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
- *
- * @author Marko Djukic <marko@oblo.com>
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @package Jonah
- */
-class FeedForm extends Horde_Form
-{
- /**
- */
- function FeedForm(&$vars)
- {
- $channel_id = $vars->get('channel_id');
- $editing = (!empty($channel_id));
-
- parent::Horde_Form($vars, ($editing ? _("Edit Feed") : _("New Feed")));
-
- $this->addHidden('', 'channel_id', 'int', false);
- $this->addHidden('', 'old_channel_type', 'text', false);
-
- $select_type =& $this->addVariable(_("Type"), 'channel_type', 'enum', true, false, null, array(Jonah_News::getAvailableTypes()));
- $select_type->setDefault(Jonah_News::getDefaultType());
- $select_type->setHelp('feed-type');
- $select_type->setAction(Horde_Form_Action::factory('submit'));
-
- $this->addVariable(_("Name"), 'channel_name', 'text', true);
- $this->addVariable(_("Extra information for this feed type"), 'extra_info', 'header', false);
- }
-
- /**
- */
- function getInfo(&$vars, &$info)
- {
- parent::getInfo($vars, $info);
- if ($vars->get('channel_type') == Jonah::COMPOSITE_CHANNEL &&
- is_array($vars->get('subchannels'))) {
- $info['channel_url'] = implode(':', $vars->get('subchannels'));
- }
- }
-
- /**
- */
- function setExtraFields($type = null, $channel_id = null)
- {
- if (is_null($type)) {
- $type = Jonah_News::getDefaultType();
- }
-
- switch ($type) {
- case Jonah::INTERNAL_CHANNEL:
- $this->addVariable(_("Description"), 'channel_desc', 'text', false);
- $this->addVariable(
- _("Channel Slug"), 'channel_slug', 'text', true, false,
- sprintf(_("Slugs allows direct access to this channel's content by visiting: %s. <br /> Slug names may contain only letters, numbers or the _ (underscore) character."),
- Horde::url('slugname', true)),
- array('/^[a-zA-Z1-9_]*$/'));
-
- $this->addVariable(_("Include full story content in syndicated feeds?"), 'channel_full_feed', 'boolean', false);
- $this->addVariable(_("Channel URL if not the default one. %c gets replaced by the feed ID."), 'channel_link', 'text', false);
- $this->addVariable(_("Channel URL for further pages, if not the default one. %c gets replaced by the feed ID, %n by the story offset."), 'channel_page_link', 'text', false);
- $this->addVariable(_("Story URL if not the default one. %c gets replaced by the feed ID, %s by the story ID."), 'channel_story_url', 'text', false);
- break;
-
- case Jonah::EXTERNAL_CHANNEL:
- $interval = Jonah_News::getIntervalLabel();
- $v = &$this->addVariable(_("Caching"), 'channel_interval', 'enum', false, false, _("The interval before stories in this feed are rechecked for updates. If none, then stories will always be refetched from the source."), array($interval));
- $v->setDefault('86400');
- $this->addVariable(_("Source URL"), 'channel_url', 'text', true, false, _("The url to use to fetch the stories, for example 'http://www.example.com/stories.rss'"));
- $this->addVariable(_("Link"), 'channel_link', 'text', false);
- $this->addVariable(_("Image"), 'channel_img', 'text', false);
- break;
-
- case Jonah::AGGREGATED_CHANNEL:
- $this->addHidden('', 'channel_url', 'text', false);
- $interval = Jonah_News::getIntervalLabel();
- $this->addVariable(_("Description"), 'channel_desc', 'text', false);
- $v = &$this->addVariable(_("Caching"), 'channel_interval', 'enum', false, false, _("The interval before stories aggregated into this feeds are rechecked for updates. If none, then stories will always be refetched from the sources."), array($interval));
- $v->setDefault('86400');
- if (!empty($channel_id)) {
- $edit_url = Horde::url('channels/aggregate.php');
- $edit_url = Horde_Util::addParameter($edit_url, 'channel_id', $channel_id);
- $edit_url = Horde_Util::addParameter($edit_url, 'channel_id', $channel_id);
- $this->addVariable(_("Source URLs"), 'channel_urls', 'link', false, false, null, array(array('text' => _("Edit aggregated feeds"), 'url' => $edit_url)));
- }
- break;
-
- case Jonah::COMPOSITE_CHANNEL:
- global $news;
- $channels = $news->getChannels(Jonah::INTERNAL_CHANNEL);
- $enum = array();
- foreach ($channels as $channel) {
- $enum[$channel['channel_id']] = $channel['channel_name'];
- }
- $this->addVariable(_("Description"), 'channel_desc', 'text', false);
- $this->addVariable(_("Channel URL if not the default one. %c gets replaced by the feed ID, %n by the story offset."), 'channel_page_link', 'text', false);
- $this->addVariable(_("Story URL if not the default one. %c gets replaced by the feed ID, %s by the story ID."), 'channel_story_url', 'text', false);
- $v = &$this->addVariable(_("Composite feeds"), 'subchannels', 'multienum', false, false, '', array($enum));
- if (!empty($channel_id)) {
- $channel = $news->getChannel($channel_id);
- $v->setDefault(explode(':', $channel['channel_url']));
- }
- break;
- }
- }
-
-}
+++ /dev/null
-<?php
-/**
- * @package Jonah
- */
-
-/**
- * Horde_Form
- */
-require_once 'Horde/Form.php';
-
-/**
- * Horde_Form_Action
- */
-require_once 'Horde/Form/Action.php';
-
-/**
- * This class extends Horde_Form to provide the form to add/edit
- * stories.
- *
- * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file LICENSE for license information (BSD). If you
- * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
- *
- * @author Marko Djukic <marko@oblo.com>
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @package Jonah
- */
-class StoryForm extends Horde_Form
-{
- /**
- */
- function StoryForm(&$vars)
- {
- parent::Horde_Form($vars, $vars->get('story_id') ? _("Edit Story") : _("Add New Story"));
-
- $this->setButtons(_("Save"), true);
- $this->addHidden('', 'channel_id', 'int', false);
- $this->addHidden('', 'story_id', 'int', false);
- $this->addHidden('', 'story_read', 'int', false);
- $this->addVariable(_("Story Title (Headline)"), 'story_title', 'text', true);
- $this->addVariable(_("Short Description"), 'story_desc', 'longtext', true, false, null, array(2, 80));
- $this->addVariable(_("Publish Now?"), 'publish_now', 'boolean', false);
-
- $published = $vars->get('story_published');
- if ($published) {
- $date_params = array(min(date('Y', $published), date('Y')),
- max(date('Y', $published), date('Y') + 10));
- } else {
- $date_params = array();
- }
-
- $d = &$this->addVariable(_("Or publish on this date:"), 'publish_date', 'monthdayyear', false, false, null, $date_params);
- $d->setDefault($published);
-
- $t = &$this->addVariable('', 'publish_time', 'hourminutesecond', false);
- $t->setDefault($published);
-
- $v = &$this->addVariable(_("Story body type"), 'story_body_type', 'enum', false, false, null, array(Jonah::getBodyTypes()));
- $v->setAction(Horde_Form_Action::factory('submit'));
- $v->setOption('trackchange', true);
-
- /* If no body type specified, default to one. */
- $body_type = $vars->get('story_body_type');
- if (empty($body_type)) {
- $body_type = Jonah::getDefaultBodyType();
- $vars->set('story_body_type', $body_type);
- }
-
- /* Set up the fields according to what the type of body requested. */
- if ($body_type == 'text') {
- $this->addVariable(_("Full Story Text"), 'story_body', 'longtext', false, false, null, array(15, 80));
- } elseif ($body_type == 'richtext') {
- $this->addVariable(_("Full Story Text"), 'story_body', 'longtext', false, false, null, array(20, 80, array('rte')));
- }
-
- $this->addVariable(_("Tags"), 'story_tags', 'text', false, false, _("Enter keywords to tag this story, separated by commas"));
- /* Only show URL insertion if it has been enabled in config. */
- if (in_array('links', $GLOBALS['conf']['news']['story_types'])) {
- $this->addVariable(_("Story URL"), 'story_url', 'text', false, false, _("If you enter a URL without a full story text, clicking on the story will send the reader straight to the URL, otherwise it will be shown at the end of the full story."));
- }
- }
-
- /**
- */
- function getInfo(&$vars, &$info)
- {
- parent::getInfo($vars, $info);
-
- /* Build release date. */
- if (!empty($info['publish_now'])) {
- $info['story_published'] = time();
- } elseif (!empty($info['publish_date'])) {
- $info['story_published'] = mktime(
- (int)$info['publish_time']['hour'],
- (int)$info['publish_time']['minute'],
- 0,
- date('n', $info['publish_date']),
- date('j', $info['publish_date']),
- date('Y', $info['publish_date']));
- } else {
- $info['story_published'] = null;
- }
-
- unset($info['publish_now']);
- unset($info['publish_date']);
- unset($info['publish_time']);
- }
-
-}
/**
* Jonah Base Class.
*
+ * Copyright 2002-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Eric Rechlin <eric@hpcalc.org>
*
/**
* Obtain the list of stories from the passed in URI.
*
+ * @deprecated Will be removed when external channels are removed.
+ *
* @param string $url The url to get the list of the channel's stories.
*/
static public function readURL($url)
}
/**
- * Returns a drop-down select box to choose which view to display.
- *
- * @param $name Name to assign to select box.
- * @param $selected Currently selected item. (optional)
- * @param $onchange JavaScript onchange code. (optional)
- *
- * @return string Generated select box code
- */
- static public function buildViewWidget($name, $selected = 'standard', $onchange = '')
- {
- require JONAH_BASE . '/config/templates.php';
-
- if ($onchange) {
- $onchange = ' onchange="' . $onchange . '"';
- }
-
- $html = '<select name="' . $name . '"' . $onchange . '>' . "\n";
- foreach ($templates as $key => $tinfo) {
- $select = ($selected == $key) ? ' selected="selected"' : '';
- $html .= '<option value="' . $key . '"' . $select . '>' . $tinfo['name'] . "</option>\n";
- }
- return $html . '</select>';
- }
-
- /**
+ * @deprecated Remove when external channels moved to hippo.
*/
static public function getChannelTypeLabel($type)
{
switch ($type) {
case Jonah::INTERNAL_CHANNEL:
return _("Local Feed");
-
- case Jonah::EXTERNAL_CHANNEL:
- return _("External Feed");
-
- case Jonah::AGGREGATED_CHANNEL:
- return _("Aggregated Feed");
-
- case Jonah::COMPOSITE_CHANNEL:
- return _("Composite Feed");
}
}
switch ($filter) {
case 'internal_channels':
- case 'external_channels':
if (empty($in) || !$perms->exists('jonah:news:' . $filter . ':' . $in)) {
return $perms->hasPermission('jonah:news:' . $filter, $GLOBALS['registry']->getAuth(), $permission);
} elseif (!is_array($in)) {
}
/**
+ * @deprecated Remove when external channels removed.
*
* @param string $type The Jonah::* constant for the channel type.
*
{
if ($type == Jonah::INTERNAL_CHANNEL) {
return 'internal_channels';
- } elseif ($type == Jonah::EXTERNAL_CHANNEL) {
- return 'external_channels';
}
}
return array_shift(array_keys($types));
}
-}
+ /**
+ * Returns the available channel types based on what was set in the
+ * configuration.
+ *
+ * @return array The available news channel types.
+ */
+ static public function getAvailableTypes()
+ {
+ $types = array();
+
+ if (empty($GLOBALS['conf']['news']['enable'])) {
+ return $types;
+ }
+ if (in_array('internal', $GLOBALS['conf']['news']['enable'])) {
+ $types[Jonah::INTERNAL_CHANNEL] = _("Local Feed");
+ }
+ if (in_array('composite', $GLOBALS['conf']['news']['enable'])) {
+ $types[Jonah::COMPOSITE_CHANNEL] = _("Composite Feed");
+ }
+
+ return $types;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/*
+ * Jonah_View:: class wraps display or the various channel and story views.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
+ */
+abstract class Jonah_View_Base
+{
+ /**
+ * Values to include in the view's scope
+ *
+ * @var array
+ */
+ protected $_params;
+
+ /**
+ * Const'r
+ *
+ * @param array $params View parameters
+ */
+ public function __construct($params = array())
+ {
+ $this->_params = $params;
+ }
+
+ protected function _exit($message)
+ {
+ extract($this->_params, EXTR_REFS);
+ $notification->push(sprintf(_("Error fetching story: %s"), $message), 'horde.error');
+ require JONAH_TEMPLATES . '/common-header.inc';
+ $notification->notify(array('listeners' => 'status'));
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ exit;
+ }
+
+ /**
+ * Render this view.
+ *
+ */
+ abstract public function run();
+
+}
+
--- /dev/null
+<?php
+/**
+ * View for handling deletion of channels.
+ *
+ * Copyright 2003 - 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
+ */
+class Jonah_View_ChannelDelete extends Jonah_View_Base
+{
+ /**
+ * Expects:
+ * $vars
+ * $registry
+ * $notification
+ */
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+
+ /* Set up the form variables and the form. */
+ $form_submit = $vars->get('submitbutton');
+ $channel_id = $vars->get('channel_id');
+
+ try {
+ $channel = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannel($channel_id);
+ } catch (Exception $e) {
+ Horde::logMessage($e, 'ERR');
+ $notification->push(_("Invalid channel specified for deletion."), 'horde.message');
+ Horde::url('channels')->redirect();
+ exit;
+ }
+
+ /* If not yet submitted set up the form vars from the fetched channel. */
+ if (empty($form_submit)) {
+ $vars = new Horde_Variables($channel);
+ }
+
+ /* Check permissions and deny if not allowed. */
+ if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::DELETE, $channel_id)) {
+ $notification->push(_("You are not authorised for this action."), 'horde.warning');
+ $registry->authenticationFailure();
+ }
+
+ $title = sprintf(_("Delete News Channel \"%s\"?"), $vars->get('channel_name'));
+ $form = new Horde_Form($vars, $title);
+ $form->setButtons(array(_("Delete"), _("Do not delete")));
+ $form->addHidden('', 'channel_id', 'int', true, true);
+ $msg = _("Really delete this News Channel? All stories created in this channel will be lost!");
+ $form->addVariable($msg, 'confirm', 'description', false);
+ if ($form_submit == _("Delete")) {
+ if ($form->validate($vars)) {
+ $form->getInfo($vars, $info);
+ try {
+ $delete = $GLOBALS['injector']->getInstance('Jonah_Driver')->deleteChannel($info);
+ $notification->push(_("The channel has been deleted."), 'horde.success');
+ Horde::url('channels')->redirect();
+ exit;
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("There was an error deleting the channel: %s"), $e->getMessage()), 'horde.error');
+ }
+ }
+ } elseif (!empty($form_submit)) {
+ $notification->push(_("Channel has not been deleted."), 'horde.message');
+ Horde::url('channels')->redirect();
+ exit;
+ }
+
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ $form->renderActive(null, $vars, Horde::selfUrl(), 'post');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
+ */
+class Jonah_View_ChannelEdit extends Jonah_View_Base
+{
+ /**
+ * expects
+ * $notification
+ * $registry
+ * $vars
+ */
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+
+ $form = new Jonah_Form_Feed($vars);
+
+ /* Set up some variables. */
+ $formname = $vars->get('formname');
+ $channel_id = $vars->get('channel_id');
+
+ /* Form not yet submitted and is being edited. */
+ if (!$formname && $channel_id) {
+ $vars = new Horde_Variables($GLOBALS['injector']->getInstance('Jonah_Driver')->getChannel($channel_id));
+ }
+
+ /* Get the vars for channel type. */
+ $channel_type = $vars->get('channel_type');
+
+ /* Check permissions and deny if not allowed. */
+ if (!Jonah::checkPermissions(Jonah::typeToPermName($channel_type), Horde_Perms::EDIT, $channel_id)) {
+ $notification->push(_("You are not authorised for this action."), 'horde.warning');
+ $registry->authenticationFailure();
+ }
+
+ /* Output the extra fields required for this channel type. */
+ $form->setExtraFields($channel_id);
+ if ($formname && empty($changed_type)) {
+ if ($form->validate($vars)) {
+ $form->getInfo($vars, $info);
+ try {
+ $save = $GLOBALS['injector']->getInstance('Jonah_Driver')->saveChannel($info);
+ $notification->push(sprintf(_("The feed \"%s\" has been saved."), $info['channel_name']), 'horde.success');
+ Horde::url('channels')->redirect();
+ exit;
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("There was an error saving the feed: %s"), $e->getMessage()), 'horde.error');
+ }
+ }
+ }
+
+ $renderer = new Horde_Form_Renderer();
+ $title = $form->getTitle();
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ $form->renderActive($renderer, $vars, 'edit.php', 'post');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * View for displaying Jonah channels.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
+ */
+class Jonah_View_ChannelList extends Jonah_View_Base
+{
+ /**
+ *
+ */
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+ try {
+ $channels = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannels();
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("An error occurred fetching channels: %s"), $e->getMessage()), 'horde.error');
+ $channels = false;
+ }
+ if ($channels) {
+ $channels = Jonah::checkPermissions('channels', Horde_Perms::SHOW, $channels);
+ /* Build channel specific fields. */
+ foreach ($channels as $key => $channel) {
+ /* Edit channel link. */
+ $url = Horde::url('channels/edit.php')->add('channel_id', $channel['channel_id']);
+ $channels[$key]['edit_link'] = $url->link(array('title' => _("Edit channel"))) . Horde::img('edit.png') . '</a>';
+
+ /* Delete channel link. */
+ $url = Horde::url('channels/delete.php')->add('channel_id', $channel['channel_id']);
+ $channels[$key]['delete_link'] = $url->link(array('title' => _("Delete channel"))) . Horde::img('delete.png') . '</a>';
+
+ /* View stories link. */
+ $channels[$key]['stories_url'] = Horde::url('stories/index.php')->add('channel_id', $channel['channel_id']);
+
+ /* Channel type specific links. */
+ $channels[$key]['addstory_link'] = '';
+ $channels[$key]['refresh_link'] = '';
+
+ switch ($channel['channel_type']) {
+ case Jonah::INTERNAL_CHANNEL:
+ /* Add story link. */
+ $url = Horde::url('stories/edit.php')->add('channel_id', $channel['channel_id']);
+ $channels[$key]['addstory_link'] = $url->link(array('title' => _("Add story"))) . Horde::img('new.png') . '</a>';
+ break;
+ }
+ $channels[$key]['channel_type'] = Jonah::getChannelTypeLabel($channel['channel_type']);
+ $channels[$key]['channel_updated'] = ($channel['channel_updated'] ? strftime($prefs->getValue('date_format'), (int)$channel['channel_updated']) : '-');
+ }
+ }
+
+ $view = new Horde_View(array('templatePath' => JONAH_TEMPLATES . '/view'));
+ $view->addHelper('Tag');
+ $view->channels = $channels;
+ $view->search_img = Horde::img('search.png');
+ $title = _("Feeds");
+ Horde::addScriptFile('prototype.js', 'horde', true);
+ Horde::addScriptFile('tables.js', 'horde', true);
+ Horde::addScriptFile('quickfinder.js', 'horde', true);
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ echo $view->render('channellist');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Script to handle requests for html delivery of stories.
+ *
+ * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Jan Schneider <jan@horde.org>
+ */
+class Jonah_View_DeliveryHtml extends Jonah_View_Base
+{
+ /**
+ * $registry
+ * $notification
+ * $conf
+ * $criteria
+ *
+ */
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+ require JONAH_BASE . '/config/templates.php';
+
+ /* Get requested channel. */
+ try {
+ $channel = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannel($criteria['feed']);
+ } catch (Exception $e) {
+ Horde::logMessage($e, 'ERR');
+ $notification->push(_("Invalid channel."), 'horde.error');
+ Horde::url('delivery/index.php', true)->redirect();
+ exit;
+ }
+
+ $title = sprintf(_("HTML Delivery for \"%s\""), $channel['channel_name']);
+
+ $options = array();
+ foreach ($templates as $key => $info) {
+ $options[] = '<option value="' . $key . '"' . ($key == $criteria['format'] ? ' selected="selected"' : '') . '>' . $info['name'] . '</option>';
+ }
+
+ $template = new Horde_Template();
+ $template->setOption('gettext', 'true');
+ $template->set('url', Horde::selfUrl());
+ $template->set('session', Horde_Util::formInput());
+ $template->set('channel_id', $criteria['feed']);
+ $template->set('channel_name', $channel['channel_name']);
+ $template->set('format', $criteria['format']);
+ $template->set('options', $options);
+
+ // @TODO: This is ugly. storage driver shouldn't be rendering any display
+ // refactor this to use individual views possibly with a choice of different templates
+ $template->set('stories', $GLOBALS['injector']->getInstance('Jonah_Driver')->renderChannel($criteria['feed'], $criteria['format']));
+ $template->set('menu', Jonah::getMenu('string'));
+
+ // Buffer the notifications and send to the template
+ Horde::startBuffer();
+ $GLOBALS['notification']->notify(array('listeners' => 'status'));
+ $template->set('notify', Horde::endBuffer());
+
+ require JONAH_TEMPLATES . '/common-header.inc';
+ echo $template->fetch(JONAH_TEMPLATES . '/delivery/html.html');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Jonah_View_StoryDelete:: handle story deletion
+ *
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Jonah
+ */
+class Jonah_View_StoryDelete extends Jonah_View_Base
+{
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+
+ $form_submit = $vars->get('submitbutton');
+ $channel_id = $vars->get('channel_id');
+ $story_id = $vars->get('id');
+
+ /* Driver */
+ $driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
+
+ /* Fetch the channel details, needed for later and to check if valid
+ * channel has been requested. */
+ try {
+ $channel = $driver->getChannel($channel_id);
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("Story editing failed: %s"), $e->getMessage()), 'horde.error');
+ Horde::url('channels/index.php', true)->redirect();
+ exit;
+ }
+
+ /* Check permissions. */
+ if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::DELETE, $channel_id)) {
+ $notification->push(_("You are not authorised for this action."), 'horde.warning');
+ $registry->authenticationFailure();
+ }
+
+ try {
+ $story = $driver->getStory($channel_id, $story_id);
+ } catch (Exception $e) {
+ $notification->push(_("No valid story requested for deletion."), 'horde.message');
+ Horde::url('channels/index.php', true)->redirect();
+ exit;
+ }
+
+ /* If not yet submitted set up the form vars from the fetched story. */
+ if (empty($form_submit)) {
+ $vars = new Horde_Variables($story);
+ }
+
+ $title = sprintf(_("Delete News Story \"%s\"?"), $vars->get('title'));
+
+ $form = new Horde_Form($vars, $title);
+ $form->setButtons(array(_("Delete"), _("Do not delete")));
+ $form->addHidden('', 'channel_id', 'int', true, true);
+ $form->addHidden('', 'id', 'int', true, true);
+ $form->addVariable(_("Really delete this News Story?"), 'confirm', 'description', false);
+
+ if ($form_submit == _("Delete")) {
+ if ($form->validate($vars)) {
+ $form->getInfo($vars, $info);
+ try {
+ $delete = $driver->deleteStory($info['channel_id'], $info['id']);
+ $notification->push(_("The story has been deleted."), 'horde.success');
+ Horde::url('stories/index.php', true)->add('channel_id', $channel_id)->setRaw(true)->redirect();
+ exit;
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("There was an error deleting the story: %s"), $e->getMessage()), 'horde.error');
+ }
+ }
+ } elseif (!empty($form_submit)) {
+ $notification->push(_("Story has not been deleted."), 'horde.message');
+ $url = Horde::url('stories/index.php', true)->add('channel_id', $channel_id)->setRaw(true);
+ Horde::url('stories/index.php', true)->add('channel_id', $channel_id)->setRaw(true)->redirect();
+ exit;
+ }
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ $form->renderActive(null, $vars, 'delete.php', 'post');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Jonah_View_StoryEdit:: to add/edit stories.
+ *
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Jonah
+ *
+ * @TODO: This will be rewritten to NOT use Horde_Form since we want more
+ * control over the form and, especially, the RTE.
+ */
+class Jonah_View_StoryEdit extends Jonah_View_Base
+{
+ /**
+ * $notification
+ * $registry
+ * $vars
+ *
+ */
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+
+ $driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
+
+ /* Set up the form variables. */
+ $channel_id = $vars->get('channel_id');
+
+ /* Fetch the channel details, needed for later and to check if valid
+ * channel has been requested. */
+ try {
+ $channel = $driver->getChannel($channel_id);
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("Story editing failed: %s"), $e->getMessage()), 'horde.error');
+ Horde::url('channels/index.php', true)->redirect();
+ exit;
+ }
+
+ /* Check permissions. */
+ if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::EDIT, $channel_id)) {
+ $notification->push(_("You are not authorised for this action."), 'horde.warning');
+ $registry->authenticationFailure();
+ }
+
+ /* Check if a story is being edited. */
+ $story_id = $vars->get('id');
+ if ($story_id && !$vars->get('formname')) {
+ $story = $driver->getStory($channel_id, $story_id);
+ $story['tags'] = implode(',', array_values($story['tags']));
+ $vars = new Horde_Variables($story);
+ }
+
+ /* Set up the form. */
+ $form = new Jonah_Form_Story($vars);
+ if ($form->validate($vars)) {
+ $form->getInfo($vars, $info);
+ try {
+ $result = $driver->saveStory($info);
+ $notification->push(sprintf(_("The story \"%s\" has been saved."), $info['title']), 'horde.success');
+ Horde::url('stories/index.php')->add('channel_id', $channel_id)->redirect();
+ exit;
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("There was an error saving the story: %s"), $e->getMessage()), 'horde.error');
+ }
+ }
+
+ /* Needed javascript. */
+ Horde::addScriptFile('open_calendar.js', 'horde');
+ $title = $form->getTitle();
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ $form->renderActive($form->getRenderer(), $vars, 'edit.php', 'post');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Turba_View_StoryList:: A view to handle displaying a list of stories in a
+ * channel.
+ *
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
+ */
+class Jonah_View_StoryList extends Jonah_View_Base
+{
+ /**
+ * expects
+ * $registry
+ * $notification
+ * $prefs
+ * $conf
+ * $channel_id
+ */
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+
+ $channel = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannel($channel_id);
+ if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::EDIT, $channel_id)) {
+ $notification->push(_("You are not authorised for this action."), 'horde.warning');
+ $registry->authenticationFailure();
+ }
+
+ /* Check if a URL has been passed. */
+ $url = Horde_Util::getFormData('url');
+ if ($url) {
+ $url = new Horde_Url($url);
+ }
+
+ try {
+ $stories = $GLOBALS['injector']->getInstance('Jonah_Driver')->getStories(array('channel_id' => $channel_id));
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("Invalid channel requested. %s"), $e->getMessage()), 'horde.error');
+ Horde::url('channels/index.php', true)->redirect();
+ exit;
+ }
+
+ /* Do some state tests. */
+ if (empty($stories)) {
+ $notification->push(_("No available stories."), 'horde.warning');
+ }
+ if (!empty($refresh)) {
+ $notification->push(_("Channel refreshed."), 'horde.success');
+ }
+ if (!empty($url)) {
+ $url->redirect();
+ exit;
+ }
+
+ /* Get channel details, for title, etc. */
+ $allow_delete = Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::DELETE, $channel_id);
+
+ /* Build story specific fields. */
+ foreach ($stories as $key => $story) {
+ /* published is the publication/release date, updated is the last change date. */
+ if (!empty($stories[$key]['published'])) {
+ $stories[$key]['published_date'] = strftime($prefs->getValue('date_format') . ', ' . ($prefs->getValue('twentyFour') ? '%H:%M' : '%I:%M%p'), $stories[$key]['published']);
+ } else {
+ $stories[$key]['published_date'] = '';
+ }
+
+ /* Default to no links. */
+ $stories[$key]['pdf_link'] = '';
+ $stories[$key]['edit_link'] = '';
+ $stories[$key]['delete_link'] = '';
+ $stories[$key]['view_link'] = Horde::link(Horde::url($story['permalink']), $story['description']) . htmlspecialchars($story['title']) . '</a>';
+
+ /* PDF link. */
+ $url = Horde::url('stories/pdf.php');
+ $url = Horde_Util::addParameter($url, array('id' => $story['id'], 'channel_id' => $channel_id));
+ $stories[$key]['pdf_link'] = Horde::link($url, _("PDF version")) . Horde::img('mime/pdf.png') . '</a>';
+
+ /* Edit story link. */
+ $url = Horde::url('stories/edit.php');
+ $url = Horde_Util::addParameter($url, array('id' => $story['id'], 'channel_id' => $channel_id));
+ $stories[$key]['edit_link'] = Horde::link($url, _("Edit story")) . Horde::img('edit.png') . '</a>';
+
+ /* Delete story link. */
+ if ($allow_delete) {
+ $url = Horde::url('stories/delete.php');
+ $url = Horde_Util::addParameter($url, array('id' => $story['id'], 'channel_id' => $channel_id));
+ $stories[$key]['delete_link'] = Horde::link($url, _("Delete story")) . Horde::img('delete.png') . '</a>';
+ }
+
+ /* Comment counter. */
+ if ($conf['comments']['allow'] &&
+ $registry->hasMethod('forums/numMessages')) {
+ $comments = $registry->call('forums/numMessages', array($stories[$key]['id'], 'jonah'));
+ if (!is_a($comments, 'PEAR_Error')) {
+ $stories[$key]['comments'] = $comments;
+ }
+ }
+
+ }
+
+ /* Render page */
+ $title = $channel['channel_name'];
+ $view = new Horde_View(array('templatePath' => JONAH_TEMPLATES . '/stories'));
+ $view->stories = $stories;
+ $view->read = true;
+ $view->comments = $conf['comments']['allow'] && $registry->hasMethod('forums/numMessages') && $channel['channel_type'] == Jonah::INTERNAL_CHANNEL;
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ echo $view->render('index');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @package Jonah
+ */
+class Jonah_View_StoryPdf extends Jonah_View
+{
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+
+ $driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
+ if (!$story_id) {
+ try {
+ $story_id = $GLOBALS['injector']->getInstance('Jonah_Driver')->getLatestStoryId($channel_id);
+ } catch (Exception $e) {
+ $this->_exit($e->getMessage());
+ }
+ }
+ try {
+ $story = $driver->getStory($channel_id, $story_id, !$browser->isRobot());
+ } catch (Exception $e) {
+ $this->_exit($e->getMessage());
+ }
+
+ // Convert the body from HTML to text if necessary.
+ if (!empty($story['body_type']) && $story['body_type'] == 'richtext') {
+ $story['body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['body'], 'html2text');
+ }
+
+ // Set up the PDF object.
+ $pdf = File_PDF::factory(array('format' => 'Letter', 'unit' => 'pt'));
+ $pdf->setMargins(50, 50);
+
+ // Enable automatic page breaks.
+ $pdf->setAutoPageBreak(true, 50);
+
+ // Start the document.
+ $pdf->open();
+
+ // Start a page.
+ $pdf->addPage();
+
+ // Publication date.
+ if (!empty($story['published_date'])) {
+ $pdf->setFont('Times', 'B', 14);
+ $pdf->cell(0, 14, $story['published_date'], 0, 1);
+ $pdf->newLine(10);
+ }
+
+ // Write the header in Times 24 Bold.
+ $pdf->setFont('Times', 'B', 24);
+ $pdf->multiCell(0, 24, $story['title'], 'B', 1);
+ $pdf->newLine(20);
+
+ // Write the story body in Times 14.
+ $pdf->setFont('Times', '', 14);
+ $pdf->write(14, $story['body']);
+
+ // Output the generated PDF.
+ $browser->downloadHeaders($story['title'] . '.pdf', 'application/pdf');
+ echo $pdf->getOutput();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Jonah_View_StoryView:: class to display an individual story.
+ *
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
+ */
+class Jonah_View_StoryView extends Jonah_View_Base
+{
+ /**
+ * Expects
+ * $registry
+ * $notification
+ * $browser
+ * $story_id
+ * $channel_id
+ *
+ */
+ public function run()
+ {
+ extract($this->_params, EXTR_REFS);
+
+ $driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
+ try {
+ $story = $driver->getStory($channel_id, $story_id, !$browser->isRobot());
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("Error fetching story: %s"), $e->getMessage()), 'horde.warning');
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ exit;
+ }
+
+ /* Grab tag related content for entire channel */
+ $cloud = new Horde_Ui_TagCloud();
+ $allTags = $driver->listTagInfo(array(), $channel_id);
+ foreach ($allTags as $tag_id => $taginfo) {
+ $cloud->addElement($taginfo['tag_name'], Horde::url('results.php')->add(array('tag_id' => $tag_id, 'channel_id' => $channel_id)), $taginfo['total']);
+ }
+
+ /* Prepare the story's tags for display */
+ // FIXME - need to actually use these.
+ $tag_html = array();
+ $tag_link = Horde::url('stories/results.php')->add('channel_id', $channel_id);
+ foreach ($story['tags'] as $id => $tag) {
+ $link = $tag_link->copy()->add('tag_id', $id);
+ $tag_html[] = $link->link() . $tag . '</a>';
+ }
+
+ /* Filter and prepare story content. */
+ if (!empty($story['body_type']) && $story['body_type'] == 'text') {
+ $story['body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
+ }
+
+ // @TODO: Where is this used and what for?
+ if (!empty($story['url'])) {
+ $story['body'] .= Horde::link(Horde::externalUrl($story['url'])) . htmlspecialchars($story['url']) . '</a></p>';
+ }
+
+ if (empty($story['published_date'])) {
+ $story['published_date'] = false;
+ }
+
+ $view = new Horde_View(array('templatePath' => array(JONAH_TEMPLATES . '/stories',
+ JONAH_TEMPLATES . '/stories/partial',
+ JONAH_TEMPLATES . '/stories/layout')));
+ $view->addHelper('Tag');
+ $view->tagcloud = $cloud->buildHTML();
+ $view->story = $story;
+
+ /* Insert link for sharing. */
+ if ($conf['sharing']['allow']) {
+ $url = Horde::url('stories/share.php')->add(array('id' => $story['id'], 'channel_id' => $channel_id));
+ $view->sharelink = $url->link() . _("Share this story") . '</a>';
+ }
+
+ /* Insert comments. */
+ if ($conf['comments']['allow']) {
+ if (!$registry->hasMethod('forums/doComments')) {
+ $err = 'User comments are enabled but the forums API is not available.';
+ Horde::logMessage($err, 'ERR');
+ } else {
+ try {
+ $comments = $registry->call('forums/doComments', array('jonah', $story_id, 'commentCallback'));
+ } catch (Exception $e) {
+ Horde::logMessage($e, 'ERR');
+ $comments = array('threads' => '', 'comments' => '');
+ }
+ $view->comments = $comments;
+ }
+ }
+
+ require JONAH_TEMPLATES . '/common-header.inc';
+ require JONAH_TEMPLATES . '/menu.inc';
+ echo $view->render('view');
+ require $registry->get('templates', 'horde') . '/common-footer.inc';
+ }
+
+}
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Marko Djukic <marko@oblo.com>
+ * @package Jonah
*/
-
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
-require_once 'Horde/Form.php';
-require_once 'Horde/Form/Renderer.php';
-
-/* Set up the form variables. */
-$vars = Horde_Variables::getDefaultVariables();
-$form_submit = $vars->get('submitbutton');
-$channel_id = $vars->get('channel_id');
-$story_id = $vars->get('story_id');
-
-/* Driver */
-$news = Jonah_News::factory();
-
-/* Fetch the channel details, needed for later and to check if valid
- * channel has been requested. */
-$channel = $news->isChannelEditable($channel_id);
-if (is_a($channel, 'PEAR_Error')) {
- $notification->push(sprintf(_("Story editing failed: %s"), $channel->getMessage()), 'horde.error');
- Horde::url('channels/index.php', true)->redirect();
-}
-
-/* Check permissions. */
-if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::DELETE, $channel_id)) {
- $notification->push(_("You are not authorised for this action."), 'horde.warning');
- Horde::authenticationFailureRedirect();
-}
-
-$story = $news->getStory($channel_id, $story_id);
-if (is_a($story, 'PEAR_Error')) {
- $notification->push(_("No valid story requested for deletion."), 'horde.message');
- Horde::url('channels/index.php', true)->redirect();
-}
-
-/* If not yet submitted set up the form vars from the fetched story. */
-if (empty($form_submit)) {
- $vars = new Horde_Variables($story);
-}
-
-$title = sprintf(_("Delete News Story \"%s\"?"), $vars->get('story_title'));
-
-$form = new Horde_Form($vars, $title);
-
-$form->setButtons(array(_("Delete"), _("Do not delete")));
-$form->addHidden('', 'channel_id', 'int', true, true);
-$form->addHidden('', 'story_id', 'int', true, true);
-$form->addVariable(_("Really delete this News Story?"), 'confirm', 'description', false);
-
-if ($form_submit == _("Delete")) {
- if ($form->validate($vars)) {
- $form->getInfo($vars, $info);
- $delete = $news->deleteStory($info['channel_id'], $info['story_id']);
- if (is_a($delete, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error deleting the story: %s"), $delete->getMessage()), 'horde.error');
- } else {
- $notification->push(_("The story has been deleted."), 'horde.success');
- Horde::url('stories/index.php', true)
- ->add('channel_id', $channel_id)
- ->redirect();
- }
- }
-} elseif (!empty($form_submit)) {
- $notification->push(_("Story has not been deleted."), 'horde.message');
- Horde::url('stories/index.php', true)
- ->add('channel_id', $channel_id)
- ->redirect();
-}
-
-$template = new Horde_Template();
-
-Horde::startBuffer();
-$form->renderActive(null, $vars, 'delete.php', 'post');
-$template->set('main', Horde::endBuffer());
-$template->set('menu', Horde::menu());
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/main/main.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+Horde_Registry::appInit('jonah');
+$params = array('notification' => &$notification,
+ 'registry' => &$registry,
+ 'vars' => Horde_Variables::getDefaultVariables());
+$view = new Jonah_View_StoryDelete($params);
+$view->run();
/**
* Script to add/edit stories.
*
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
- *
- * $Horde: jonah/stories/edit.php,v 1.48 2009/11/24 04:15:38 chuck Exp $
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you did not
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Marko Djukic <marko@oblo.com>
+ * @package Jonah
*/
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
-require_once JONAH_BASE . '/lib/Forms/Story.php';
-require_once 'Horde/Form/Action.php';
-require_once 'Horde/Form/Renderer.php';
-
-$news = Jonah_News::factory();
-
-/* Set up the form variables. */
-$vars = Horde_Variables::getDefaultVariables();
-$channel_id = $vars->get('channel_id');
-
-/* Fetch the channel details, needed for later and to check if valid
- * channel has been requested. */
-$channel = $news->isChannelEditable($channel_id);
-if (is_a($channel, 'PEAR_Error')) {
- $notification->push(sprintf(_("Story editing failed: %s"), $channel->getMessage()), 'horde.error');
- Horde::url('channels/index.php', true)->redirect();
-}
-
-/* Check permissions. */
-if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::EDIT, $channel_id)) {
- $notification->push(_("You are not authorised for this action."), 'horde.warning');
- Horde::authenticationFailureRedirect();
-}
-
-/* Check if a story is being edited. */
-$story_id = $vars->get('story_id');
-if ($story_id && !$vars->get('formname')) {
- $story = $news->getStory($channel_id, $story_id);
- $story['story_tags'] = implode(',', array_values($story['story_tags']));
- $vars = new Horde_Variables($story);
-}
-
-/* Set up the form. */
-$form = new StoryForm($vars);
-if ($form->validate($vars)) {
- $form->getInfo($vars, $info);
- $result = $news->saveStory($info);
- if (is_a($result, 'PEAR_Error')) {
- $notification->push(sprintf(_("There was an error saving the story: %s"), $result->getMessage()), 'horde.error');
- } else {
- $notification->push(sprintf(_("The story \"%s\" has been saved."), $info['story_title']), 'horde.success');
- Horde::url('stories/index.php', true)
- ->add('channel_id', $channel_id)
- ->redirect();
- }
-}
-
-/* Render the form. */
-$template = new Horde_Template();
-
-Horde::startBuffer();
-$form->renderActive($form->getRenderer(), $vars, 'edit.php', 'post');
-$template->set('main', Horde::endBuffer());
-$template->set('menu', Horde::menu());
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
+Horde_Registry::appInit('jonah');
-$title = $form->getTitle();
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/main/main.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+$params = array('notification' => &$notification,
+ 'registry' => &$registry,
+ 'vars' => Horde_Variables::getDefaultVariables());
+$view = new Jonah_View_StoryEdit($params);
+$view->run();
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
* @author Marko Djukic <marko@oblo.com>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
*/
-
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
-$news = Jonah_News::factory();
+Horde_Registry::appInit('jonah');
/* Redirect to the news index if no channel_id is specified. */
$channel_id = Horde_Util::getFormData('channel_id');
if (empty($channel_id)) {
$notification->push(_("No channel requested."), 'horde.error');
- Horde::url('channels/index.php', true)->redirect();
-}
-
-$channel = $news->getChannel($channel_id);
-if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::EDIT, $channel_id)) {
- $notification->push(_("You are not authorised for this action."), 'horde.warning');
- Horde::authenticationFailureRedirect();
-}
-
-/* Check if a forced refresh is being called for an external channel. */
-$refresh = Horde_Util::getFormData('refresh');
-
-/* Check if a URL has been passed. */
-$url = Horde_Util::getFormData('url');
-
-$stories = $news->getStories($channel_id, null, 0, !empty($refresh), null, true);
-if (is_a($stories, 'PEAR_Error')) {
- $notification->push(sprintf(_("Invalid channel requested. %s"), $stories->getMessage()), 'horde.error');
- Horde::url('channels/index.php', true)->redirect();
-}
-
-/* Do some state tests. */
-if (empty($stories)) {
- $notification->push(_("No available stories."), 'horde.warning');
-}
-if (!empty($refresh)) {
- $notification->push(_("Channel refreshed."), 'horde.success');
-}
-if (!empty($url)) {
- header('Location: ' . $url);
+ header('Location: ' . Horde::url('channels/index.php', true));
exit;
}
-/* Get channel details, for title, etc. */
-$channel = $news->getChannel($channel_id);
-
-$allow_delete = Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::DELETE, $channel_id);
-
-/* Build story specific fields. */
-foreach ($stories as $key => $story) {
- /* story_published is the publication/release date, story_updated
- * is the last change date. */
- if (!empty($stories[$key]['story_published'])) {
- $stories[$key]['story_published_date'] = strftime($prefs->getValue('date_format') . ', ' . ($prefs->getValue('twentyFour') ? '%H:%M' : '%I:%M%p'), $stories[$key]['story_published']);
- } else {
- $stories[$key]['story_published_date'] = '';
- }
-
- /* Default to no links. */
- $stories[$key]['pdf_link'] = '';
- $stories[$key]['edit_link'] = '';
- $stories[$key]['delete_link'] = '';
-
- /* These links only if internal channel. */
- if ($channel['channel_type'] == Jonah::INTERNAL_CHANNEL ||
- $channel['channel_type'] == Jonah::COMPOSITE_CHANNEL) {
- $stories[$key]['view_link'] = Horde::link(Horde::url($story['story_link']), $story['story_desc']) . htmlspecialchars($story['story_title']) . '</a>';
-
- /* PDF link. */
- $url = Horde::url('stories/pdf.php');
- $url = Horde_Util::addParameter($url, array('story_id' => $story['story_id'], 'channel_id' => $channel_id));
- $stories[$key]['pdf_link'] = Horde::link($url, _("PDF version")) . Horde::img('mime/pdf.png') . '</a>';
-
- /* Edit story link. */
- $url = Horde::url('stories/edit.php');
- $url = Horde_Util::addParameter($url, array('story_id' => $story['story_id'], 'channel_id' => $channel_id));
- $stories[$key]['edit_link'] = Horde::link($url, _("Edit story")) . Horde::img('edit.png') . '</a>';
-
- /* Delete story link. */
- if ($allow_delete) {
- $url = Horde::url('stories/delete.php');
- $url = Horde_Util::addParameter($url, array('story_id' => $story['story_id'], 'channel_id' => $channel_id));
- $stories[$key]['delete_link'] = Horde::link($url, _("Delete story")) . Horde::img('delete.png') . '</a>';
- }
-
- /* Comment counter. */
- if ($conf['comments']['allow'] &&
- $registry->hasMethod('forums/numMessages')) {
- $comments = $registry->call('forums/numMessages', array($stories[$key]['story_id'], 'jonah'));
- if (!is_a($comments, 'PEAR_Error')) {
- $stories[$key]['comments'] = $comments;
- }
- }
- } else {
- if (!empty($story['story_body'])) {
- $stories[$key]['view_link'] = Horde::link(Horde::url($story['story_link']), $story['story_desc'], '', '_blank') . htmlspecialchars($story['story_title']) . '</a>';
- } else {
- $stories[$key]['view_link'] = Horde::link(Horde::externalUrl($story['story_url']), $story['story_desc'], '', '_blank') . htmlspecialchars($story['story_title']) . '</a>';
- }
- }
-}
-
-$template = new Horde_Template();
-$template->setOption('gettext', true);
-$template->set('header', htmlspecialchars($channel['channel_name']));
-$template->set('refresh', Horde::link(Horde_Util::addParameter(Horde::selfUrl(true), array('refresh' => 1)), _("Refresh Channel")) . Horde::img('reload.png') . '</a>');
-$template->set('listheaders', array(_("Story"), _("Date")));
-$template->set('stories', $stories, true);
-$template->set('read', $channel['channel_type'] == Jonah::INTERNAL_CHANNEL || $channel['channel_type'] == Jonah::COMPOSITE_CHANNEL, true);
-$template->set('comments', $conf['comments']['allow'] && $registry->hasMethod('forums/numMessages') && $channel['channel_type'] == Jonah::INTERNAL_CHANNEL, true);
-$template->set('menu', Horde::menu());
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
-
-$title = $channel['channel_name'];
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $template->fetch(JONAH_TEMPLATES . '/stories/index.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+$params = array('registry' => &$registry,
+ 'notification' => &$notification,
+ 'prefs' => &$prefs,
+ 'conf' => &$conf,
+ 'channel_id' => $channel_id);
+$view = new Jonah_View_StoryList($params);
+$view->run();
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
+ * @package Jonah
*/
-
-function _exit($message)
-{
- $GLOBALS['notification']->push(sprintf(_("Error fetching story: %s"), $message), 'horde.error');
- require JONAH_TEMPLATES . '/common-header.inc';
- $GLOBALS['notification']->notify(array('listeners' => 'status'));
- require $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc';
- exit;
-}
-
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah', array(
+Horde_Registry::appInit('jonah', array(
'authentication' => 'none',
'session_control' => 'readonly'
));
-$news = Jonah_News::factory();
-
-$channel_id = Horde_Util::getFormData('channel_id');
-$story_id = Horde_Util::getFormData('story_id');
-if (!$story_id) {
- $story_id = $news->getLatestStoryId($channel_id);
- if (is_a($story_id, 'PEAR_Error')) {
- _exit($story_id->getMessage());
- }
-}
-
-$story = $news->getStory($channel_id, $story_id, !$browser->isRobot());
-if (is_a($story, 'PEAR_Error')) {
- _exit($story->getMessage());
-} elseif (empty($story['story_body']) && !empty($story['story_url'])) {
- _exit(_("Cannot generate PDFs of remote stories."));
-}
-
-// Convert the body from HTML to text if necessary.
-if (!empty($story['story_body_type']) && $story['story_body_type'] == 'richtext') {
- $story['story_body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_body'], 'html2text');
-}
-
-// Set up the PDF object.
-$pdf = File_PDF::factory(array('format' => 'Letter', 'unit' => 'pt'));
-$pdf->setMargins(50, 50);
-
-// Enable automatic page breaks.
-$pdf->setAutoPageBreak(true, 50);
-
-// Start the document.
-$pdf->open();
-
-// Start a page.
-$pdf->addPage();
-
-// Publication date.
-if (!empty($story['story_published_date'])) {
- $pdf->setFont('Times', 'B', 14);
- $pdf->cell(0, 14, $story['story_published_date'], 0, 1);
- $pdf->newLine(10);
-}
-
-// Write the header in Times 24 Bold.
-$pdf->setFont('Times', 'B', 24);
-$pdf->multiCell(0, 24, $story['story_title'], 'B', 1);
-$pdf->newLine(20);
-
-// Write the story body in Times 14.
-$pdf->setFont('Times', '', 14);
-$pdf->write(14, $story['story_body']);
-
-// Output the generated PDF.
-$browser->downloadHeaders($story['story_title'] . '.pdf', 'application/pdf');
-echo $pdf->getOutput();
+$params = array('registry' => &$registry,
+ 'notification' => &$notification,
+ 'story_id' => Horde_Util::getFormData('id'),
+ 'browser' => &$browser,
+ 'channel_id' => Horde_Util::getFormData('channel_id'));
+$view = new Jonah_View_StoryPdf($params);
+$view->run();
<?php
/**
- * Display list of articles that match a tag query from an internal
- * channel.
+ * Display list of articles that match a tag query.
+ *
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
*/
-
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah');
-
-$news = Jonah_News::factory();
+Horde_Registry::appInit('jonah');
+$driver = $GLOBALS['injector']->getInstance('Jonah_Driver');
/* Redirect to the news index if no tag_id is specified. */
$tag_id = Horde_Util::getFormData('tag_id');
* a search for tags for ALL visible internal channels. */
$channel_id = Horde_Util::getFormData('channel_id', null);
if (!is_null($channel_id)) {
- $channel = $news->getChannel($channel_id);
+ $channel = $driver->getChannel($channel_id);
if (!Jonah::checkPermissions(Jonah::typeToPermName($channel['channel_type']), Horde_Perms::SHOW, $channel_id)) {
$notification->push(_("You are not authorised for this action."), 'horde.warning');
- Horde::authenticationFailureRedirect();
+ $registry->authenticationFailure();
}
$channel_ids = array($channel_id);
} else {
$channel_ids = array();
- $channels = $news->getChannels(Jonah::INTERNAL_CHANNEL);
+ $channels = $driver->getChannels();
foreach ($channels as $ch) {
if (Jonah::checkPermissions(Jonah::typeToPermName($ch['channel_type']), Horde_Perms::SHOW, $ch['channel_id'])) {
$channel_ids[] = $ch['channel_id'];
$notification->push(_("No tag requested."), 'horde.error');
Horde::url('channels/index.php', true)->redirect();
}
-$tag_name = array_shift($news->getTagNames(array($tag_id)));
-$stories = $news->searchTagsById(array($tag_id), 10, 0, $channel_ids);
-if (is_a($stories, 'PEAR_Error')) {
- $notification->push(sprintf(_("Invalid channel requested. %s"), $stories->getMessage()), 'horde.error');
+$tag_name = array_shift($driver->getTagNames(array($tag_id)));
+
+try {
+ $stories = $driver->searchTagsById(array($tag_id), 10, 0, $channel_ids);
+} catch (Exception $e) {
+ $notification->push(sprintf(_("Invalid channel requested. %s"), $e->getMessage()), 'horde.error');
Horde::url('channels/index.php', true)->redirect();
+ exit;
}
/* Do some state tests. */
with more than one channel. */
$channel_id = $story['channel_id'];
- if (!empty($stories[$key]['story_published'])) {
- $stories[$key]['story_published_date'] = strftime($prefs->getValue('date_format') . ', ' . ($prefs->getValue('twentyFour') ? '%H:%M' : '%I:%M%p'), $stories[$key]['story_published']);
+ if (!empty($stories[$key]['published'])) {
+ $stories[$key]['published_date'] = strftime($prefs->getValue('date_format') . ', ' . ($prefs->getValue('twentyFour') ? '%H:%M' : '%I:%M%p'), $stories[$key]['published']);
} else {
- $stories[$key]['story_published_date'] = '';
+ $stories[$key]['published_date'] = '';
}
/* Default to no links. */
$stories[$key]['pdf_link'] = '';
$stories[$key]['edit_link'] = '';
$stories[$key]['delete_link'] = '';
-
- $stories[$key]['view_link'] = Horde::link(Horde::url($story['story_link']), $story['story_desc']) . htmlspecialchars($story['story_title']) . '</a>';
+ $stories[$key]['view_link'] = Horde::url($story['link'])->link(array('title' => $story['desc'])) . htmlspecialchars($story['title']) . '</a>';
/* PDF link. */
- $url = Horde::url('stories/pdf.php');
- $url = Horde_Util::addParameter($url, array('story_id' => $story['story_id'], 'channel_id' => $channel_id));
- $stories[$key]['pdf_link'] = Horde::link($url, _("PDF version")) . Horde::img('mime/pdf.png') . '</a>';
+ $url = Horde::url('stories/pdf.php')->add(array('id' => $story['id'], 'channel_id' => $channel_id));
+ $stories[$key]['pdf_link'] = $url->link(array('title' => _("PDF version"))) . Horde::img('mime/pdf.png') . '</a>';
/* Edit story link. */
if (Jonah::checkPermissions(Jonah::typeToPermName(Jonah::INTERNAL_CHANNEL), Horde_Perms::EDIT, $channel_id)) {
- $url = Horde::url('stories/edit.php');
- $url = Horde_Util::addParameter($url, array('story_id' => $story['story_id'], 'channel_id' => $channel_id));
- $stories[$key]['edit_link'] = Horde::link($url, _("Edit story")) . Horde::img('edit.png') . '</a>';
+ $url = Horde::url('stories/edit.php')->add(array('id' => $story['id'], 'channel_id' => $channel_id));
+ $stories[$key]['edit_link'] = $url->link(array('title' => _("Edit story"))) . Horde::img('edit.png') . '</a>';
}
/* Delete story link. */
if (Jonah::checkPermissions(Jonah::typeToPermName(Jonah::INTERNAL_CHANNEL), Horde_Perms::DELETE, $channel_id)) {
- $url = Horde::url('stories/delete.php');
- $url = Horde_Util::addParameter($url, array('story_id' => $story['story_id'], 'channel_id' => $channel_id));
- $stories[$key]['delete_link'] = Horde::link($url, _("Delete story")) . Horde::img('delete.png') . '</a>';
+ $url = Horde::url('stories/delete.php')->add(array('id' => $story['id'], 'channel_id' => $channel_id));
+ $stories[$key]['delete_link'] = $url->link(array('title' => _("Delete story"))) . Horde::img('delete.png') . '</a>';
}
/* Comment counter. */
if ($conf['comments']['allow'] &&
$registry->hasMethod('forums/numMessages')) {
- $comments = $registry->call('forums/numMessages', array($stories[$key]['story_id'], 'jonah'));
- if (!is_a($comments, 'PEAR_Error')) {
- $stories[$key]['comments'] = $comments;
- }
+ try {
+ $comments = $registry->call('forums/numMessages', array($stories[$key]['id'], 'jonah'));
+ } catch (Exception $e) {}
+ $stories[$key]['comments'] = $comments;
}
}
<?php
/**
- * $Horde: jonah/stories/share.php,v 1.33 2009/09/06 17:00:39 jan Exp $
- *
- * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 1999-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
+ *
+ * @package Jonah
*/
+/**
+ *
+ * @global <type> $conf
+ * @param <type> $story_part
+ * @param <type> $from
+ * @param <type> $recipients
+ * @param <type> $subject
+ * @param <type> $note
+ * @return <type>
+ */
function _mail($story_part, $from, $recipients, $subject, $note)
{
global $conf;
}
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah', array(
+Horde_Registry::appInit('jonah', array(
'authentication' => 'none',
'session_control' => 'readonly'
));
-require_once 'Horde/Form.php';
-require_once 'Horde/Form/Renderer.php';
-
-$news = Jonah_News::factory();
-
/* Set up the form variables. */
$vars = Horde_Variables::getDefaultVariables();
$channel_id = $vars->get('channel_id');
-$story_id = $vars->get('story_id');
+$story_id = $vars->get('id');
if (!$conf['sharing']['allow']) {
Horde::url('stories/view.php', true)
->add(array('story_id' => $story_id, 'channel_id' => $channel_id))
->redirect();
+ exit;
}
-$story = $news->getStory($channel_id, $story_id);
+$story = $GLOBALS['injector']->getInstance('Jonah_Driver')->getStory($channel_id, $story_id);
if (is_a($story, 'PEAR_Error')) {
$notification->push(sprintf(_("Error fetching story: %s"), $story->getMessage()), 'horde.warning');
$story = '';
}
-$vars->set('subject', $story['story_title']);
+$vars->set('subject', $story['title']);
/* Set up the form. */
$form = new Horde_Form($vars);
$form->setTitle($title);
$form->setButtons(_("Send"));
$form->addHidden('', 'channel_id', 'int', false);
-$form->addHidden('', 'story_id', 'int', false);
+$form->addHidden('', 'id', 'int', false);
$v = &$form->addVariable(_("From"), 'from', 'email', true, false);
if ($GLOBALS['registry']->getAuth()) {
$v->setDefault($injector->getInstance('Horde_Prefs_Identity')->getIdentity()->getValue('from_addr'));
if ($form->validate($vars)) {
$form->getInfo($vars, $info);
- $channel = $news->getChannel($channel_id);
+ $channel = $GLOBALS['injector']->getInstance('Jonah_Driver')->getChannel($channel_id);
if (empty($channel['channel_story_url'])) {
+<<<<<<< HEAD
+ $story_url = Horde::url('stories/view.php', true);
+ $story_url = Horde_Util::addParameter($story_url, array('channel_id' => '%c', 'id' => '%s'));
+=======
$story_url = Horde::url('stories/view.php', true);
$story_url = Horde_Util::addParameter($story_url, array('channel_id' => '%c', 'story_id' => '%s'));
+>>>>>>> master
} else {
$story_url = $channel['channel_story_url'];
}
$story_url = str_replace(array('%25c', '%25s'), array('%c', '%s'), $story_url);
- $story_url = str_replace(array('%c', '%s', '&'), array($channel_id, $story['story_id'], '&'), $story_url);
+ $story_url = str_replace(array('%c', '%s', '&'), array($channel_id, $story['id'], '&'), $story_url);
if ($info['include'] == 0) {
require_once 'Horde/MIME/Part.php';
$message_part->setContents($message_part->replaceEOL($story_url));
$message_part->setDescription(_("Story Link"));
} else {
- $message_part = Jonah_News::getStoryAsMessage($story);
+ $message_part = Jonah::getStoryAsMessage($story);
}
$result = _mail($message_part, $info['from'], $info['recipients'],
<?php
/**
- * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (BSD). If you
* did not receive this file, see http://cvs.horde.org/co.php/jonah/LICENSE.
*
* @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Jonah
*/
-
require_once dirname(__FILE__) . '/../lib/Application.php';
-$jonah = Horde_Registry::appInit('jonah', array(
- 'authentication' => 'none'
-));
-
-$news = Jonah_News::factory();
+Horde_Registry::appInit('jonah', array('authentication' => 'none'));
$channel_id = Horde_Util::getFormData('channel_id');
-$story_id = Horde_Util::getFormData('story_id');
+$story_id = Horde_Util::getFormData('id');
if (!$story_id) {
- $story_id = $news->getLatestStoryId($channel_id);
- if (is_a($story_id, 'PEAR_Error')) {
- $notification->push(sprintf(_("Error fetching story: %s"), $story_id->getMessage()), 'horde.warning');
+ try {
+ $story_id = $injector->getInstance('Jonah_Driver')->getLatestStoryId($channel_id);
+ } catch (Exception $e) {
+ $notification->push(sprintf(_("Error fetching story: %s"), $e->getMessage()), 'horde.warning');
require JONAH_TEMPLATES . '/common-header.inc';
- $notification->notify(array('listeners' => 'status'));
+ require JONAH_TEMPLATES . '/menu.inc';
require $registry->get('templates', 'horde') . '/common-footer.inc';
exit;
}
}
-$story = $news->getStory($channel_id, $story_id, !$browser->isRobot());
-if (is_a($story, 'PEAR_Error')) {
- $notification->push(sprintf(_("Error fetching story: %s"), $story->getMessage()), 'horde.warning');
- require JONAH_TEMPLATES . '/common-header.inc';
- $notification->notify(array('listeners' => 'status'));
- require $registry->get('templates', 'horde') . '/common-footer.inc';
- exit;
-} elseif (empty($story['story_body']) && !empty($story['story_url'])) {
- Horde::externalUrl($story['story_url'])->redirect();
-}
-
-/* Grab tag related content for entire channel */
-$cloud = new Horde_Core_Ui_TagCloud();
-$allTags = $news->listTagInfo(array(), $channel_id);
-foreach ($allTags as $tag_id => $taginfo) {
- $cloud->addElement($taginfo['tag_name'], Horde_Util::addParameter('results.php', array('tag_id' => $tag_id, 'channel_id' => $channel_id)), $taginfo['total']);
-}
-
-/* Prepare the story's tags for display */
-$tag_html = array();
-$tag_link = Horde_Util::addParameter(Horde::url('stories/results.php'), 'channel_id', $channel_id);
-foreach ($story['story_tags'] as $id => $tag) {
- $link = Horde_Util::addParameter($tag_link, 'tag_id', $id);
- $tag_html[] = Horde::link($link) . $tag . '</a>';
-}
-
-/* Filter and prepare story content. */
-$story['story_title'] = htmlspecialchars($story['story_title']);
-$story['story_desc'] = htmlspecialchars($story['story_desc']);
-if (!empty($story['story_body_type']) && $story['story_body_type'] == 'text') {
- $story['story_body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_body'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
-}
-if (!empty($story['story_url'])) {
- $story['story_body'] .= "\n<p>" . Horde::link(Horde::externalUrl($story['story_url'])) . htmlspecialchars($story['story_url']) . '</a></p>';
-}
-if (empty($story['story_published_date'])) {
- $story['story_published_date'] = false;
-}
-
-$story_template = new Horde_Template();
-$story_template->set('story', $story, true);
-$story_template->set('storytags', implode(', ', $tag_html));
-
-$view_template = new Horde_Template();
-$view_template->setOption('gettext', true);
-$view_template->set('story', $story_template->fetch(JONAH_TEMPLATES . '/stories/story.html'));
-$view_template->set('cloud', '<div class="tagSelector" ' . $cloud->buildHTML() . '</div>', true);
-/* Insert link for sharing. */
-if ($conf['sharing']['allow']) {
- $url = Horde::url('stories/share.php');
- $url = Horde_Util::addParameter($url, array('story_id' => $story['story_id'], 'channel_id' => $channel_id));
- $view_template->set('sharelink', Horde::link($url) . _("Share this story") . '</a>', true);
-} else {
- $view_template->set('sharelink', false, true);
-}
-
-/* Insert comments. */
-if ($conf['comments']['allow']) {
- if (!$registry->hasMethod('forums/doComments')) {
- $err = 'User comments are enabled but the forums API is not available.';
- Horde::logMessage($err, 'ERR');
- } else {
- $comments = $registry->call('forums/doComments', array('jonah', $story_id, 'commentCallback'));
- if (is_a($comments, 'PEAR_Error')) {
- Horde::logMessage($threads, 'ERR');
- $comments = '';
- }
- $comments = $comments['threads'] . '<br />' . $comments['comments'];
- $view_template->set('comments', $comments, true);
- }
-} else {
- $view_template->set('comments', false, true);
-}
-
-$view_template->set('menu', Horde::menu());
-
-// Buffer the notifications and send to the template
-Horde::startBuffer();
-$GLOBALS['notification']->notify(array('listeners' => 'status'));
-$template->set('notify', Horde::endBuffer());
-
-require JONAH_TEMPLATES . '/common-header.inc';
-echo $view_template->fetch(JONAH_TEMPLATES . '/stories/view.html');
-require $registry->get('templates', 'horde') . '/common-footer.inc';
+$params = array('registry' => &$registry,
+ 'notification' => &$notification,
+ 'channel_id' => $channel_id,
+ 'browser' => &$browser,
+ 'conf' => &$conf,
+ 'story_id' => $story_id);
+$view = new Jonah_View_StoryView($params);
+$view->run();
\ No newline at end of file
+++ /dev/null
-<tag:menu />
-<tag:notify />
-
-<div class="header">
- <tag:header />
- <a id="quicksearchL" href="#" title="<gettext>Search</gettext>" onclick="$('quicksearchL').hide(); $('quicksearch').show(); $('quicksearchT').focus(); return false;"><tag:search_img /></a>
- <div id="quicksearch" style="display:none">
- <input type="text" name="quicksearchT" id="quicksearchT" for="feeds-body" empty="feeds-empty" />
- <small>
- <a title="<gettext>Close Search</gettext>" href="#" onclick="$('quicksearch').hide(); $('quicksearchT').value = ''; QuickFinder.filter($('quicksearchT')); $('quicksearchL').show(); return false;">X</a>
- </small>
- </div>
-</div>
-
-<if:channels>
-<table id="feeds" width="100%" class="sortable" cellspacing="0">
-<thead>
- <tr>
- <th width="1%"> </th>
- <loop:listheaders>
- <th<tag:listheaders.attrs />>
- <tag:listheaders.label />
- </th>
- </loop:listheaders>
- </tr>
-</thead>
-
-<tbody id="feeds-body">
- <loop:channels>
- <tr>
- <td class="nowrap">
- <tag:channels.edit_link />
- <tag:channels.refresh_link />
- <tag:channels.addstory_link />
- <tag:channels.lists_link />
- <tag:channels.delete_link />
- </td>
- <td>
- <a href="<tag:channels.stories_url />"><tag:channels.channel_name /></a>
- </td>
- <td><tag:channels.channel_type /></td>
- <td class="linedRow"><tag:channels.channel_updated /></td>
- </tr>
- </loop:channels>
-</tbody>
-</table>
-<div id="feeds-empty">
- <gettext>No feeds match</gettext>
-</div>
-<else:channels>
-<div class="text">
- <em><gettext>No channels are available.</gettext></em>
-</div>
-</else:channels>
-</if:channels>
<head>
<?php
-$page_title = $registry->get('name');
+$page_title = $GLOBALS['registry']->get('name');
if (!empty($title)) {
$page_title .= ' :: ' . $title;
}
<pubDate><tag:channel_updated /></pubDate>
<loop:stories>
<item>
- <title><tag:stories.story_title /></title>
- <description><tag:stories.story_desc /></description>
- <link><tag:stories.story_link /></link>
+ <title><tag:stories.title /></title>
+ <description><tag:stories.description /></description>
+ <link><tag:stories.permalink /></link>
</item>
</loop:stories>
</channel>
<generator><tag:jonah /></generator>
<loop:stories>
<item>
- <title><tag:stories.story_title /></title>
- <link><tag:stories.story_link /></link>
- <description><tag:stories.story_desc /></description>
- <pubDate><tag:stories.story_published /></pubDate>
- <guid isPermaLink="true"><tag:stories.story_permalink /></guid>
+ <title><tag:stories.title /></title>
+ <link><tag:stories.permalink /></link>
+ <description><tag:stories.description /></description>
+ <pubDate><tag:stories.published /></pubDate>
+ <guid isPermaLink="true"><tag:stories.permalink /></guid>
</item>
</loop:stories>
</channel>
<generator><tag:jonah /></generator>
<loop:stories>
<item>
- <title><tag:stories.story_title /></title>
- <link><tag:stories.story_link /></link>
- <description><tag:stories.story_desc /></description>
- <content:encoded><![CDATA[<tag:stories.story_body />
+ <title><tag:stories.title /></title>
+ <link><tag:stories.permalink /></link>
+ <description><tag:stories.description /></description>
+ <content:encoded><![CDATA[<tag:stories.body />
]]></content:encoded>
<pubDate><tag:stories.story_published /></pubDate>
- <guid isPermaLink="true"><tag:stories.story_permalink /></guid>
+ <guid isPermaLink="true"><tag:stories.permalink /></guid>
</item>
</loop:stories>
</channel>
<pubDate><tag:channel_updated /></pubDate>
<loop:stories>
<item>
- <title><tag:stories.story_title /></title>
- <description><tag:stories.story_desc /></description>
- <content:encoded><![CDATA[<tag:stories.story_body />
+ <title><tag:stories.title /></title>
+ <description><tag:stories.description /></description>
+ <content:encoded><![CDATA[<tag:stories.body />
]]></content:encoded>
- <link><tag:stories.story_link /></link>
+ <link><tag:stories.permalink /></link>
</item>
</loop:stories>
</channel>
--- /dev/null
+<?php echo Horde::menu();
+$GLOBALS['notification']->notify(array('listeners' => 'status'));
\ No newline at end of file
+++ /dev/null
-<tag:menu />
-<tag:notify />
-
-<div class="header">
- <tag:header /> <tag:refresh />
-</div>
-
-<if:stories>
-<table width="100%" cellspacing="0" class="linedRow nowrap">
- <tr class="item">
- <th width="1%"> </th>
- <loop:listheaders>
- <th class="leftAlign">
- <tag:listheaders />
- </th>
- </loop:listheaders>
- <if:read>
- <th class="leftAlign">
- <gettext>Read</gettext>
- </th>
- </if:read>
- <if:comments>
- <th class="leftAlign">
- <gettext>Comments</gettext>
- </th>
- </if:comments>
- </tr>
-
- <loop:stories>
- <tr>
- <td>
- <tag:stories.pdf_link />
- <tag:stories.edit_link />
- <tag:stories.delete_link />
- </td>
- <td>
- <tag:stories.view_link />
- </td>
- <td>
- <tag:stories.story_published_date />
- </td>
- <if:read>
- <td>
- <tag:stories.story_read />
- </td>
- </if:read>
- <if:comments>
- <td>
- <tag:stories.comments />
- </td>
- </if:comments>
- </tr>
- </loop:stories>
-</table>
-</if:stories>
--- /dev/null
+<?php
+/**
+ * Template for stories index page - lists available stories
+ *
+ * ->stories
+ * ->read
+ * ->comments
+ * ->stories
+ */
+?>
+<?php if (!empty($this->stories)): ?>
+<table width="100%" cellspacing="0" class="linedRow nowrap">
+ <tr class="item">
+ <th width="1%"> </th>
+ <th class="leftAlign"><?php echo _("Story") ?></th>
+ <th class="leftAlign"><?php echo _("Date") ?></th>
+ <?php if ($this->read): ?>
+ <th class="leftAlign"><?php echo _("Read") ?></th>
+ <?php endif; ?>
+ <?php if ($this->comments): ?>
+ <th class="leftAlign"><?php echo _("Comments") ?></th>
+ <?php endif; ?>
+ </tr>
+ <?php foreach ($this->stories as $story): ?>
+ <tr>
+ <td>
+ <?php echo $story['pdf_link'] ?>
+ <?php echo $story['edit_link'] ?>
+ <?php echo $story['delete_link'] ?>
+ </td>
+ <td>
+ <?php echo $story['view_link'] ?>
+ </td>
+ <td>
+ <?php echo $story['published_date'] ?>
+ </td>
+ <?php if ($this->read): ?>
+ <td>
+ <?php echo $story['readcount'] ?>
+ </td>
+ <?php endif; ?>
+ <?php if ($this->comments): ?>
+ <td>
+ <?php echo $story['comments'] ?>
+ </td>
+ <?php endif; ?>
+ </tr>
+ <?php endforeach; ?>
+</table>
+<?php endif; ?>
--- /dev/null
+<?php
+/**
+ * Main layout for viewing story entries
+ * Expects:
+ * ->tagcloud
+ * ->story
+ * ->sharelink
+ * ->comments
+ */
+?>
+<?php if (!empty($this->tagcloud)): ?>
+<?php echo $this->contentTag('div', $this->contentDiv('div', $this->tagcloud, array('class' => 'tagSelector')), array('style' => 'float:right;'));?>
+<div style="margin-right:170px;">
+<?php else:?>
+<div>
+<?php endif;?>
+ <?php echo $this->renderPartial('story', array('local' => array('story' => $this->story))); ?>
+ <?php echo $this->contentTag('div', (!empty($this->sharelink) ? $this->sharelink : ''), array('class' => 'storyLinks'));?>
+</div>
+<?php
+ if (!empty($this->comments)) {
+ echo $this->contentTag('div', $this->comments['threads'] . $this->tag('br') . $this->comments['comments'], array('class' => 'storyComments'));
+ }
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Default template for rendering individual stories.
+ * Expects:
+ * ->published_date
+ * ->title
+ * ->tags
+ * ->description
+ * ->body
+ */
+
+echo $this->contentTag('h1',
+ $this->contentTag('span',
+ $this->story['published_date'],
+ array('class' => 'storyDate')) . $this->escape($this->story['title']),
+ array('class' => 'header'));
+
+echo $this->contentTag('div', _("Tags:") . implode(', ', $this->story['tags']), array('class' => 'storyTags'));
+echo $this->contentTag('div', $this->escape($this->story['description']), array('class' => 'storySubtitle'));
+// body is already escaped in the View class.
+echo $this->contentTag('div', $this->story['body'], array('class' => 'storyBody'));
+?>
+++ /dev/null
-<h1 class="header">
- <span class="storyDate"><tag:story.story_published_date /></span> <tag:story.story_title />
-</h1>
-
-<p class="storyTags">
- <gettext>Tags: </gettext><tag:storytags />
-</p>
-
-<p class="storySubtitle">
- <tag:story.story_desc />
-</p>
-
-<div class="storyBody">
- <tag:story.story_body />
-</div>
+++ /dev/null
-<tag:menu />
-<tag:notify />
-
-<if:cloud>
- <div style="float:right;"><tag:cloud /></div>
- <div style="margin-right:170px;">
-<else:cloud>
- <div>
-</else:cloud>
-</if:cloud>
-<tag:story />
-<div class="storyLinks">
-<if:sharelink>
- <tag:sharelink />
-</if:sharelink>
-</div>
-
-</div>
-<if:comments>
-<div class="storyComments">
-<tag:comments />
-</div>
-</if:comments>
--- /dev/null
+<?php
+/**
+ * index view for rendering channel list. Expects:
+ * ->search_img
+ * ->channels
+ *
+ *
+ */
+?>
+<div class="header">
+ <?php echo _("Manage Feeds") ?>
+ <a id="quicksearchL" href="#" title="<?php echo _("Search")?>" onclick="$('quicksearchL').hide(); $('quicksearch').show(); $('quicksearchT').focus(); return false;"><?php echo $this->search_img?></a>
+ <div id="quicksearch" style="display:none;">
+ <input type="text" name="quicksearchT" id="quicksearchT" for="feeds-body" empty="feeds-empty" />
+ <small>
+ <a title="<?php echo _("Close Search")?>" href="#" onclick="$('quicksearch').hide(); $('quicksearchT').value = ''; QuickFinder.filter($('quicksearchT')); $('quicksearchL').show(); return false;">X</a>
+ </small>
+ </div>
+</div>
+
+<?php if (count($this->channels)):?>
+ <table id="feeds" width="100%" class="sortable" cellspacing="0">
+ <thead>
+ <tr>
+ <th width="1%"> </th>
+ <th class="sortdown"><?php echo _("Name")?></th>
+ <th><?php echo _("Type")?></th>
+ <th><?php echo _("Last Update")?></th>
+ </tr>
+ </thead>
+
+ <tbody id="feeds-body">
+ <?php foreach ($this->channels as $channel):?>
+ <tr>
+ <td class="nowrap">
+ <?php echo $channel['edit_link'] . $channel['refresh_link'] . $channel['addstory_link'] . $channel['delete_link'];?>
+ </td>
+ <td>
+ <a href="<?php echo $channel['stories_url']?>"><?php echo $channel['channel_name']?></a>
+ </td>
+ <td><?php echo $channel['channel_type']?></td>
+ <td class="linedRow"><?php echo $channel['channel_updated']?></td>
+ </tr>
+ <?php endforeach?>
+ </tbody>
+ </table>
+ <div id="feeds-empty">
+ <?php echo _("No feeds match")?>
+ </div>
+<?php else:?>
+ <div class="text">
+ <em><?php echo _("No channels are available.")?></em>
+ </div>
+<?php endif;?>
\ No newline at end of file