Fixes on feeds:
[banana.git] / banana / feed.inc.php
CommitLineData
e02edbfe 1<?php
2/********************************************************************************
3* banana/feed.inc.php : Feed Builder
4* ------------------------
5*
6* This file is part of the banana distribution
7* Copyright: See COPYING files that comes with this distribution
8********************************************************************************/
9
10require_once dirname(__FILE__) . '/banana.inc.php';
11
12define('BANANA_FEED_VERSION', '0.1');
13
14class BananaFeed
15{
16 /** Structure version
17 */
18 private $version;
19
20 /** Feed name
21 */
22 public $group;
23
24 /** Feed description
25 */
26 public $description;
27
28 /** A 'ordered by id' spool of the last messages
29 * Each Message is an array with :
30 * array('author' => author, 'date' => date (UNIX TS), 'title' => subject, 'body' => html body,
31 * 'link' => link, 'reply' => reply)
32 */
33 public $messages = array();
34
35 /** Create an empty feed
36 */
37 private function __construct()
38 {
39 $this->version = BANANA_FEED_VERSION;
40 $this->group = Banana::$group;
41 $this->description = Banana::$protocole->getDescription();
42 }
43
44 /** Update the feed, using current settings of Banana
45 * Calling this function suppose that Banana::$spool is the spool of the current box
46 */
47 public function update()
48 {
49 if (!Banana::$spool || Banana::$spool->group != $this->group) {
50 return false;
51 }
52 if (!Banana::$spool->ids) {
53 $spool_indexes = array();
54 } else {
55 $spool_indexes = Banana::$spool->ids;
56 sort($spool_indexes, SORT_NUMERIC);
57 $spool_indexes = array_slice($spool_indexes, -Banana::$feed_size, Banana::$feed_size);
58 }
59 $feed_indexes = array_keys($this->messages);
60 $old = array_diff($feed_indexes, $spool_indexes);
61 foreach ($old as $key) {
62 unset($this->messages[$key]);
63 }
64 $new = array_diff($spool_indexes, $feed_indexes);
65 foreach ($new as $key) {
66 $message =& Banana::$protocole->getMessage($key);
67 $array = array();
68 $array['author'] = $message->getAuthorName();
69 $array['date'] = $message->getHeaderValue('Date');
70 $array['title'] = $message->getHeaderValue('Subject');
71 $array['body'] = $message->toHtml();
72 $array['link'] = Banana::$page->makeUrl(array('group' => $this->group, 'artid' => $key));
73 if (Banana::$protocole->canSend()) {
74 $array['reply'] = Banana::$page->makeUrl(array('group' => $this->group, 'artid' => $key, 'action' => 'new'));
75 }
76 $this->messages[$key] = $array;
77 }
8879bc6c 78 uasort($this->messages, Array('BananaFeed', 'compare'));
e02edbfe 79 $this->writeToFile();
80 }
81
82 /** Get the spool corresponding with the current settings of Banana
83 */
84 static public function &getFeed()
85 {
86 $feed =& BananaFeed::readFromFile();
87 if (!$feed) {
88 $feed = new BananaFeed();
89 }
90 if (Banana::$feed_updateOnDemand) {
91 $feed->update();
92 }
93 return $feed;
94 }
95
96 /** Return the cache file name
97 */
98 static private function filename()
99 {
100 $file = Banana::$spool_root . '/' . Banana::$protocole->name() . '/';
101 if (!is_dir($file)) {
102 mkdir($file);
103 }
104 return $file . Banana::$protocole->filename() . '_feed';
105 }
106
107 /** Read a feed from a cache file
108 */
109 static private function &readFromFile()
110 {
111 $feed = null;
112 $file = BananaFeed::filename();
113 if (!file_exists($file)) {
114 return $feed;
115 }
116 $feed = unserialize(file_get_contents($file));
117 if ($feed->version != BANANA_FEED_VERSION) {
118 $feed = null;
119 }
120 return $feed;
121 }
122
123 /** Write a feed to a cache file
124 */
125 private function writeToFile()
126 {
127 $file = BananaFeed::filename();
128 file_put_contents($file, serialize($this));
129 }
130
131 /** Merge to feeds into a new one
132 */
133 static public function &merge(&$feed1, &$feed2, $name, $description = null)
134 {
135 if (!$feed1) {
136 $feed = null;
137 $feed1 =& $feed2;
138 $feed2 =& $feed;
139 }
140 if ($feed1->group == $name) {
141 $master =& $feed1;
142 $slave =& $feed2;
143 } else if ($feed2 && $feed2->group == $name) {
144 $master =& $feed2;
145 $slave =& $feed1;
146 } else {
147 $master = new BananaFeed();
148 $master->group = $name;
149 $master->description = $description;
150 foreach ($feed1->messages as $key=>$message) {
151 $message['title'] = '[' . $feed1->group . '] ' . $message['title'];
152 $master->messages[$feed1->group . '-' . $key] = $message;
153 }
154 $slave =& $feed2;
155 }
156 if (!$slave) {
157 return $master;
158 }
159 $messages = array();
8879bc6c 160 $m1 = end($master->messages);
161 $m2 = end($slave->messages);
e02edbfe 162 for ($i = 0 ; $i < 2 * Banana::$feed_size && ($m1 || $m2) ; $i++) {
163 if ($m2 && (!$m1 || $m1['date'] < $m2['date'])) {
164 $m2['title'] = '[' . $feed2->group . '] ' . $m2['title'];
165 $messages[$slave->group . '-' . key($slave->messages)] = $m2;
8879bc6c 166 $m2 = prev($slave->messages);
e02edbfe 167 } else {
168 $messages[key($master->messages)] = $m1;
8879bc6c 169 $m1 = prev($master->messages);
e02edbfe 170 }
171 }
8879bc6c 172 uasort($messages, array('BananaFeed', 'compare'));
e02edbfe 173 $master->messages =& $messages;
174 return $master;
175 }
176
8879bc6c 177 static function compare($a, $b)
178 {
179 if ($a['date'] == $b['date']) {
180 return 0;
181 }
182 return $a['date'] < $b['date'] ? -1 : 1;
183 }
184
e02edbfe 185 /** Generate the feed xml
186 */
187 public function toXML()
188 {
189 Banana::$page->assign_by_ref('feed', $this);
190 return Banana::$page->feed();
191 }
192}
193
194// vim:set et sw=4 sts=4 ts=4 enc=utf-8:
195?>