From 8988426ac8ce043815f1426e480977b804474c47 Mon Sep 17 00:00:00 2001 From: "Michael J. Rubinsky" Date: Wed, 15 Sep 2010 10:52:00 -0400 Subject: [PATCH] remove unused files --- jonah/lib/News.php | 827 ----------------------------------------------- jonah/lib/News/sql.php | 858 ------------------------------------------------- 2 files changed, 1685 deletions(-) delete mode 100644 jonah/lib/News.php delete mode 100644 jonah/lib/News/sql.php diff --git a/jonah/lib/News.php b/jonah/lib/News.php deleted file mode 100644 index 75cb48f18..000000000 --- a/jonah/lib/News.php +++ /dev/null @@ -1,827 +0,0 @@ - - * @author Marko Djukic - * @author Jan Schneider - * @package Jonah - */ -class Jonah_News -{ - /** - * Hash containing connection parameters. - * - * @var array - */ - protected $_params = array(); - - /** - * Constructs a new News storage object. - * - * @param array $params A hash containing connection parameters. - */ - public function __construct($params = array()) - { - $this->_params = $params; - } - - /** - */ - function deleteChannel(&$info) - { - return $this->_deleteChannel($info['channel_id']); - } - - /** - * Fetches the requested channel, while actually passing on the request to - * the backend _getChannel() function to do the real work. - * - * @param integer $channel_id The channel id to fetch. - * - * @return array|PEAR_Error The channel details as an array or a - * PEAR_Error if not valid or not found. - */ - function getChannel($channel_id) - { - static $channel = array(); - - /* We need a non empty channel id. */ - if (empty($channel_id)) { - return PEAR::raiseError(_("Missing channel id.")); - } - - /* Cache the fetching of channels. */ - if (!isset($channel[$channel_id])) { - $channel[$channel_id] = $this->_getChannel($channel_id); - if (!is_a($channel[$channel_id], 'PEAR_Error')) { - if (empty($channel[$channel_id]['channel_link'])) { - $channel[$channel_id]['channel_official'] = Horde_Util::addParameter(Horde::url('delivery/html.php', true, -1), 'channel_id', $channel_id, false); - } else { - $channel[$channel_id]['channel_official'] = str_replace(array('%25c', '%c'), array('%c', $channel_id), $channel[$channel_id]['channel_link']); - } - } - } - - return $channel[$channel_id]; - } - - /** - * Checks if the channel is editable by first checking if the $channel_id - * returns a valid channel array and then whether the channel type is - * Jonah::INTERNAL_CHANNEL, which is the only one to allow stories to be - * added. - * - * @param integer $channel_id The channel id to check. - * - * @return array|PEAR_Error The channel details as an array or a - * PEAR_Error if not editable. - */ - function isChannelEditable($channel_id) - { - /* Check if this channel id returns a valid channel. */ - $channel = $this->getChannel($channel_id); - if (is_a($channel, 'PEAR_Error')) { - return $channel; - } - - /* Check if the channel type allows adding of stories. */ - if ($channel['channel_type'] != Jonah::INTERNAL_CHANNEL) { - return PEAR::raiseError(sprintf(_("Feed \"%s\" is not authored on this system."), $channel['channel_name'])); - } - - return $channel; - } - - /** - * Returns the most recent or all stories from a channel. - * - * @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. - */ - function getStories($channel_id, $max = 10, $from = 0, $refresh = false, - $date = null, $unreleased = false, - $order = Jonah::ORDER_PUBLISHED) - { - $channel = $this->getChannel($channel_id); - if (is_a($channel, 'PEAR_Error')) { - Horde::logMessage($channel, 'ERR'); - return array(); - } - - /* Fetch the stories according to channel type, using a - * template method pattern for each type. */ - $funcs = array( - Jonah::INTERNAL_CHANNEL => '_getInternalStories', - Jonah::EXTERNAL_CHANNEL => '_getExternalStories', - Jonah::AGGREGATED_CHANNEL => '_getAggregatedStories', - Jonah::COMPOSITE_CHANNEL => '_getCompositeStories', - ); - - $func = $funcs[$channel['channel_type']]; - return $this->$func($channel, $max, $from, $refresh, $date, $unreleased, $order); - } - - /** - */ - function _getInternalStories($channel, $max = 10, $from = 0, $refresh = false, - $date = null, $unreleased = false, - $order = Jonah::ORDER_PUBLISHED) - { - return $GLOBALS['injector']->getInstance('Jonah_Driver')->legacyGetStories($channel, $max, $from, $refresh, $date, $unreleased, $order); - } - - /** - */ - function _getExternalStories($channel, $max = 10, $from = 0, $refresh = false, - $date = null, $unreleased = false, - $order = Jonah::ORDER_PUBLISHED) - { - if ($refresh) { - $channel['channel_interval'] = -1; - } - $stories = $this->fetchExternalStories($channel['channel_id'], $channel['channel_url'], $channel['channel_interval']); - array_walk($stories, array($this, '_escapeExternalStories'), $channel); - if (!is_null($max)) { - $stories = array_slice($stories, $from, $max); - } - return $stories; - } - - /** - */ - function _escapeExternalStories(&$story, $key, $channel) - { - $story = array_merge($channel, $story); - $story['story_link'] = Horde::externalUrl($story['story_url']); - } - - /** - */ - function _getAggregatedStories($channel, $max = 10, $from = 0, $refresh = false, - $date = null, $unreleased = false, - $order = Jonah::ORDER_PUBLISHED) - { - switch ($order) { - case Jonah::ORDER_PUBLISHED: - $sort = 'story_published'; - break; - - case Jonah::ORDER_READ: - $sort = 'story_read'; - break; - - case Jonah::ORDER_COMMENTS: - //@TODO - break; - } - - if ($refresh) { - $channel['channel_interval'] = -1; - } - - $stories = array(); - $date_format = $GLOBALS['prefs']->getValue('date_format'); - $channels = explode(':', $channel['channel_url']); - foreach ($channels as $id) { - $channel_data = $this->getChannel($id); - if (is_a($channel_data, 'PEAR_Error')) { - continue; - } - $externals = $this->fetchExternalStories(null, $channel_data['channel_url'], $channel['channel_interval']); - if (!is_array($externals)) { - continue; - } - - foreach ($externals as $external) { - $info = array(); - - /* Check if we have seen this story already. */ - $story = $this->_getStoryByUrl($channel['channel_id'], $external['story_url']); - if (is_array($story)) { - /* Check if the story is unchanged. */ - if ($this->getChecksum($story) == $this->getChecksum($external)) { - $story['story_updated_date'] = strftime($date_format, $story['story_updated']); - $story['story_link'] = Horde::externalUrl($story['story_url']); - $stories[] = array_merge($channel_data, $story); - continue; - } - - $info['story_id'] = $story['story_id']; - } - - $info['channel_id'] = $channel['channel_id']; - $info['story_title'] = $external['story_title']; - $info['story_desc'] = $external['story_desc']; - $info['story_url'] = $external['story_url']; - $info['story_link'] = Horde::externalUrl($external['story_url']); - $info['story_body'] = isset($external['story_body']) ? $external['story_body'] : null; - $info['story_body_type'] = isset($external['story_body_type']) ? $external['story_body_type'] : 'text'; - $info['story_published'] = $external['story_published']; - $info['story_updated'] = $external['story_updated']; - - $this->saveStory($info); - - $info['story_updated_date'] = strftime($date_format, $external['story_updated']); - $stories[] = array_merge($channel_data, $info); - } - } - - Horde_Array::arraySort($stories, $sort, 1); - if (!is_null($max)) { - $stories = array_slice($stories, $from, $max); - } - - return $stories; - } - - /** - */ - function _getCompositeStories($channel, $max = 10, $from = 0, $refresh = false, - $date = null, $unreleased = false, - $order = Jonah::ORDER_PUBLISHED) - { - switch ($order) { - case Jonah::ORDER_PUBLISHED: - $sort = 'story_published'; - break; - - case Jonah::ORDER_READ: - $sort = 'story_read'; - break; - - case Jonah::ORDER_COMMENTS: - //@TODO - break; - } - - $stories = array(); - $channels = explode(':', $channel['channel_url']); - foreach ($channels as $subchannel) { - $stories = array_merge($stories, $this->getStories($subchannel, null, 0, $refresh, $date)); - } - foreach ($stories as $key => $story) { - $stories[$key]['story_link'] = $this->getStoryLink($channel, $story); - } - Horde_Array::arraySort($stories, $sort, 1); - if (!is_null($max)) { - $stories = array_slice($stories, $from, $max); - } - return $stories; - } - - /** - */ - 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; - } - } - - /* First save to the backend. */ - $result = $this->_saveStory($info); - if (is_a($result, 'PEAR_Error') || !$deliver) { - /* Return here also if editing, do not bother doing deliveries for - * an edited story. */ - return $result; - } - } - - /** - */ - function getStory($channel_id, $story_id, $read = false) - { - $channel = null; - if ($channel_id) { - $channel = $this->getChannel($channel_id); - if (is_a($channel, 'PEAR_Error')) { - return $channel; - } - if ($channel['channel_type'] == Jonah::EXTERNAL_CHANNEL) { - return $this->_getExternalStory($channel, $story_id); - } - } - - $story = $this->_getStory($story_id, $read); - if (is_a($story, 'PEAR_Error')) { - return $story; - } - - /* Format story link. */ - $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']); - } - - return $story; - } - - /** - * Returns the official link to a story. - * - * @param array $channel A channel hash. - * @param array $story A story hash. - * - * @return string The story link. - */ - function getStoryLink($channel, $story) - { - if ((empty($story['story_url']) || !empty($story['story_body'])) && - !empty($channel['channel_story_url'])) { - $url = $channel['channel_story_url']; - } else { - $url = Horde_Util::addParameter(Horde::url('stories/view.php', true, -1), array('channel_id' => '%c', 'story_id' => '%s'), null, false); - } - return str_replace(array('%25c', '%25s', '%c', '%s'), - array('%c', '%s', $channel['channel_id'], $story['story_id']), - $url); - } - - /** - */ - function getChecksum($story) - { - return md5($story['story_title'] . $story['story_desc']); - } - - /** - * Fetches a story list from an external channel, caching the data - * and only actually fetching if there is no valid cache. - * - * @param integer $channel_id The channel id to fetch. - * @param string $url The url from where to fetch the story list. - * @param integer $interval The interval in seconds since the last fetch - * after which the cache will be considered - * expired and an actual fetch will be done. - * - * @return array An array of available stories. - */ - function fetchExternalStories($channel_id, $url, $interval) - { - $cache = $GLOBALS['injector']->getInstance('Horde_Cache'); - $timestamp = time(); - if (is_a($cache, 'Horde_Cache') && ($stories = $cache->get($url, $interval))) { - $stories = Horde_Serialize::unserialize($stories, Horde_Serialize::UTF7_BASIC, $GLOBALS['registry']->getCharset()); - } else { - $stories = Jonah_News::_fetchExternalStories($url, $timestamp); - $cache->set($url, Horde_Serialize::serialize($stories, Horde_Serialize::UTF7_BASIC, $GLOBALS['registry']->getCharset())); - } - - /* If the stories from cache return the same timestamp as - * $timestamp it means that the cache has been refreshed. */ - if ($channel_id !== null) { - if ($stories['timestamp'] == $timestamp) { - $this->_timestampChannel($channel_id, $timestamp); - } - } - - unset($stories['timestamp']); - return $stories; - } - - /** - */ - function getIntervalLabel($seconds = null) - { - $interval = array(1 => _("none"), - 1800 => _("30 mins"), - 3600 => _("1 hour"), - 7200 => _("2 hours"), - 14400 => _("4 hours"), - 28800 => _("8 hours"), - 43200 => _("12 hours"), - 86400 => _("24 hours")); - - if ($seconds === null) { - return $interval; - } else { - return $interval[$seconds]; - } - } - - /** - * Returns the available channel types based on what was set in the - * configuration. - * - * @return array The available news channel types. - */ - function getAvailableTypes() - { - if (isset($types)) { - return $types; - } - - static $types = array(); - - if (empty($GLOBALS['conf']['news']['enable'])) { - return $types; - } - if (in_array('external', $GLOBALS['conf']['news']['enable'])) { - $types[Jonah::EXTERNAL_CHANNEL] = _("External Feed"); - } - if (in_array('internal', $GLOBALS['conf']['news']['enable'])) { - $types[Jonah::INTERNAL_CHANNEL] = _("Local Feed"); - } - if (in_array('aggregated', $GLOBALS['conf']['news']['enable'])) { - $types[Jonah::AGGREGATED_CHANNEL] = _("Aggregated Feed"); - } - if (in_array('composite', $GLOBALS['conf']['news']['enable'])) { - $types[Jonah::COMPOSITE_CHANNEL] = _("Composite Feed"); - } - - return $types; - } - - /** - * Returns the default channel type based on what was set in the - * configuration. - * - * @return integer The default news channel type. - */ - function getDefaultType() - { - if (in_array('external', $GLOBALS['conf']['news']['enable'])) { - return Jonah::EXTERNAL_CHANNEL; - } else { - return Jonah::INTERNAL_CHANNEL; - } - } - - /** - * Returns the stories of a channel rendered with the specified template. - * - * @param integer $channel_id The news channel to get stories from. - * @param string $tpl The name of the template to use. - * @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 integer $order How to sort the results for internal channels - * Possible values are the Jonah::ORDER_* - * constants. - * - * @return string The rendered story listing. - */ - 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']); - $template = new Horde_Template(); - - if ($escape) { - $channel['channel_name'] = htmlspecialchars($channel['channel_name']); - $channel['channel_desc'] = htmlspecialchars($channel['channel_desc']); - } - $template->set('channel', $channel, true); - - /* 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(); - } - } else { - $stories = $this->getStories($channel_id, null, 0, false, time(), false, $order); - if (is_a($stories, 'PEAR_Error')) { - return $stories->getMessage(); - } - $max = count($stories); - } - - if (!$stories) { - $template->set('error', _("No stories are currently available."), true); - $template->set('stories', false, true); - $template->set('image', false, true); - $template->set('form', false, true); - } else { - /* Escape. */ - if ($escape) { - array_walk($stories, array($this, '_escapeStories')); - } - - /* Process story summaries. */ - array_walk($stories, array($this, '_escapeStoryDescriptions')); - - $template->set('error', false, true); - $template->set('story_marker', Horde::img('story_marker.png')); - $template->set('image', false, true); - $template->set('form', false, true); - if ($from) { - $template->set('previous', max(0, $from - $max), true); - } else { - $template->set('previous', false, true); - } - if ($from && !empty($channel['channel_page_link'])) { - $template->set('previous_link', - str_replace( - array('%25c', '%25n', '%c', '%n'), - array('%c', '%n', $channel['channel_id'], max(0, $from - $max)), - $channel['channel_page_link']), - true); - } else { - $template->set('previous_link', false, true); - } - $more = count($stories) > $max; - if ($more) { - $template->set('next', $from + $max, true); - array_pop($stories); - } else { - $template->set('next', false, true); - } - if ($more && !empty($channel['channel_page_link'])) { - $template->set('next_link', - str_replace( - array('%25c', '%25n', '%c', '%n'), - array('%c', '%n', $channel['channel_id'], $from + $max), - $channel['channel_page_link']), - true); - } else { - $template->set('next_link', false, true); - } - - $template->set('stories', $stories, true); - } - - return $template->parse($templates[$tpl]['template']); - } - - /** - */ - 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']); - } - if (empty($value['story_body_type']) || $value['story_body_type'] != 'richtext') { - $value['story_body'] = htmlspecialchars($value['story_body']); - } - } - - /** - */ - function _escapeStoryDescriptions(&$value, $key) - { - $value['story_desc'] = nl2br($value['story_desc']); - } - - /** - * Returns the provided story as a MIME part. - * - * @param array $story A data array representing a story. - * - * @return MIME_Part The MIME message part containing the story parts. - */ - function &getStoryAsMessage(&$story) - { - require_once 'Horde/MIME/Part.php'; - - /* Add the story to the message based on the story's body type. */ - switch ($story['story_body_type']) { - case 'richtext': - /* Get a plain text version of a richtext story. */ - $body_html = $story['story_body']; - $body_text = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($body_html, 'html2text'); - - /* Add description. */ - $body_html = '

' . $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($story['story_desc'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO, 'callback' => null)) . "

\n" . $body_html; - $body_text = Horde_String::wrap(' ' . $story['story_desc'], 70) . "\n\n" . $body_text; - - /* Add the text version of the story to the base message. */ - $message_text = new MIME_Part('text/plain'); - $message_text->setCharset($GLOBALS['registry']->getCharset()); - $message_text->setContents($message_text->replaceEOL($body_text)); - $message_text->setDescription(_("Plaintext Version of Story")); - - /* Add an HTML version of the story to the base message. */ - $message_html = new MIME_Part('text/html', Horde_String::wrap($body_html), - $GLOBALS['registry']->getCharset(), 'inline'); - $message_html->setDescription(_("HTML Version of Story")); - - /* Add the two parts as multipart/alternative. */ - $basepart = new MIME_Part('multipart/alternative'); - $basepart->addPart($message_text); - $basepart->addPart($message_html); - - return $basepart; - - 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->setCharset($GLOBALS['registry']->getCharset()); - - return $message_text; - } - } - - /** - * Attempts to return a concrete Jonah_News instance based on $driver. - * - * @param string $driver The type of concrete Jonah_News subclass to - * return. The is based on the storage driver - * ($driver). The code is dynamically included. - * - * @param array $params A hash containing any additional configuration or - * connection parameters a subclass might need. - * - * @return mixed The newly created concrete Jonah_News instance, or false - * on an error. - */ - function factory($driver = null, $params = null) - { - if ($driver === null) { - $driver = $GLOBALS['conf']['news']['storage']['driver']; - } - $driver = basename($driver); - - if ($params === null) { - $params = Horde::getDriverConfig(array('news', 'storage'), $driver); - } - - $class = 'Jonah_News_' . $driver; - if (!class_exists($class, false)) { - include dirname(__FILE__) . '/News/' . $driver . '.php'; - } - if (class_exists($class)) { - return new $class($params); - } else { - return PEAR::raiseError(sprintf(_("No such backend \"%s\" found"), $driver)); - } - } - - /** - * Get the full body of an external feed story. - * - * @access private - * - * @param array $channel The channel the story belongs to. - * @param integer $story_id The id of the story in the channel. - * - * @return array The story array. - */ - function _getExternalStory($channel, $story_id) - { - $stories = $this->fetchExternalStories($channel['channel_id'], $channel['channel_url'], $channel['channel_interval']); - if (isset($stories[$story_id])) { - return $stories[$story_id]; - } - - return PEAR::raiseError(sprintf(_("Story \"%s\" not found in \"%s\"."), $story_id, $channel['channel_title'])); - } - - /** - * This function is called if cached data isn't available and is what - * actually does the URL fetching and XML parsing to get the story list. - * It is only called if the cached data has expired or didn't exist. - * - * @access private - * - * @param string $url The url from where to fetch the story list. - * @param integer $timestamp Timestamp of this fetch. - * - * @return array An array of available stories. - */ - function _fetchExternalStories($url, $timestamp) - { - try { - $xml = Jonah::readURL($url); - } catch (Jonah_Exception $e) { - Horde::logMessage($e, 'ERR'); - return array('timestamp' => $timestamp); - } - - /* Parse the feed. */ - $charset = empty($xml['charset']) ? 'utf-8' : $xml['charset']; - $parser = new Jonah_FeedParser($charset); - if (!$parser->parse($xml['body'])) { - if (isset($GLOBALS['notification'])) { - $GLOBALS['notification']->push(sprintf(_("Error parsing external feed from %s: %s"), $url, $parser->error), 'warning'); - } else { - Horde::logMessage(sprintf("Error parsing external feed from %s: %s", $url, $parser->error), 'ERR'); - } - } - $stories = $parser->structure; - $parser->cleanup(); - - /* Set the passed timestamp. */ - $items = array('timestamp' => $timestamp); - if (!empty($stories['items'])) { - foreach ($stories['items'] as $key => $story) { - $items[$key]['story_id'] = $key; - $items[$key]['story_title'] = isset($story['title']) ? Horde_String::convertCharset($story['title'], 'utf-8') : _("[No title]"); - $items[$key]['story_desc'] = isset($story['description']) ? Horde_String::convertCharset($story['description'], 'utf-8') : ''; - $items[$key]['story_url'] = isset($story['link']) ? $story['link'] : ''; - - /* Set the body, and filter it if it's HTML */ - $items[$key]['story_body'] = isset($story['body']) ? Horde_String::convertCharset($story['body'], 'utf-8') : null; - $items[$key]['story_body_type'] = isset($story['body_type']) ? Horde_String::convertCharset($story['body_type'], 'utf-8') : 'text'; - if ($items[$key]['story_body_type'] == 'html') { - $items[$key]['story_body'] = $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($items[$key]['story_body'], 'xss'); - } - - if (isset($story['pubdate']) && $pubdate_dt = strtotime($story['pubdate'])) { - $items[$key]['story_published'] = $pubdate_dt; - } else { - $items[$key]['story_published'] = $timestamp; - } - - if (isset($story['moddate']) && $moddate_dt = strtotime($story['moddate'])) { - $items[$key]['story_updated'] = $moddate_dt; - } else { - $items[$key]['story_updated'] = $timestamp; - } - - // Media related - if (isset($story['media:content']) && is_array($story['media:content'])) { - $items[$key]['story_media_content_url'] = $story['media:content']['url']; - $items[$key]['story_media_content_type'] = empty($story['media:content']['type']) ? null : $story['media:content']['type']; - $items[$key]['story_media_title'] = isset($story['media:title']) ? $story['media:title'] : ''; - $items[$key]['story_media_description'] = isset($story['media:description']['value']) ? $story['media:description']['value'] : ''; - $items[$key]['story_media_description_type'] = isset($story['media:description']['type']) ? $story['media:description']['type'] : ''; - $items[$key]['story_media_thumbnail_url'] = (isset($story['media:thumbnail']['url']) ? $story['media:thumbnail']['url'] : (isset($story['media:content']['url']) ? $story['media:content']['url'] : '')); - } - } - } - - return $items; - } - - /** - * Stubs for the tag functions. If supported by the backend, these need - * to be implemented in the concrete Jonah_News_* class. - */ - function writeTags($resource_id, $channel_id, $tags) - { - return PEAR::raiseError(_("Tag support not enabled in backend.")); - } - - function readTags($resource_id) - { - return PEAR::raiseError(_("Tag support not enabled in backend.")); - } - - function listTagInfo($tags = array(), $channel_id = null) - { - return PEAR::raiseError(_("Tag support not enabled in backend.")); - } - - function searchTagsById($ids, $max = 10, $from = 0, $channel_id = array(), - $order = Jonah::ORDER_PUBLISHED) - { - return PEAR::raiseError(_("Tag support not enabled in backend.")); - } - - function getTagNames($ids) - { - return PEAR::raiseError(_("Tag support not enabled in backend.")); - } - - -} diff --git a/jonah/lib/News/sql.php b/jonah/lib/News/sql.php deleted file mode 100644 index a762e18da..000000000 --- a/jonah/lib/News/sql.php +++ /dev/null @@ -1,858 +0,0 @@ - - * @author Chuck Hagenbuch - * @author Jan Schneider - * @package Jonah - */ -class Jonah_News_sql extends Jonah_News { - - /** - * Handle for the current database connection. - * - * @var DB - */ - var $_db; - - /** - * Boolean indicating whether or not we're connected to the SQL server. - * - * @var boolean - */ - var $_connected = false; - - /** - * Saves a channel to the backend. - * - * @param array $info The channel to add. - * Must contain a combination of the following - * entries: - *
-     * 'channel_id'       If empty a new channel is being added, otherwise one
-     *                    is being edited.
-     * 'channel_name'     The headline.
-     * 'channel_desc'     A description of this channel.
-     * 'channel_type'     Whether internal or external.
-     * 'channel_interval' If external then interval at which to refresh.
-     * 'channel_link'     The link to the source.
-     * 'channel_url'      The url from where to fetch the story list.
-     * 'channel_image'    A channel image.
-     * 
- * - * @return int|PEAR_Error The channel ID on success, PEAR_Error on - * failure. - */ - 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')) { - Horde::logMessage($info['channel_id'], 'ERR'); - return $info['channel_id']; - } - $sql = 'INSERT INTO jonah_channels' . - ' (channel_id, channel_name, channel_slug, channel_type, channel_full_feed, channel_desc, channel_interval, channel_url, channel_link, channel_page_link, channel_story_url, channel_img)' . - ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; - $values = array(); - } else { - $sql = 'UPDATE jonah_channels' . - ' SET channel_id = ?, channel_name = ?, channel_slug = ?, channel_type = ?, channel_full_feed = ?, channel_desc = ?, channel_interval = ?, channel_url = ?, channel_link = ?, channel_page_link = ?, channel_story_url = ?, channel_img = ?' . - ' WHERE channel_id = ?'; - $values = array((int)$info['channel_id']); - } - - array_unshift($values, - (int)$info['channel_id'], - Horde_String::convertCharset($info['channel_name'], $GLOBALS['registry']->getCharset(), $this->_params['charset']), - isset($info['channel_slug']) ? $info['channel_slug'] : '', - (int)$info['channel_type'], - (int)$info['channel_full_feed'], - isset($info['channel_desc']) ? $info['channel_desc'] : null, - isset($info['channel_interval']) ? (int)$info['channel_interval'] : null, - isset($info['channel_url']) ? $info['channel_url'] : null, - isset($info['channel_link']) ? $info['channel_link'] : null, - isset($info['channel_page_link']) ? $info['channel_page_link'] : null, - isset($info['channel_story_url']) ? $info['channel_story_url'] : null, - isset($info['channel_img']) ? $info['channel_img'] : null); - Horde::logMessage('SQL Query by Jonah_News_sql::saveChannel(): ' . $sql, 'DEBUG'); - $result = $this->_db->query($sql, $values); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, 'ERR'); - return $result; - } - - return $info['channel_id']; - } - - /** - * 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. - */ - function getChannels($type = null) - { - if (is_a(($result = $this->_connect()), 'PEAR_Error')) { - return $result; - } - - $wsql = ''; - if (!is_null($type)) { - if (!is_array($type)) { - $type = array($type); - } - for ($i = 0, $i_max = count($type); $i < $i_max; ++$i) { - $type[$i] = 'channel_type = ' . (int)$type[$i]; - } - $wsql = 'WHERE ' . implode(' OR ', $type); - } - - $sql = sprintf('SELECT channel_id, channel_name, channel_type, channel_updated FROM jonah_channels %s ORDER BY channel_name', $wsql); - - Horde::logMessage('SQL Query by Jonah_News_sql::getChannels(): ' . $sql, 'DEBUG'); - $result = $this->_db->getAll($sql, DB_FETCHMODE_ASSOC); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, 'ERR'); - return $result; - } - for ($i = 0; $i < count($result); $i++) { - $result[$i]['channel_name'] = Horde_String::convertCharset($result[$i]['channel_name'], $this->_params['charset']); - } - - return $result; - } - - /** - */ - 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_News_sql::_getChannel(): ' . $sql, 'DEBUG'); - $result = $this->_db->getRow($sql, DB_FETCHMODE_ASSOC); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, 'ERR'); - return $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_News_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); - } - } - } - - return $result; - } - - /** - */ - 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_News_sql::_timestampChannel(): ' . $sql, 'DEBUG'); - $result = $this->_db->query($sql); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, 'ERR'); - } - return $result; - } - - /** - */ - 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_News_sql::_readStory(): ' . $sql, 'DEBUG'); - $result = $this->_db->query($sql); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, 'ERR'); - } - return $result; - } - - /** - */ - 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_News_sql::deleteChannel(): ' . $sql, 'DEBUG'); - $result = $this->_db->query($sql, $values); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, 'ERR'); - } - - return $result; - } - - /** - * @param array &$info - */ - 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']; - } - $channel = $this->getChannel($info['channel_id']); - $permalink = $this->getStoryLink($channel, $info); - $sql = 'INSERT INTO jonah_stories (story_id, channel_id, story_title, story_desc, story_body_type, story_body, story_url, story_published, story_updated, story_read, story_permalink, story_author) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; - $values = array($permalink, $GLOBALS['registry']->getAuth()); - } 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']); - } - - if (empty($info['story_read'])) { - $info['story_read'] = 0; - } - - /* Deal with any tags */ - if (!empty($info['story_tags'])) { - $tags = explode(',', $info['story_tags']); - } else { - $tags = array(); - } - $this->writeTags($info['story_id'], $info['channel_id'], $tags); - - array_unshift($values, - (int)$info['story_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, - time(), - (int)$info['story_read']); - - Horde::logMessage('SQL Query by Jonah_News_sql::_saveStory(): ' . $sql, 'DEBUG'); - $result = $this->_db->query($sql, $values); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, 'ERR'); - return $result; - } - - $this->_timestampChannel($info['channel_id'], time()); - return true; - } - - /** - * Converts the text fields of a story from the backend charset to the - * output charset. - * - * @param array $story A story hash. - * - * @return array The converted hash. - */ - 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()); - } - if (isset($story['story_tags'])) { - $story['story_tags'] = Horde_String::convertCharset($story['story_tags'], $this->_params['charset'], $GLOBALS['registry']->getCharset()); - } - return $story; - } - - /** - * Returns the most recent or all stories from a channel. - * - * @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. - */ - function _getStories($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; - case Jonah::ORDER_READ: - $sql .= ' ORDER BY story_read DESC'; - break; - case Jonah::ORDER_COMMENTS: - //@TODO - break; - } - - if (!is_null($max)) { - $sql = $this->_db->modifyLimitQuery($sql, (int)$from, (int)$max, $values); - } - - Horde::logMessage('SQL Query by Jonah_News_sql::_getStories(): ' . $sql, 'DEBUG'); - $result = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - 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; - } - - /** - */ - function _getStory($story_id, $read = false) - { - 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_News_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; - } - - /** - */ - function _getStoryByUrl($channel_id, $story_url) - { - if (is_a(($result = $this->_connect()), 'PEAR_Error')) { - return $result; - } - - $sql = 'SELECT * FROM jonah_stories' . - ' WHERE channel_id = ? AND story_url = ?'; - $values = array((int)$channel_id, $story_url); - - Horde::logMessage('SQL Query by Jonah_News_sql::_getStoryByUrl(): ' . $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 URL \"%s\" not found."), $story_url)); - } - $result = $this->_convertFromBackend($result); - if (empty($result['story_permalink'])) { - $this->_addPermalink($result); - } - - return $result; - } - - /** - * Adds a missing permalink to a story. - * - * @param array $story A story hash. - */ - 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']); - Horde::logMessage('SQL Query by Jonah_News_sql::_addPermalink(): ' . $sql, 'DEBUG'); - $result = $this->_db->query($sql, $values); - if (!is_a($result, 'PEAR_Error')) { - $story['story_permalink'] = $values[0]; - } - } - - /** - * Gets the latest released story from a given internal channel - * - * @param int $channel_id The channel id. - * - * @return int The story id. - */ - 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'; - $values = array((int)$channel_id, time()); - - Horde::logMessage('SQL Query by Jonah_News_sql::getLatestStoryId(): ' . $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(_("Channel \"%s\" not found."), $channel_id)); - } - - return $result['story_id']; - } - - /** - */ - 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_News_sql::deleteStory(): ' . $sql, 'DEBUG'); - $result = $this->_db->query($sql, $values); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result->getMessage(), 'ERR'); - return $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')) { - Horde::logMessage($result->getMessage(), 'ERR'); - return $result; - } - - return true; - } - - /** - * Write out the tags for a specific resource. - * - * @param int $resource_id The story we are tagging. - * @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 - */ - 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(?, ?)'); - $query = $this->_db->prepare('SELECT tag_id FROM jonah_tags WHERE tag_name = ?'); - 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; - } elseif ($results->numRows() == 0) { - $id = $this->_db->nextId('jonah_tags'); - $result = $this->_db->execute($insert, array($id, $tag)); - $tagkeys[] = $id; - } else { - $row = $results->fetchRow(DB_FETCHMODE_ASSOC); - $tagkeys[] = $row['tag_id']; - } - } - - // Free our resources. - $this->_db->freePrepared($insert, true); - $this->_db->freePrepared($query, true); - - $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_News_sql::writeTags: ' . $sql, - 'DEBUG'); - - $this->_db->query($sql); - foreach ($tagkeys as $key) { - $this->_db->execute($query, array($resource_id, $channel_id, $key)); - } - $this->_db->freePrepared($query, true); - - /* @TODO We should clear at least any of our cached counts */ - return true; - } - - /** - * Retrieve the tags for a specified resource. - * - * @param int $resource_id The resource to get tags for. - * - * @return mixed An array of tags | PEAR_Error - */ - 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_News_sql::readTags ' . $sql, - 'DEBUG'); - - $tags = $this->_db->getAssoc($sql, false, array($resource_id), false); - return $tags; - } - - /** - * Retrieve the list of used tag_names, tag_ids and the total number - * of resources that are linked to that tag. - * - * @param array $tags An optional array of tag_ids. If omitted, all tags - * will be included. - * - * @param array $channel_id An optional array of channel_ids. - * - * @return mixed An array containing tag_name, and total | PEAR_Error - */ - 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); - } - $cache = $GLOBALS['injector']->getInstance('Horde_Cache'); - $cache_key = 'jonah_tags_' . md5(serialize($tags) . md5(serialize($channel_id))); - $cache_value = $cache->get($cache_key, $GLOBALS['conf']['cache']['default_lifetime']); - if ($cache_value) { - return unserialize($cache_value); - } - - $haveWhere = false; - $sql = 'SELECT tn.tag_id, tag_name, COUNT(tag_name) total FROM jonah_tags as tn INNER JOIN jonah_stories_tags as t ON t.tag_id = tn.tag_id'; - if (count($tags)) { - $sql .= ' WHERE tn.tag_id IN (' . implode(',', $tags) . ')'; - $haveWhere = true; - } - if (!is_null($channel_id)) { - if (!$haveWhere) { - $sql .= ' WHERE'; - } else { - $sql .= ' AND'; - } - $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); - $cache->set($cache_key, serialize($results)); - return $results; - } - - /** - * Search for resources matching the specified criteria - * - * @param array $ids An array of tag_ids to search for. Note that - * these are AND'd together. - * @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 array $channel Limit the result set to resources - * present in these channels - * @param integer $order How to order the results for internal - * channels. Possible values are the - * Jonah::ORDER_* constants. - * - * @return mixed Array of stories| PEAR_Error - */ - 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 { - $stories = array(); - $sql = 'SELECT DISTINCT s.story_id, s.channel_id FROM jonah_stories' - . ' as s, jonah_stories_tags as t'; - for ($i = 0; $i < count($ids); $i++) { - $sql .= ', jonah_stories_tags as t' . $i; - } - $sql .= ' WHERE s.story_id = t.story_id'; - for ($i = 0 ; $i < count($ids); $i++) { - $sql .= ' AND t' . $i . '.tag_id = ' . $ids[$i] . ' AND t' - . $i . '.story_id = t.story_id'; - } - - /* Limit to particular channels if requested */ - if (count($channel_id) > 0) { - // Have to find out if we are a composite channel or not. - $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(); - $sql .= ' AND t.channel_id IN (' . implode(', ', $channels) - . ') AND s.story_published IS NOT NULL AND ' - . 's.story_published < ' . $timestamp; - } - - switch ($order) { - case Jonah::ORDER_PUBLISHED: - $sql .= ' ORDER BY story_published DESC'; - break; - case Jonah::ORDER_READ: - $sql .= ' ORDER BY story_read DESC'; - break; - case Jonah::ORDER_COMMENTS: - //@TODO - break; - } - - /* Instantiate the channel object outside the loop if we - * are only limiting to one channel. */ - if (count($channel_id) == 1) { - $channel = $this->getChannel($channel_id[0]); - } - Horde::logMessage('SQL query by Jonah_News_sql::searchTags: ' . $sql, 'DEBUG'); - $results = $this->_db->limitQuery($sql, $from, $max); - if (is_a($results, 'PEAR_Error')) { - return $results; - } - - for ($i = 0; $i < $results->numRows(); $i++) { - $row = $results->fetchRow(); - $story = $this->_getStory($row[0], false); - if (count($channel_id > 1)) { - // Make sure we get the correct channel info for composites - if (!empty($cchannels[$story['channel_id']])) { - $channel = $this->getChannel($cchannels[$story['channel_id']]); - } else { - $channel = $this->getChannel($story['channel_id']); - } - } - - /* Format story link. */ - $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']); - } - - $stories[] = $story; - } - } - - return $stories; - } - - /** - * Search for articles matching specific tag name(s). - * - * @see Jonah_News_sql::searchTagsById() - */ - function searchTags($names, $max = 10, $from = 0, $channel_id = array(), - $order = Jonah::ORDER_PUBLISHED) - { - $ids = $this->getTagIds($names); - if (is_a($ids, 'PEAR_Error')) { - return $ids; - } - return $this->searchTagsById(array_values($ids), $max, $from, $channel_id, $order); - } - - - /** - * Return a set of tag names given the tag_ids. - * - * @param array $ids An array of tag_ids to get names for. - * - * @return mixed An array of tag names | PEAR_Error. - */ - 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 .= ')'; - $tags = $this->_db->getCol($sql); - return $tags; - } - - /** - * Return a set of tag_ids, given the tag name - * - * @param array $names An array of names to search for - * - * @return mixed An array of tag_name => tag_ids | PEAR_Error - */ - 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 .= ')'; - $tags = $this->_db->getAssoc($sql); - return $tags; - } - - /** - * Attempts to open a persistent connection to the SQL server. - * - * @return boolean True on success; PEAR_Error on failure. - */ - function _connect() - { - if ($this->_connected) { - return true; - } - - try { - $this->_db = $GLOBALS['injector']->getInstance('Horde_Db_Pear')->getDb('rw', 'jonah', 'news'); - } catch (Horde_Exception $e) { - return PEAR::raiseError($e->getMessage()); - } - - $this->_connected = true; - - return true; - } - -} -- 2.11.0