1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Contains block_rss_client 19 * @package block_rss_client 20 * @copyright Daryl Hawes 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL 22 */ 23 24 /** 25 * A block which displays Remote feeds 26 * 27 * @package block_rss_client 28 * @copyright Daryl Hawes 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL 30 */ 31 32 class block_rss_client extends block_base { 33 /** @var bool track whether any of the output feeds have recorded failures */ 34 private $hasfailedfeeds = false; 35 36 function init() { 37 $this->title = get_string('pluginname', 'block_rss_client'); 38 } 39 40 function applicable_formats() { 41 return array('all' => true, 'tag' => false); // Needs work to make it work on tags MDL-11960 42 } 43 44 function specialization() { 45 // After the block has been loaded we customize the block's title display 46 if (!empty($this->config) && !empty($this->config->title)) { 47 // There is a customized block title, display it 48 $this->title = $this->config->title; 49 } else { 50 // No customized block title, use localized remote news feed string 51 $this->title = get_string('remotenewsfeed', 'block_rss_client'); 52 } 53 } 54 55 /** 56 * Gets the footer, which is the channel link of the last feed in our list of feeds 57 * 58 * @param array $feedrecords The feed records from the database. 59 * @return block_rss_client\output\footer|null The renderable footer or null if none should be displayed. 60 */ 61 protected function get_footer($feedrecords) { 62 $footer = null; 63 64 if ($this->config->block_rss_client_show_channel_link) { 65 global $CFG; 66 require_once($CFG->libdir.'/simplepie/moodle_simplepie.php'); 67 68 $feedrecord = array_pop($feedrecords); 69 $feed = new moodle_simplepie($feedrecord->url); 70 $channellink = new moodle_url($feed->get_link()); 71 72 if (!empty($channellink)) { 73 $footer = new block_rss_client\output\footer($channellink); 74 } 75 } 76 77 if ($this->hasfailedfeeds) { 78 if (has_any_capability(['block/rss_client:manageownfeeds', 'block/rss_client:manageanyfeeds'], $this->context)) { 79 if ($footer === null) { 80 $footer = new block_rss_client\output\footer(); 81 } 82 $manageurl = new moodle_url('/blocks/rss_client/managefeeds.php', 83 ['courseid' => $this->page->course->id]); 84 $footer->set_failed($manageurl); 85 } 86 } 87 88 return $footer; 89 } 90 91 function get_content() { 92 global $CFG, $DB; 93 94 if ($this->content !== NULL) { 95 return $this->content; 96 } 97 98 // initalise block content object 99 $this->content = new stdClass; 100 $this->content->text = ''; 101 $this->content->footer = ''; 102 103 if (empty($this->instance)) { 104 return $this->content; 105 } 106 107 if (!isset($this->config)) { 108 // The block has yet to be configured - just display configure message in 109 // the block if user has permission to configure it 110 111 if (has_capability('block/rss_client:manageanyfeeds', $this->context)) { 112 $this->content->text = get_string('feedsconfigurenewinstance2', 'block_rss_client'); 113 } 114 115 return $this->content; 116 } 117 118 // How many feed items should we display? 119 $maxentries = 5; 120 if ( !empty($this->config->shownumentries) ) { 121 $maxentries = intval($this->config->shownumentries); 122 }elseif( isset($CFG->block_rss_client_num_entries) ) { 123 $maxentries = intval($CFG->block_rss_client_num_entries); 124 } 125 126 /* --------------------------------- 127 * Begin Normal Display of Block Content 128 * --------------------------------- */ 129 130 $renderer = $this->page->get_renderer('block_rss_client'); 131 $block = new \block_rss_client\output\block(); 132 133 if (!empty($this->config->rssid)) { 134 list($rssidssql, $params) = $DB->get_in_or_equal($this->config->rssid); 135 $rssfeeds = $DB->get_records_select('block_rss_client', "id $rssidssql", $params); 136 137 if (!empty($rssfeeds)) { 138 $showtitle = false; 139 if (count($rssfeeds) > 1) { 140 // When many feeds show the title for each feed. 141 $showtitle = true; 142 } 143 144 foreach ($rssfeeds as $feed) { 145 if ($renderablefeed = $this->get_feed($feed, $maxentries, $showtitle)) { 146 $block->add_feed($renderablefeed); 147 } 148 } 149 150 $footer = $this->get_footer($rssfeeds); 151 } 152 } 153 154 $this->content->text = $renderer->render_block($block); 155 if (isset($footer)) { 156 $this->content->footer = $renderer->render_footer($footer); 157 } 158 159 return $this->content; 160 } 161 162 163 function instance_allow_multiple() { 164 return true; 165 } 166 167 function has_config() { 168 return true; 169 } 170 171 function instance_allow_config() { 172 return true; 173 } 174 175 /** 176 * Returns the html of a feed to be displaed in the block 177 * 178 * @param mixed feedrecord The feed record from the database 179 * @param int maxentries The maximum number of entries to be displayed 180 * @param boolean showtitle Should the feed title be displayed in html 181 * @return block_rss_client\output\feed|null The renderable feed or null of there is an error 182 */ 183 public function get_feed($feedrecord, $maxentries, $showtitle) { 184 global $CFG; 185 require_once($CFG->libdir.'/simplepie/moodle_simplepie.php'); 186 187 if ($feedrecord->skipuntil) { 188 // Last attempt to gather this feed via cron failed - do not try to fetch it now. 189 $this->hasfailedfeeds = true; 190 return null; 191 } 192 193 $simplepiefeed = new moodle_simplepie($feedrecord->url); 194 195 if(isset($CFG->block_rss_client_timeout)){ 196 $simplepiefeed->set_cache_duration($CFG->block_rss_client_timeout * 60); 197 } 198 199 if ($simplepiefeed->error()) { 200 debugging($feedrecord->url .' Failed with code: '.$simplepiefeed->error()); 201 return null; 202 } 203 204 if(empty($feedrecord->preferredtitle)){ 205 // Simplepie does escape HTML entities. 206 $feedtitle = $this->format_title($simplepiefeed->get_title()); 207 }else{ 208 // Moodle custom title does not does escape HTML entities. 209 $feedtitle = $this->format_title(s($feedrecord->preferredtitle)); 210 } 211 212 if (empty($this->config->title)){ 213 //NOTE: this means the 'last feed' displayed wins the block title - but 214 //this is exiting behaviour.. 215 $this->title = strip_tags($feedtitle); 216 } 217 218 $feed = new \block_rss_client\output\feed($feedtitle, $showtitle, $this->config->block_rss_client_show_channel_image); 219 220 if ($simplepieitems = $simplepiefeed->get_items(0, $maxentries)) { 221 foreach ($simplepieitems as $simplepieitem) { 222 try { 223 $item = new \block_rss_client\output\item( 224 $simplepieitem->get_id(), 225 new moodle_url($simplepieitem->get_link()), 226 $simplepieitem->get_title(), 227 $simplepieitem->get_description(), 228 new moodle_url($simplepieitem->get_permalink()), 229 $simplepieitem->get_date('U'), 230 $this->config->display_description 231 ); 232 233 $feed->add_item($item); 234 } catch (moodle_exception $e) { 235 // If there is an error with the RSS item, we don't 236 // want to crash the page. Specifically, moodle_url can 237 // throw an exception of the param is an extremely 238 // malformed url. 239 debugging($e->getMessage()); 240 } 241 } 242 } 243 244 // Feed image. 245 if ($imageurl = $simplepiefeed->get_image_url()) { 246 try { 247 $image = new \block_rss_client\output\channel_image( 248 new moodle_url($imageurl), 249 $simplepiefeed->get_image_title(), 250 new moodle_url($simplepiefeed->get_image_link()) 251 ); 252 253 $feed->set_image($image); 254 } catch (moodle_exception $e) { 255 // If there is an error with the RSS image, we don'twant to 256 // crash the page. Specifically, moodle_url can throw an 257 // exception if the param is an extremely malformed url. 258 debugging($e->getMessage()); 259 } 260 } 261 262 return $feed; 263 } 264 265 /** 266 * Strips a large title to size and adds ... if title too long 267 * This function does not escape HTML entities, so they have to be escaped 268 * before being passed here. 269 * 270 * @param string title to shorten 271 * @param int max character length of title 272 * @return string title shortened if necessary 273 */ 274 function format_title($title,$max=64) { 275 276 if (core_text::strlen($title) <= $max) { 277 return $title; 278 } else { 279 return core_text::substr($title, 0, $max - 3) . '...'; 280 } 281 } 282 283 /** 284 * Return the plugin config settings for external functions. 285 * 286 * @return stdClass the configs for both the block instance and plugin 287 * @since Moodle 3.8 288 */ 289 public function get_config_for_external() { 290 global $CFG; 291 292 // Return all settings for all users since it is safe (no private keys, etc..). 293 $instanceconfigs = !empty($this->config) ? $this->config : new stdClass(); 294 $pluginconfigs = (object) [ 295 'num_entries' => $CFG->block_rss_client_num_entries, 296 'timeout' => $CFG->block_rss_client_timeout 297 ]; 298 299 return (object) [ 300 'instance' => $instanceconfigs, 301 'plugin' => $pluginconfigs, 302 ]; 303 } 304 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body