MDL-65788 tool_policy: Prevent two modals rendering for guests.
[moodle.git] / blocks / rss_client / block_rss_client.php
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/>.
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  */
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  */
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;
36     function init() {
37         $this->title = get_string('pluginname', 'block_rss_client');
38     }
40     function applicable_formats() {
41         return array('all' => true, 'tag' => false);   // Needs work to make it work on tags MDL-11960
42     }
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     }
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         global $PAGE;
63         $footer = null;
65         if ($this->config->block_rss_client_show_channel_link) {
66             global $CFG;
67             require_once($CFG->libdir.'/simplepie/moodle_simplepie.php');
69             $feedrecord     = array_pop($feedrecords);
70             $feed           = new moodle_simplepie($feedrecord->url);
71             $channellink    = new moodle_url($feed->get_link());
73             if (!empty($channellink)) {
74                 $footer = new block_rss_client\output\footer($channellink);
75             }
76         }
78         if ($this->hasfailedfeeds) {
79             if (has_any_capability(['block/rss_client:manageownfeeds', 'block/rss_client:manageanyfeeds'], $this->context)) {
80                 if ($footer === null) {
81                     $footer = new block_rss_client\output\footer();
82                 }
83                 $manageurl = new moodle_url('/blocks/rss_client/managefeeds.php', ['courseid' => $PAGE->course->id]);
84                 $footer->set_failed($manageurl);
85             }
86         }
88         return $footer;
89     }
91     function get_content() {
92         global $CFG, $DB;
94         if ($this->content !== NULL) {
95             return $this->content;
96         }
98         // initalise block content object
99         $this->content = new stdClass;
100         $this->content->text   = '';
101         $this->content->footer = '';
103         if (empty($this->instance)) {
104             return $this->content;
105         }
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
111             if (has_capability('block/rss_client:manageanyfeeds', $this->context)) {
112                 $this->content->text = get_string('feedsconfigurenewinstance2', 'block_rss_client');
113             }
115             return $this->content;
116         }
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         }
126         /* ---------------------------------
127          * Begin Normal Display of Block Content
128          * --------------------------------- */
130         $renderer = $this->page->get_renderer('block_rss_client');
131         $block = new \block_rss_client\output\block();
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);
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                 }
144                 foreach ($rssfeeds as $feed) {
145                     if ($renderablefeed = $this->get_feed($feed, $maxentries, $showtitle)) {
146                         $block->add_feed($renderablefeed);
147                     }
148                 }
150                 $footer = $this->get_footer($rssfeeds);
151             }
152         }
154         $this->content->text = $renderer->render_block($block);
155         if (isset($footer)) {
156             $this->content->footer = $renderer->render_footer($footer);
157         }
159         return $this->content;
160     }
163     function instance_allow_multiple() {
164         return true;
165     }
167     function has_config() {
168         return true;
169     }
171     function instance_allow_config() {
172         return true;
173     }
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');
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         }
193         $simplepiefeed = new moodle_simplepie($feedrecord->url);
195         if(isset($CFG->block_rss_client_timeout)){
196             $simplepiefeed->set_cache_duration($CFG->block_rss_client_timeout * 60);
197         }
199         if ($simplepiefeed->error()) {
200             debugging($feedrecord->url .' Failed with code: '.$simplepiefeed->error());
201             return null;
202         }
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         }
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         }
218         $feed = new \block_rss_client\output\feed($feedtitle, $showtitle, $this->config->block_rss_client_show_channel_image);
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                     );
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         }
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                 );
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         }
262         return $feed;
263     }
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) {
276         if (core_text::strlen($title) <= $max) {
277             return $title;
278         } else {
279             return core_text::substr($title, 0, $max - 3) . '...';
280         }
281     }