.
/**
* A block which displays Remote feeds
*
* @package rss_client
* @copyright Daryl Hawes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class block_rss_client extends block_base {
function init() {
$this->title = get_string('feedstitle', 'block_rss_client');
}
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, $DB;
if ($this->content !== NULL) {
return $this->content;
}
// initalise block content object
$this->content = new stdClass;
$this->content->text = '';
$this->content->footer = '';
if (empty($this->instance)) {
return $this->content;
}
if (!isset($this->config)) {
// The block has yet to be configured - just display configure message in
// the block if user has permission to configure it
if (has_capability('block/rss_client:manageanyfeeds', $this->context)) {
$this->content->text = get_string('feedsconfigurenewinstance2', 'block_rss_client');
}
return $this->content;
}
// How many feed items should we display?
$maxentries = 5;
if ( !empty($this->config->shownumentries) ) {
$maxentries = intval($this->config->shownumentries);
}elseif( isset($CFG->block_rss_client_num_entries) ) {
$maxentries = intval($CFG->block_rss_client_num_entries);
}
/* ---------------------------------
* Begin Normal Display of Block Content
* --------------------------------- */
$output = '';
if (!empty($this->config->rssid)) {
list($rss_ids_sql, $params) = $DB->get_in_or_equal($this->config->rssid);
$rss_feeds = $DB->get_records_select('block_rss_client', "id $rss_ids_sql", $params);
$showtitle = false;
if (count($rss_feeds) > 1) {
// when many feeds show the title for each feed
$showtitle = true;
}
foreach($rss_feeds as $feed){
$output.= $this->get_feed_html($feed, $maxentries, $showtitle);
}
}
$this->content->text = $output;
return $this->content;
}
function instance_allow_multiple() {
return true;
}
function has_config() {
return true;
}
function instance_allow_config() {
return true;
}
/**
* Returns the html of a feed to be displaed in the block
*
* @param mixed feedrecord The feed record from the database
* @param int maxentries The maximum number of entries to be displayed
* @param boolean showtitle Should the feed title be displayed in html
* @return string html representing the rss feed content
*/
function get_feed_html($feedrecord, $maxentries, $showtitle){
global $CFG;
require_once($CFG->libdir.'/simplepie/moodle_simplepie.php');
$feed = new moodle_simplepie($feedrecord->url);
if(isset($CFG->block_rss_client_timeout)){
$feed->set_cache_duration($CFG->block_rss_client_timeout*60);
}
if(debugging() && $feed->error()){
return '
'. $feedrecord->url .' Failed with code: '.$feed->error().'
';
}
$r = ''; // return string
if($this->config->block_rss_client_show_channel_image){
if($image = $feed->get_image_url()){
$imagetitle = s($feed->get_image_title());
$imagelink = $feed->get_image_link();
$r.='';
}
}
if(empty($feedrecord->preferredtitle)){
$feedtitle = $this->format_title($feed->get_title());
}else{
$feedtitle = $this->format_title($feedrecord->preferredtitle);
}
if($showtitle){
$r.=''.$feedtitle.'
';
}
$r.=''."\n";
$feeditems = $feed->get_items(0, $maxentries);
foreach($feeditems as $item){
$r.= $this->get_item_html($item);
}
$r.='
';
if ($this->config->block_rss_client_show_channel_link) {
$channellink = $feed->get_link();
if (!empty($channellink)){
//NOTE: this means the 'last feed' display wins the block title - but
//this is exiting behaviour..
$this->content->footer = ''. get_string('clientchannellink', 'block_rss_client') .'';
}
}
if (empty($this->config->title)){
//NOTE: this means the 'last feed' displayed wins the block title - but
//this is exiting behaviour..
$this->title = strip_tags($feedtitle);
}
return $r;
}
/**
* Returns the html list item of a feed item
*
* @param mixed item simplepie_item representing the feed item
* @return string html li representing the rss feed item
*/
function get_item_html($item){
$link = $item->get_link();
$title = $item->get_title();
$description = $item->get_description();
if(empty($title)){
// no title present, use portion of description
$title = textlib::substr(strip_tags($description), 0, 20) . '...';
}else{
$title = break_up_long_words($title, 30);
}
if(empty($link)){
$link = $item->get_id();
} else {
//URLs in our RSS cache will be escaped (correctly as theyre store in XML)
//html_writer::link() will re-escape them. To prevent double escaping unescape here.
//This can by done using htmlspecialchars_decode() but moodle_url also has that effect
$link = new moodle_url($link);
}
$r = html_writer::start_tag('li');
$r.= html_writer::start_tag('div',array('class'=>'link'));
$r.= html_writer::link($link, s($title), array('onclick'=>'this.target="_blank"'));
$r.= html_writer::end_tag('div');
if($this->config->display_description && !empty($description)){
$description = break_up_long_words($description, 30);
$formatoptions = new stdClass();
$formatoptions->para = false;
$r.= html_writer::start_tag('div',array('class'=>'description'));
$r.= format_text($description, FORMAT_HTML, $formatoptions, $this->page->course->id);
$r.= html_writer::end_tag('div');
}
$r.= html_writer::end_tag('li');
return $r;
}
/**
* Strips a large title to size and adds ... if title too long
*
* @param string title to shorten
* @param int max character length of title
* @return string title s() quoted and shortened if necessary
*/
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 - goes through all feeds and retrieves them with the cache
* duration set to 0 in order to force the retrieval of the item and
* refresh the cache
*
* @return boolean true if all feeds were retrieved succesfully
*/
function cron() {
global $CFG, $DB;
require_once($CFG->libdir.'/simplepie/moodle_simplepie.php');
// We are going to measure execution times
$starttime = microtime();
// And we have one initial $status
$status = true;
// 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 simplepie caching
// so feeds will be renewed only if cache has expired
@set_time_limit(60);
$feed = new moodle_simplepie();
// set timeout for longer than normal to be agressive at
// fetching feeds if possible..
$feed->set_timeout(40);
$feed->set_cache_duration(0);
$feed->set_feed_url($rec->url);
$feed->init();
if ($feed->error()) {
mtrace ('error');
mtrace ('SimplePie failed with error:'.$feed->error());
$status = false;
} else {
mtrace ('ok');
}
$counter ++;
}
$rs->close();
// Show times
mtrace($counter . ' feeds refreshed (took ' . microtime_diff($starttime, microtime()) . ' seconds)');
// And return $status
return $status;
}
}