public function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; $name = trim($mform->getElementValue('name')); $description = trim($mform->getElementValue('description')); $url = $mform->getElementValue('url'); if (empty($name) || empty($description)) { $rss = new moodle_simplepie($url); if (empty($name) && $rss->get_title()) { $mform->setDefault('name', $rss->get_title()); } if (empty($description) && $rss->get_description()) { $mform->setDefault('description', $rss->get_description()); } } if ($id = $mform->getElementValue('id')) { $mform->setDefault('autotags', implode(',', tag_get_tags_array('blog_external', $id))); $mform->freeze('url'); $mform->freeze('filtertags'); // TODO change the filtertags element to a multiple select, using the tags of the external blog // Use $rss->get_channel_tags() } }
/** * Reset RSS cache * * @return boolean success if cache clear or didn't exist */ public static function reset_cache() { $cachedir = moodle_simplepie::get_cache_directory(); return remove_dir($cachedir); }
/** * 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; }
/** * Given a record in the {blog_external} table, checks the blog's URL * for new entries not yet copied into Moodle. * Also attempts to identify and remove deleted blog entries * * @param object $externalblog * @return boolean False if the Feed is invalid */ function blog_sync_external_entries($externalblog) { global $CFG, $DB; require_once $CFG->libdir . '/simplepie/moodle_simplepie.php'; $rssfile = new moodle_simplepie_file($externalblog->url); $filetest = new SimplePie_Locator($rssfile); if (!$filetest->is_feed($rssfile)) { $externalblog->failedlastsync = 1; $DB->update_record('blog_external', $externalblog); return false; } else { if (!empty($externalblog->failedlastsync)) { $externalblog->failedlastsync = 0; $DB->update_record('blog_external', $externalblog); } } $rss = new moodle_simplepie($externalblog->url); if (empty($rss->data)) { return null; } //used to identify blog posts that have been deleted from the source feed $oldesttimestamp = null; $uniquehashes = array(); foreach ($rss->get_items() as $entry) { // If filtertags are defined, use them to filter the entries by RSS category if (!empty($externalblog->filtertags)) { $containsfiltertag = false; $categories = $entry->get_categories(); $filtertags = explode(',', $externalblog->filtertags); $filtertags = array_map('trim', $filtertags); $filtertags = array_map('strtolower', $filtertags); foreach ($categories as $category) { if (in_array(trim(strtolower($category->term)), $filtertags)) { $containsfiltertag = true; } } if (!$containsfiltertag) { continue; } } $uniquehashes[] = $entry->get_permalink(); $newentry = new stdClass(); $newentry->userid = $externalblog->userid; $newentry->module = 'blog_external'; $newentry->content = $externalblog->id; $newentry->uniquehash = $entry->get_permalink(); $newentry->publishstate = 'site'; $newentry->format = FORMAT_HTML; // Clean subject of html, just in case $newentry->subject = clean_param($entry->get_title(), PARAM_TEXT); // Observe 128 max chars in DB // TODO: +1 to raise this to 255 if (textlib::strlen($newentry->subject) > 128) { $newentry->subject = textlib::substr($newentry->subject, 0, 125) . '...'; } $newentry->summary = $entry->get_description(); //used to decide whether to insert or update //uses enty permalink plus creation date if available $existingpostconditions = array('uniquehash' => $entry->get_permalink()); //our DB doesnt allow null creation or modified timestamps so check the external blog supplied one $entrydate = $entry->get_date('U'); if (!empty($entrydate)) { $existingpostconditions['created'] = $entrydate; } //the post ID or false if post not found in DB $postid = $DB->get_field('post', 'id', $existingpostconditions); $timestamp = null; if (empty($entrydate)) { $timestamp = time(); } else { $timestamp = $entrydate; } //only set created if its a new post so we retain the original creation timestamp if the post is edited if ($postid === false) { $newentry->created = $timestamp; } $newentry->lastmodified = $timestamp; if (empty($oldesttimestamp) || $timestamp < $oldesttimestamp) { //found an older post $oldesttimestamp = $timestamp; } if (textlib::strlen($newentry->uniquehash) > 255) { // The URL for this item is too long for the field. Rather than add // the entry without the link we will skip straight over it. // RSS spec says recommended length 500, we use 255. debugging('External blog entry skipped because of oversized URL', DEBUG_DEVELOPER); continue; } if ($postid === false) { $id = $DB->insert_record('post', $newentry); // Set tags if ($tags = tag_get_tags_array('blog_external', $externalblog->id)) { tag_set('post', $id, $tags); } } else { $newentry->id = $postid; $DB->update_record('post', $newentry); } } // Look at the posts we have in the database to check if any of them have been deleted from the feed. // Only checking posts within the time frame returned by the rss feed. Older items may have been deleted or // may just not be returned anymore. We can't tell the difference so we leave older posts alone. $sql = "SELECT id, uniquehash\n FROM {post}\n WHERE module = 'blog_external'\n AND " . $DB->sql_compare_text('content') . " = " . $DB->sql_compare_text(':blogid') . "\n AND created > :ts"; $dbposts = $DB->get_records_sql($sql, array('blogid' => $externalblog->id, 'ts' => $oldesttimestamp)); $todelete = array(); foreach ($dbposts as $dbpost) { if (!in_array($dbpost->uniquehash, $uniquehashes)) { $todelete[] = $dbpost->id; } } $DB->delete_records_list('post', 'id', $todelete); $DB->update_record('blog_external', array('id' => $externalblog->id, 'timefetched' => time())); }
function test_redirect() { global $CFG; $feed = new moodle_simplepie(moodlesimplepie_test::REDIRECTURL); $this->assertFalse($feed->error()); $this->assertEqual($feed->get_title(), 'Moodle News'); $this->assertEqual($feed->get_link(), 'http://moodle.org/mod/forum/view.php?f=1'); }
$context = $PAGE->context; } else { $context = context_system::instance(); $PAGE->set_context($context); } $urlparams = array('rssid' => $rssid); if ($courseid) { $urlparams['courseid'] = $courseid; } if ($returnurl) { $urlparams['returnurl'] = $returnurl; } $PAGE->set_url('/blocks/rss_client/viewfeed.php', $urlparams); $PAGE->set_pagelayout('popup'); $rssrecord = $DB->get_record('block_rss_client', array('id' => $rssid), '*', MUST_EXIST); $rss = new moodle_simplepie($rssrecord->url); if ($rss->error()) { debugging($rss->error()); print_error('errorfetchingrssfeed'); } $strviewfeed = get_string('viewfeed', 'block_rss_client'); $PAGE->set_title($strviewfeed); $PAGE->set_heading($strviewfeed); $managefeeds = new moodle_url('/blocks/rss_client/managefeeds.php', $urlparams); $PAGE->navbar->add(get_string('blocks')); $PAGE->navbar->add(get_string('pluginname', 'block_rss_client')); $PAGE->navbar->add(get_string('managefeeds', 'block_rss_client'), $managefeeds); $PAGE->navbar->add($strviewfeed); echo $OUTPUT->header(); if (!empty($rssrecord->preferredtitle)) { $feedtitle = $rssrecord->preferredtitle;
/** * Autodiscovers a feed url from a given url, to be used by the formslibs * filter function * * Uses simplepie with autodiscovery set to maximum level to try and find * a feed to subscribe to. * See: http://simplepie.org/wiki/reference/simplepie/set_autodiscovery_level * * @param string URL to autodiscover a url * @return string URL of feed or original url if none found */ public static function autodiscover_feed_url($url) { $rss = new moodle_simplepie(); $rss->set_feed_url($url); $rss->set_autodiscovery_level(SIMPLEPIE_LOCATOR_ALL); // When autodiscovering an RSS feed, simplepie will try lots of // rss links on a page, so set the timeout high $rss->set_timeout(20); $rss->init(); if ($rss->error()) { return $url; } return $rss->subscribe_url(); }
$newexternal->description = empty($data->description) ? $rss->get_description() : $data->description; $newexternal->userid = $USER->id; $newexternal->url = $data->url; $newexternal->filtertags = !empty($data->filtertags) ? $data->filtertags : null; $newexternal->timemodified = time(); $newexternal->id = $DB->insert_record('blog_external', $newexternal); core_tag_tag::set_item_tags('core', 'blog_external', $newexternal->id, context_user::instance($newexternal->userid), $data->autotags); blog_sync_external_entries($newexternal); // Log this action. $eventparms = array('context' => $context, 'objectid' => $newexternal->id, 'other' => array('url' => $newexternal->url)); $event = \core\event\blog_external_added::create($eventparms); $event->trigger(); break; case 'edit': if ($data->id && $DB->record_exists('blog_external', array('id' => $data->id))) { $rss = new moodle_simplepie($data->url); $external->id = $data->id; $external->name = empty($data->name) ? $rss->get_title() : $data->name; $external->description = empty($data->description) ? $rss->get_description() : $data->description; $external->userid = $USER->id; $external->url = $data->url; $external->filtertags = !empty($data->filtertags) ? $data->filtertags : null; $external->timemodified = time(); $DB->update_record('blog_external', $external); // Log this action. $eventparms = array('context' => $context, 'objectid' => $external->id, 'other' => array('url' => $external->url)); $event = \core\event\blog_external_updated::create($eventparms); $event->trigger(); core_tag_tag::set_item_tags('core', 'blog_external', $external->id, context_user::instance($external->userid), $data->autotags); } else { print_error('wrongexternalid', 'blog');
/** * Fetch the activity stream from the tracker and register the activity items * * @param int $before optionally filter activity that happened before this timestamp * @param int $after optionally filter activity that happened after this timestamp * @internal */ function dev_register_tracker_activity($before = null, $after = null) { global $DB; $filters = array(); $filters[] = 'streams=' . rawurlencode('key+IS+MDL+MDLQA+MDLSITE+MOBILE'); if (!is_null($before) and !is_null($after)) { $filters[] = 'streams=' . rawurlencode('update-date+BETWEEN+' . $after * 1000 . '+' . $before * 1000); } else { if (!is_null($before)) { $filters[] = 'streams=' . rawurlencode('update-date+BEFORE+' . $before * 1000); } else { if (!is_null($after)) { $filters[] = 'streams=' . rawurlencode('update-date+AFTER+' . $after * 1000); } } } $url = 'https://tracker.moodle.org/activity?' . implode('&', $filters); if (!is_null($after)) { fputs(STDOUT, date("Y-m-d H:i:s", $after)); } else { fputs(STDOUT, '*'); } fputs(STDOUT, ' - '); if (!is_null($before)) { fputs(STDOUT, date("Y-m-d H:i:s", $before)); } else { fputs(STDOUT, '*'); } $feed = new moodle_simplepie(); $feed->set_timeout(10); $feed->set_feed_url($url); $feed->init(); if ($error = $feed->error()) { fputs(STDERR, $error . PHP_EOL); exit(1); } $fetched = 0; $created = 0; foreach ($feed->get_items() as $item) { $fetched++; $activity = new stdClass(); $activity->uuid = $item->get_id(); $activity->title = $item->get_title(); $activity->timecreated = $item->get_date('U'); $activity->link = $item->get_link(); if ($tmp = $item->get_category()) { $activity->category = $tmp->get_term(); } if ($tmp = $item->get_author()) { $activity->personfullname = $tmp->get_name(); $activity->personemail = $tmp->get_email(); $activity->personlink = $tmp->get_link(); } if (!$DB->record_exists('dev_tracker_activities', array('uuid' => $activity->uuid))) { $DB->insert_record('dev_tracker_activities', $activity, false, true); $created++; } } fputs(STDOUT, sprintf(" %d %d %s\n", $fetched, $created, rawurldecode($url))); }
function get_content() { global $SESSION, $CFG, $USER, $OUTPUT; // quick and simple way to prevent block from showing up on front page if (!isloggedin()) { $this->content = NULL; return $this->content; } // which field is the username in $this->userfield = get_config('blocks/gmail', 'username') ? get_config('blocks/gmail', 'username') : 'username'; // quick and simple way to prevent block from showing up on users My Moodle if their email does not match the Google registered domain $this->domain = get_config('blocks/gmail', 'domainname') ? get_config('blocks/gmail', 'domainname') : get_config('auth/gsaml', 'domainname'); if ($this->content !== NULL) { return $this->content; } $this->content = new stdClass(); $this->content->items = array(); $this->content->icons = array(); $this->content->footer = ''; // This lib breaks install if left at top level only include // when we know we need it if ($USER->id !== 0) { require_once $CFG->libdir . '/simplepie/moodle_simplepie.php'; } // Test for domain settings if (empty($this->domain)) { $this->content->items = array(get_string('mustusegoogleauthenticaion', 'block_gmail')); $this->content->icons = array(); return $this->content; } if (!($this->oauthsecret = get_config('blocks/gmail', 'oauthsecret'))) { $this->content->items = array(get_string('missingoauthkey', 'block_gmail')); $this->content->icons = array(); return $this->content; } $feederror = false; // Obtain gmail feed data $feeddata = $this->obtain_gmail_feed(); if (empty($feeddata)) { $feederror = true; } else { // Parse google atom feed $feed = new moodle_simplepie(); $feed->set_raw_data($feeddata); $status = $feed->init(); $msgs = $feed->get_items(); } if ($feederror) { $this->content->items[] = get_string('sorrycannotgetmail', 'block_gmail'); } else { //$unreadmsgsstr = get_string('unreadmsgs','block_gmail'); $unreadmsgsstr = ''; $composestr = get_string('compose', 'block_gmail'); $inboxstr = get_string('inbox', 'block_gmail'); // Obtain link option $newwinlnk = get_config('blocks/gmail', 'newwinlink'); $composelink = '<a ' . ($newwinlnk ? 'target="_new"' : '') . ' href="' . 'http://mail.google.com/a/' . $this->domain . '/?AuthEventSource=SSO#compose">' . $composestr . '</a>'; $inboxlink = '<a ' . ($newwinlnk ? 'target="_new"' : '') . ' href="' . 'http://mail.google.com/a/' . $this->domain . '">' . $inboxstr . '</a>'; $this->content->items[] = '<img src="' . $OUTPUT->pix_url('gmail', 'block_gmail') . '" alt="message" /> ' . $inboxlink . ' ' . $composelink . ' ' . $unreadmsgsstr . '<br/>'; // Only show as many messages as specified in config $countmsg = true; if (!($msgnumber = get_config('blocks/gmail', 'msgnumber'))) { // 0 msg means as many as you want. $countmsg = false; } $mc = 0; // only show the detail if they have access to it if (!has_capability('block/gmail:viewlist', $this->page->context)) { $mc = count($msgs); $this->content->items[] = get_string('unread', 'block_gmail', $mc) . ($mc == 1 ? '' : 's') . '<br/>'; } else { foreach ($msgs as $msg) { if ($countmsg and $mc == $msgnumber) { break; } $mc++; // Displaying Message Data $author = $msg->get_author(); $author->get_name(); $summary = $msg->get_description(); // Google partners need a special gmail url $servicelink = $msg->get_link(); $servicelink = str_replace('http://mail.google.com/mail', 'http://mail.google.com/a/' . $this->domain, $servicelink); // To Save Space given them option to show first and last or just last name $authornames = explode(" ", $author->get_name()); $author_first = array_shift($authornames); $author_last = array_shift($authornames); // Show first Name if (!($showfirstname = get_config('blocks/gmail', 'showfirstname'))) { $author_first = ''; } // Show last Name if (!($showlastname = get_config('blocks/gmail', 'showlastname'))) { $author_last = ''; } // I should do clean_param($summary, PARAM_TEXT) But then ' will have \' if ($newwinlnk) { $text = '<a target="_new" title="' . format_string($summary); $text .= '" href="' . $servicelink . '">' . format_string($msg->get_title()) . '</a> ' . $author_first . ' ' . $author_last; $this->content->items[] = $text; } else { $text = '<a title="' . format_string($summary); $text .= '" href="' . $servicelink . '">' . format_string($msg->get_title()) . '</a> ' . $author_first . ' ' . $author_last; $this->content->items[] = $text; } } } } return $this->content; }
function test_failfeed() { $feed = new moodle_simplepie('http://111xxxxxxxxxxxxxmoodle.org/'); $this->assertTrue($feed->error()); }
function test_redirect() { global $CFG; $feed = new moodle_simplepie(); $feed->set_timeout(self::TIMEOUT); $feed->set_feed_url(self::REDIRECTURL); $feed->init(); $this->assertNull($feed->error()); $this->assertEquals($feed->get_title(), 'Moodle News'); $this->assertEquals($feed->get_link(), 'http://moodle.org/mod/forum/view.php?f=1'); }
/** * cron - goes through all the feeds. If the feed has a skipuntil value * that is less than the current time cron will attempt to retrieve it * with the cache duration set to 0 in order to force the retrieval of * the item and refresh the cache. * * If a feed fails then the skipuntil time of that feed is set to be * later than the next expected cron time. The amount of time will * increase each time the fetch fails until the maximum is reached. * * If a feed that has been failing is successfully retrieved it will * go back to being handled as though it had never failed. * * CRON should therefor process requests for permanently broken RSS * feeds infrequently, and temporarily unavailable feeds will be tried * less often until they become available again. * * @return boolean Always returns true */ function cron() { global $CFG, $DB; require_once $CFG->libdir . '/simplepie/moodle_simplepie.php'; // Get the legacy cron time, strangely the cron property of block_base // does not seem to get set. This means we must retrive it here. $this->cron = $DB->get_field('block', 'cron', array('name' => 'rss_client')); // We are going to measure execution times $starttime = microtime(); $starttimesec = time(); // Fetch all site feeds. $rs = $DB->get_recordset('block_rss_client'); $counter = 0; mtrace(''); foreach ($rs as $rec) { mtrace(' ' . $rec->url . ' ', ''); // Skip feed if it failed recently. if ($starttimesec < $rec->skipuntil) { mtrace('skipping until ' . userdate($rec->skipuntil)); continue; } // Fetch the rss feed, using standard simplepie caching // so feeds will be renewed only if cache has expired core_php_time_limit::raise(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()) { // Skip this feed (for an ever-increasing time if it keeps failing). $rec->skiptime = $this->calculate_skiptime($rec->skiptime); $rec->skipuntil = time() + $rec->skiptime; $DB->update_record('block_rss_client', $rec); mtrace("Error: could not load/find the RSS feed - skipping for {$rec->skiptime} seconds."); } else { mtrace('ok'); // It worked this time, so reset the skiptime. if ($rec->skiptime > 0) { $rec->skiptime = 0; $rec->skipuntil = 0; $DB->update_record('block_rss_client', $rec); } // Only increase the counter when a feed is sucesfully refreshed. $counter++; } } $rs->close(); // Show times mtrace($counter . ' feeds refreshed (took ' . microtime_diff($starttime, microtime()) . ' seconds)'); return true; }
public function test_redirect() { $feed = new moodle_simplepie($this->getExternalTestFileUrl('/rss_redir.php'), self::TIMEOUT); $this->assertNull($feed->error()); $this->assertSame('Moodle News', $feed->get_title()); $this->assertSame('http://moodle.org/mod/forum/view.php?f=1', $feed->get_link()); }
/** * Given a record in the {blog_external} table, checks the blog's URL * for new entries not yet copied into Moodle. * * @param object $externalblog * @return boolean False if the Feed is invalid */ function blog_sync_external_entries($externalblog) { global $CFG, $DB; require_once $CFG->libdir . '/simplepie/moodle_simplepie.php'; $rssfile = new moodle_simplepie_file($externalblog->url); $filetest = new SimplePie_Locator($rssfile); if (!$filetest->is_feed($rssfile)) { $externalblog->failedlastsync = 1; $DB->update_record('blog_external', $externalblog); return false; } else { if (!empty($externalblog->failedlastsync)) { $externalblog->failedlastsync = 0; $DB->update_record('blog_external', $externalblog); } } // Delete all blog entries associated with this external blog blog_delete_external_entries($externalblog); $rss = new moodle_simplepie($externalblog->url); if (empty($rss->data)) { return null; } foreach ($rss->get_items() as $entry) { // If filtertags are defined, use them to filter the entries by RSS category if (!empty($externalblog->filtertags)) { $containsfiltertag = false; $categories = $entry->get_categories(); $filtertags = explode(',', $externalblog->filtertags); $filtertags = array_map('trim', $filtertags); $filtertags = array_map('strtolower', $filtertags); foreach ($categories as $category) { if (in_array(trim(strtolower($category->term)), $filtertags)) { $containsfiltertag = true; } } if (!$containsfiltertag) { continue; } } $newentry = new stdClass(); $newentry->userid = $externalblog->userid; $newentry->module = 'blog_external'; $newentry->content = $externalblog->id; $newentry->uniquehash = $entry->get_permalink(); $newentry->publishstate = 'site'; $newentry->format = FORMAT_HTML; $newentry->subject = $entry->get_title(); $newentry->summary = $entry->get_description(); //our DB doesnt allow null creation or modified timestamps so check the external blog didnt supply one $entrydate = $entry->get_date('U'); if (empty($entrydate)) { $newentry->created = time(); $newentry->lastmodified = time(); } else { $newentry->created = $entrydate; $newentry->lastmodified = $entrydate; } $textlib = textlib_get_instance(); if ($textlib->strlen($newentry->uniquehash) > 255) { // The URL for this item is too long for the field. Rather than add // the entry without the link we will skip straight over it. // RSS spec says recommended length 500, we use 255. debugging('External blog entry skipped because of oversized URL', DEBUG_DEVELOPER); continue; } $id = $DB->insert_record('post', $newentry); // Set tags if ($tags = tag_get_tags_array('blog_external', $externalblog->id)) { tag_set('post', $id, $tags); } } $DB->update_record('blog_external', array('id' => $externalblog->id, 'timefetched' => mktime())); }