1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
19: $plugin_description = gettext("Merges several RSS feeds into one.");
20: $plugin_author = "Malte Müller (acrylian)";
21: $plugin_disable = (class_exists('SimpleXMLElement')) ? false : gettext('PHP <em>SimpleXML</em> is required.');
22: $option_interface = 'MergedRSSOptions';
23:
24:
25: if (isset($_GET['mergedrss'])) {
26:
27: $feeds = getOption('mergedrss_feeds');
28: $feeds = explode(';', $feeds);
29: if (count($feeds) < 0) {
30: exitZP();
31: }
32:
33: header("Content-type: text/xml");
34:
35:
36: $RSS_date = date("r", mktime(10, 0, 0, 9, 8, 2010));
37: if (isset($_GET['lang'])) {
38: $locale = sanitize($_GET['lang']);
39: } else {
40: $locale = getOption('locale');
41: }
42: $gallery = new Gallery();
43:
44: $MergedRSS = new MergedRSS($feeds, getBare(get_language_string($gallery->getTitle(), $locale)), FULLWEBPATH, getBare(get_language_string($gallery->getDesc(), $locale)), $RSS_date);
45:
46:
47: $mergedrss_feeditems = getOption('mergedrss_items');
48: if (empty($mergedrss_feeditems)) {
49: $mergedrss_feeditems = 10;
50: }
51: $MergedRSS->export(false, true, $mergedrss_feeditems);
52: exitZP();
53: }
54:
55: class MergedRSSOptions {
56:
57: function __construct() {
58: setOptionDefault('mergedrss_items', 10);
59: }
60:
61: function getOptionsSupported() {
62: return array(
63: gettext('RSS feeds to merge') => array('key' => 'mergedrss_feeds', 'type' => OPTION_TYPE_TEXTAREA,
64: 'order' => 11,
65: 'multilingual' => false,
66: 'desc' => gettext('Enter the full urls of the feeds to merge separated by semicolons (e.g. "http://www.domain1.com/rss; http://www.domain2.com/rss")')),
67: gettext('Feed items:') => array('key' => 'mergedrss_items', 'type' => OPTION_TYPE_TEXTBOX,
68: 'order' => 2,
69: 'desc' => gettext("The number of new entries you want to appear in your site’s RSS feed")),
70: );
71: }
72:
73: function handleOption($option, $currentValue) {
74:
75: }
76:
77: }
78:
79: class MergedRSS {
80:
81: private $myFeeds = null;
82: private $myTitle = null;
83: private $myLink = null;
84: private $myDescription = null;
85: private $myPubDate = null;
86: private $myCacheTime = null;
87:
88:
89: public function __construct($feeds, $channel_title = null, $channel_link = null, $channel_description = null, $channel_pubdate = null, $cache_time_in_seconds = 86400) {
90:
91: $this->myTitle = $channel_title;
92: $this->myLink = $channel_link;
93: $this->myDescription = $channel_description;
94: $this->myPubDate = $channel_pubdate;
95: $this->myCacheTime = $cache_time_in_seconds;
96:
97:
98: $this->myFeeds = array();
99:
100:
101: if (!is_array($feeds)) {
102: $feeds = array($feeds);
103: }
104: foreach ($feeds as $feed) {
105: $this->myFeeds[] = trim($feed);
106: }
107: }
108:
109:
110: public function export($return_as_string = true, $output = false, $limit = null) {
111:
112: $mergedrss_cache_file = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/rss/mergedrss.xml';
113: $use_mergedrss_cache = file_exists($mergedrss_cache_file) && time() - filemtime($mergedrss_cache_file) < $this->myCacheTime;
114: if ($use_mergedrss_cache) {
115: $xml = file_get_contents($mergedrss_cache_file);
116: } else {
117:
118: $items = array();
119:
120: foreach ($this->myFeeds as $RSS_url) {
121:
122: $cache_file = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/rss/' . self::create_RSS_key($RSS_url) . '.xml';
123:
124:
125: if (strstr($RSS_url, FULLWEBPATH)) {
126: $use_cache = false;
127: } else {
128: $use_cache = file_exists($cache_file) && time() - filemtime($cache_file) < $this->myCacheTime;
129: }
130: if ($use_cache) {
131:
132: $sxe = self::fetch_from_cache($cache_file);
133: $results = $sxe->channel->item;
134: } else {
135:
136: $sxe = self::fetch_from_url($RSS_url);
137: $results = $sxe->channel->item;
138: if ($use_cache) {
139: if (isset($results)) {
140: $sxe->asXML($cache_file);
141: } else {
142:
143: if (file_exists($cache_file)) {
144: $sxe = self::fetch_from_cache($cache_file);
145: $results = $sxe->channel->item;
146: }
147: }
148: }
149: }
150: if (isset($results)) {
151:
152: foreach ($results as $item) {
153: $items[] = $item;
154: }
155: }
156: }
157: }
158: if (!$use_mergedrss_cache) {
159:
160: $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
161: $xml .= "<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n";
162: $xml .= "<channel>\n";
163: if (isset($this->myTitle)) {
164: $xml .= "\t<title>" . $this->myTitle . "</title>\n";
165: }
166: $xml .= "\t<atom:link href=\"" . PROTOCOL . ':/' . WEBPATH . '/index.php?mergedrss' . "\" rel=\"self\" type=\"application/rss+xml\" />\n";
167: if (isset($this->myLink)) {
168: $xml .= "\t<link>" . $this->myLink . "</link>\n";
169: }
170: if (isset($this->myDescription)) {
171: $xml .= "\t<description>" . $this->myDescription . "</description>\n";
172: }
173: if (isset($this->myPubDate)) {
174: $xml .= "\t<pubDate>" . $this->myPubDate . "</pubDate>\n";
175: }
176:
177: if (sizeof($items) > 0) {
178:
179: usort($items, array($this, "self::compare_items"));
180:
181: if (isset($limit)) {
182: array_splice($items, intval($limit));
183: }
184:
185: for ($i = 0; $i < sizeof($items); $i++) {
186: $xml .= $items[$i]->asXML() . "\n";
187: }
188: }
189: $xml .= "</channel>\n</rss>";
190:
191: $rssobj = new SimpleXMLElement($xml);
192: $rssobj->asXML($mergedrss_cache_file);
193: }
194:
195: if ($output) {
196: header('Content-Type: application/xml');
197: echo $xml;
198: }
199:
200: if ($return_as_string) {
201: return $xml;
202: }
203: }
204:
205:
206: private static function compare_items($a, $b) {
207: return strtotime($b->pubDate) - strtotime($a->pubDate);
208: }
209:
210:
211: private static function fetch_from_cache($cache_file) {
212: if (file_exists($cache_file)) {
213: return simplexml_load_file($cache_file);
214: }
215: return null;
216: }
217:
218:
219: private static function fetch_from_url($url) {
220:
221: $sxe = new SimpleXMLElement($url, null, true);
222: return $sxe;
223: }
224:
225:
226: private static function create_RSS_key($url) {
227: return preg_replace('/[^a-zA-Z0-9\.]/', '_', $url) . 'cache';
228: }
229: }
230: ?>