moodle/blocks/rss_client/block_rss_client.php
tjhunt e92c286c20 block contexts: MDL-19098 every block should have a context
even non-course and sticky blocks.

The parent context is block_instances.parentcontextid.

The block context should be used for checking permissions directly
related to the block, like moodle/block:view or moodle/site:manageblocks.

However, if the block is displaying information about the current page,
for example the participants block showing who 'here', then it may be
better to use the context of the page where the bloack is appearing -
in other words $this->page->context - to check permissions about the
user's ability to see participants here.

Or, if the block is displaying something stronly related to courses,
for example, a course meny block, the block should probably use the
context for $this->page->course to check permissions.
2009-07-13 08:37:34 +00:00

346 lines
14 KiB
PHP

<?php //$Id$
/*******************************************************************
* This file contains one class which defines a block for display on
* any Moodle page. This block can be configured to display the contents
* of a remote RSS news feed in your web site.
*
* @author Daryl Hawes
* @version $Id$
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package base
******************************************************************/
/**
* This class is for a block which defines a block for display on
* any Moodle page.
*/
class block_rss_client extends block_base {
function init() {
$this->title = get_string('feedstitle', 'block_rss_client');
$this->version = 2007101511;
$this->cron = 300; /// Set min time between cron executions to 300 secs (5 mins)
}
function preferred_width() {
return 210;
}
function applicable_formats() {
return array('all' => true, 'tag' => false); // Needs work to make it work on tags MDL-11960
}
function specialization() {
// After the block has been loaded we customize the block's title display
if (!empty($this->config) && !empty($this->config->title)) {
// There is a customized block title, display it
$this->title = $this->config->title;
} else {
// No customized block title, use localized remote news feed string
$this->title = get_string('remotenewsfeed', 'block_rss_client');
}
}
function get_content() {
global $CFG, $editing, $USER;
if (!empty($this->page->course)) {
$this->courseid = $this->page->course->id;
}
/// When displaying feeds in block, we double $CFG->block_rss_client_timeout
/// so those feeds retrieved and cached by the cron() process will have a
/// better chance to be used
if (!empty($CFG->block_rss_client_timeout)) {
$CFG->block_rss_client_timeout *= 2;
}
require_once($CFG->libdir .'/rsslib.php');
if($this->content !== NULL) {
return $this->content;
}
$this->content = new stdClass;
$this->content->text = '';
$this->content->footer = '';
if (empty($this->instance)) {
// We're being asked for content without an associated instance
return $this->content;
}
$output = '';
$rssid = -1;
$display_description = false;
if (isset($CFG->block_rss_client_num_entries) && is_numeric($CFG->block_rss_client_num_entries) ) {
$shownumentries = intval($CFG->block_rss_client_num_entries);
} else {
$shownumentries = 5; //default to 5 entries is not specified in admin section or instance
}
if (!empty($this->config)) {
if (!empty($this->config->rssid)) {
if (is_array($this->config->rssid)) {
$rssidarray = $this->config->rssid;
} else { // Make an array of the single value
$rssidarray = array($this->config->rssid);
}
}
if (!empty($this->config->display_description)) {
$display_description = intval($this->config->display_description);
}
if (!empty($this->config->shownumentries)) {
$shownumentries = intval($this->config->shownumentries);
}
}
if (has_any_capability(array('block/rss_client:createsharedfeeds', 'block/rss_client:createprivatefeeds'), $this->context)) {
$page = $this->page;
//if ($page->user_allowed_editing()) { // for SUBMITTERS_ALL_ACCOUNT_HOLDERS we're going to run into trouble later if we show it and then they don't have write access to the page.
if (isset($this->config)) {
// This instance is configured - show Add/Edit feeds link.
$script = $page->url->out(
array('instanceid' => $this->instance->id,
'sesskey' => sesskey(),
'blockaction' => 'config',
'currentaction' => 'managefeeds',
'id' => $this->courseid,
'section' => 'rss'
));
$output .= '<div class="info"><a title="'. get_string('feedsaddedit', 'block_rss_client') .'" href="'. $script .'">'. get_string('feedsaddedit', 'block_rss_client') .'</a></div>';
} else {
// This instance has not been configured yet - show configure link?
if (has_capability('block/rss_client:manageanyfeeds', $this->context)) {
$script = $page->url->out(
array('instanceid' => $this->instance->id,
'sesskey' => sesskey(),
'blockaction' => 'config',
'currentaction' => 'configblock',
'id' => $this->page->course->id,
'section' => 'rss'
));
$output .= '<div class="info"><a title="'. get_string('feedsconfigurenewinstance', 'block_rss_client') .'" href="'. $script.'">'. get_string('feedsconfigurenewinstance', 'block_rss_client') .'</a></div>';
}
}
//}
}
// Daryl Hawes note: if count of rssidarray is greater than 1
// we should possibly display a drop down menu of selected feed titles
// so user can select a single feed to view (similar to RSSFeed)
if (!empty($rssidarray)) {
$numids = count($rssidarray);
$count = 0;
foreach ($rssidarray as $rssid) {
$output .= $this->get_rss_by_id($rssid, $display_description, $shownumentries, ($numids > 1) ? true : false);
if ($numids > 1 && $count != $numids -1 && !empty($rssfeedstring)) {
$output .= '<hr style="width=:80%" />';
}
$count ++;
}
}
$this->content->text = $output;
return $this->content;
}
function instance_allow_multiple() {
return true;
}
function has_config() {
return true;
}
function instance_allow_config() {
return true;
}
/**
* @param int $rssid The feed to be displayed
* @param bool $display_description Should the description information from the feed be displayed or simply the title?
* @param int $shownumentries The maximum number of feed entries to be displayed.
* @param bool $showtitle True if the feed title should be displayed above the feed entries.
* @return string|NULL
*/
function get_rss_by_id($rssid, $display_description, $shownumentries, $showtitle=false) {
global $CFG, $DB;
$returnstring = '';
$now = time();
require_once($CFG->libdir .'/rsslib.php');
require_once(MAGPIE_DIR .'rss_fetch.inc');
if (!defined('MAGPIE_OUTPUT_ENCODING')) {
define('MAGPIE_OUTPUT_ENCODING', 'utf-8'); // see bug 3107
}
$rss_record = $DB->get_record('block_rss_client', array('id'=>$rssid));
if (isset($rss_record) && isset($rss_record->id)) {
// By capturing the output from fetch_rss this way
// error messages do not display and clutter up the moodle interface
// however, we do lose out on seeing helpful messages like "cache hit", etc.
ob_start();
$rss = fetch_rss($rss_record->url);
$rsserror = ob_get_contents();
ob_end_clean();
if ($rss === false) {
if (debugging() && !empty($rsserror)) {
// There was a failure in loading the rss feed, print link to full error text
return '<a href="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_error.php?error='. urlencode($rsserror) .'">Error loading a feed.</a><br />'; //Daryl Hawes note: localize this line
}
}
// first we must verify that the rss feed is loaded
// by checking $rss and $rss->items exist before using them
if (empty($rss) || empty($rss->items)) {
return '';
}
if ($shownumentries > 0 && $shownumentries < count($rss->items) ) {
$rss->items = array_slice($rss->items, 0, $shownumentries);
}
if (empty($rss_record->preferredtitle)) {
if (isset($rss->channel['title'])) { // Just in case feed is dead
$feedtitle = $this->format_title($rss->channel['title']);
} else {
$feedtitle = '';
}
} else {
$feedtitle = $this->format_title($rss_record->preferredtitle);
}
if (isset($this->config) &&
isset($this->config->block_rss_client_show_channel_image) &&
$this->config->block_rss_client_show_channel_image &&
isset($rss->image) && isset($rss->image['link']) && isset($rss->image['title']) && isset($rss->image['url']) ) {
$rss->image['title'] = s($rss->image['title']);
$returnstring .= "\n".'<div class="image" title="'. $rss->image['title'] .'"><a href="'. $rss->image['link'] .'"><img src="'. $rss->image['url'] .'" alt="'. $rss->image['title'] .'" /></a></div>';
}
if ($showtitle) {
$returnstring .= '<div class="title">'. $feedtitle .'</div>';
}
$formatoptions->para = false;
/// Accessibility: markup as a list.
$returnstring .= '<ul class="list">'."\n";
foreach ($rss->items as $item) {
if ($item['title'] == '') {
// no title present, use portion of description
$item['title'] = substr(strip_tags($item['description']), 0, 20) . '...';
} else {
$item['title'] = break_up_long_words($item['title'], 30);
}
if ($item['link'] == '') {
$item['link'] = $item['guid'];
}
$item['title'] = s($item['title']);
$item['link'] = str_replace('&', '&amp;', $item['link']);
$returnstring .= '<li><div class="link"><a href="'. $item['link'] .'" onclick="this.target=\'_blank\'" >'. $item['title'] . "</a></div>\n";
if ($display_description && !empty($item['description'])) {
$item['description'] = break_up_long_words($item['description'], 30);
$returnstring .= '<div class="description">'.
format_text($item['description'], FORMAT_MOODLE, $formatoptions, $this->courseid) .
'</div>';
}
$returnstring .= "</li>\n";
}
$returnstring .= "</ul>\n";
if (!empty($rss->channel['link'])) {
$rss->channel['link'] = str_replace('&', '&amp;', $rss->channel['link']);
if (!empty($this->config) && isset($this->config->block_rss_client_show_channel_link) && $this->config->block_rss_client_show_channel_link) {
$this->content->footer = '<a href="'. $rss->channel['link'] .'">'. get_string('clientchannellink', 'block_rss_client') .'</a>';
}
if (!empty($feedtitle) ) {
$feedtitle = '<a href="'. $rss->channel['link'] .'">'. $feedtitle .'</a>';
}
}
}
// if block has no custom title
if (empty($this->config) || (!empty($this->config) && empty($this->config->title))) {
// if the feed has a title
if (!empty($feedtitle) and ($feedtitle != '<a href="'. $rss->channel['link'] .'"></a>')) {
// set the block's title to the feed's title
$this->title = strip_tags($feedtitle);
}
}
return $returnstring;
}
// just strips the title down and adds ... for excessively long titles.
function format_title($title,$max=64) {
/// Loading the textlib singleton instance. We are going to need it.
$textlib = textlib_get_instance();
if ($textlib->strlen($title) <= $max) {
return s($title);
} else {
return s($textlib->substr($title,0,$max-3).'...');
}
}
// cron function, used to refresh all the RSS feeds from Moodle cron
function cron() {
global $CFG, $DB;
/// We are going to measure execution times
$starttime = microtime();
/// And we have one initial $status
$status = true;
/// We require some stuff
require_once($CFG->libdir .'/rsslib.php');
require_once(MAGPIE_DIR .'rss_fetch.inc');
if (!defined('MAGPIE_OUTPUT_ENCODING')) {
define('MAGPIE_OUTPUT_ENCODING', 'utf-8'); // see bug 3107
}
/// Fetch all site feeds.
$rs = $DB->get_recordset('block_rss_client');
$counter = 0;
mtrace('');
foreach ($rs as $rec) {
mtrace(' ' . $rec->url . ' ', '');
/// Fetch the rss feed, using standard magpie caching
/// so feeds will be renewed only if cache has expired
// sometimes the cron times out on moodle.org during fetching,
// there is a 5s limit in magpie which should work, but does not sometimes :-(
@set_time_limit(60);
if ($rss = fetch_rss($rec->url)) {
mtrace ('ok');
} else {
mtrace ('error');
$status = false;
}
$counter ++;
}
$rs->close();
/// Show times
mtrace($counter . ' feeds refreshed (took ' . microtime_diff($starttime, microtime()) . ' seconds)');
/// And return $status
return $status;
}
}
?>