aggregator.module 29.2 KB
Newer Older
1
<?php
2
// $Id$
3

Dries's avatar
   
Dries committed
4
function import_help() {
5
 ?>
Dries's avatar
   
Dries committed
6
7
8
9
10
  <p>In Drupal you have <i>feeds</i> and <i>bundles</i>.   Feeds define news sources and bundles categoriz syndicated content by source, topic or any other heuristic.   Bundles provide a generalized way of creating composite feeds.  They allow you, for example, to combine various sport-related feeds into one bundle called "Sport".</p>
  <p>You can have several providers of news feeds.  You can add a feed by clicking the "add feed" link on the import administration pages.  Give the feed a name, supply the URI and a comma-separated list of attributes that you want to associate the feed with.  The update interval defines how often Drupal should go out to try and grab fresh content.  The expiration time defines how long syndicated content is kept in the database.  So set the update and expiration time and save your settings.  You have just defined your first feed.  If you have more feeds repeat as necessary.</p>
  <p>To verify whether your feed works, press "update items" at the overview page.  The number of items that have been sucessfully fetched, should then become visible in the third column of the feed overview.</p>
  <p>Now you have to define some bundles.  Bundles look for feeds that contain one of the keywords associated with the bundle and display those feeds together.  To define a bundle you have to give it a name and a comma-separated list of keywords just like this is the case for feeds.</p>
  <p>Your newly created bundle will now show up in the list of blocks that you can see at the block related administration pages.  There you can customize where and when your bundles will be displayed.</p>
11
12
13
 <?php
}

Dries's avatar
   
Dries committed
14
15
16
17
function import_conf_options() {
  $number = array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 30 => 30, 35 => 35, 40 => 40, 45 => 45, 50 => 50, 55 => 55, 60 => 60, 65 => 65, 70 => 70, 75 => 75, 80 => 80, 85 => 85, 90 => 90, 95 => 95, 100 => 100);
  $output .= form_select("Items per block", "import_block_limit", variable_get("import_block_limit", 15), $number, "The maximum number of items displayed in one block.");
  $output .= form_select("Items per page", "import_page_limit", variable_get("import_page_limit", 75), $number, "The maximum number of items displayed on one page.");
Dries's avatar
   
Dries committed
18

Dries's avatar
   
Dries committed
19
20
21
  return $output;
}

Dries's avatar
   
Dries committed
22
function import_perm() {
Dries's avatar
   
Dries committed
23
  return array("administer news feeds", "access news feeds");
Dries's avatar
   
Dries committed
24
25
26
}

function import_link($type) {
Dries's avatar
   
Dries committed
27
28
29
30
31
  if ($type == "admin" && user_access("administer news feeds")) {
    $links[] = "<a href=\"admin.php?mod=import\">news feeds</a>";
  }

  if ($type == "page" && user_access("access news feeds")) {
Dries's avatar
   
Dries committed
32
    $links[] = "<a href=\"module.php?mod=import\" title=\"". t("Read the latest news from syndicated websites.") ."\">". t("news feeds") ."</a>";
Dries's avatar
   
Dries committed
33
34
35
  }

  return $links ? $links : array();
Dries's avatar
   
Dries committed
36
37
}

Dries's avatar
   
Dries committed
38
function import_cron() {
Dries's avatar
   
Dries committed
39
40
41
42
43
44
45
  $result = db_query("SELECT * FROM feed WHERE timestamp + refresh < ". time());
  while ($feed = db_fetch_array($result)) {
    import_refresh($feed);
  }
}

function import_update() {
46
47
  $result = db_query("SELECT * FROM feed");
  while ($feed = db_fetch_array($result)) {
Dries's avatar
   
Dries committed
48
49
50
51
    import_refresh($feed);
  }
}

Dries's avatar
   
Dries committed
52
53
function import_format_item($item, $feed = 0) {
  global $theme, $user;
Dries's avatar
   
Dries committed
54

Dries's avatar
   
Dries committed
55
  if ($user->uid && user_access("post blogs")) {
Dries's avatar
   
Dries committed
56
    $output .= "<a href=\"module.php?mod=node&op=add&type=blog&iid=$item->iid\" title=\"". t("Comment on this news item in your personal blog.") ."\"><img src=\"". $theme->image("blog.gif") ."\" border=\"0\" width=\"12\" height=\"16\" alt=\"". t("Blog this item") ."\" /></a> ";
Dries's avatar
   
Dries committed
57
58
59
  }

  $output .= "<a href=\"". check_output($item->link) ."\" target=\"new\">". check_output($item->title) ."</a>";
60

Dries's avatar
   
Dries committed
61
  return $output ."<br />";
62
63
}

Dries's avatar
   
Dries committed
64
65
function import_bundle_block($attributes) {

66
67
68
  if ($attributes) {
    $keys = explode(",", $attributes);
    foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'";
69

Dries's avatar
   
Dries committed
70
    $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15));
Dries's avatar
   
Dries committed
71
  }
72

Dries's avatar
   
Dries committed
73
74
  while ($item = db_fetch_object($result)) {
    $output .= import_format_item($item);
75
  }
Dries's avatar
   
Dries committed
76
77

  return $output;
78
79
}

Dries's avatar
   
Dries committed
80
81
function import_feed_block($feed) {
  $result = db_query("SELECT * FROM item WHERE fid = '$feed->fid' ORDER BY iid DESC LIMIT ". variable_get("import_block_limit", 15));
82

Dries's avatar
   
Dries committed
83
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
84
    $output .= import_format_item($item);
Dries's avatar
   
Dries committed
85
  }
Dries's avatar
   
Dries committed
86

Dries's avatar
   
Dries committed
87
88
89
  return $output;
}

Dries's avatar
   
Dries committed
90
function import_block() {
Dries's avatar
   
Dries committed
91
  return array_merge(import_get_bundles(), import_get_feeds());
Dries's avatar
   
Dries committed
92
93
}

Dries's avatar
   
Dries committed
94
function import_get_bundles($attributes = 0) {
Dries's avatar
   
Dries committed
95
  $result = db_query("SELECT * FROM bundle ORDER BY title");
Dries's avatar
   
Dries committed
96

Dries's avatar
   
Dries committed
97
  $i = 0;
Dries's avatar
   
Dries committed
98
  while ($bundle = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
99
    $block[$i]["subject"] = $bundle->title;
Dries's avatar
   
Dries committed
100
    $block[$i]["content"] = import_bundle_block($bundle->attributes) ."<p><div align=\"right\"><a href=\"module.php?mod=import&op=bundle&id=$bundle->bid\" title=\"". t("View this bundle's recent news.") ."\">". t("more") ."</a></div></p>";
Dries's avatar
   
Dries committed
101
    $block[$i]["info"] = "$bundle->title bundle";
Dries's avatar
   
Dries committed
102

Dries's avatar
   
Dries committed
103
104
    $i++;
  }
Dries's avatar
   
Dries committed
105

Dries's avatar
   
Dries committed
106
  return $block;
Dries's avatar
   
Dries committed
107
108
}

Dries's avatar
   
Dries committed
109
function import_get_feeds($attributes = 0) {
Dries's avatar
   
Dries committed
110
  $result = db_query("SELECT * FROM feed ORDER BY fid");
Dries's avatar
   
Dries committed
111
112
113

  $i = 0;
  while ($feed = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
114
    $block[$i]["subject"] = $feed->title;
Dries's avatar
   
Dries committed
115
    $block[$i]["content"] = import_feed_block($feed) ."<p><div align=\"right\"><a href=\"module.php?mod=import&op=feed&id=$feed->fid\" title=\"". t("View this feed's recent news.") ."\">". t("more") ."</a></div></p>";
Dries's avatar
   
Dries committed
116
    $block[$i]["info"] = "$feed->title feed";
Dries's avatar
   
Dries committed
117
118
119
120

    $i++;
  }

Dries's avatar
   
Dries committed
121
  return $block;
Dries's avatar
   
Dries committed
122
123
}

Dries's avatar
   
Dries committed
124
function import_remove($feed) {
Dries's avatar
   
Dries committed
125
126
  db_query("DELETE FROM item WHERE fid = '". $feed["fid"] ."'");
  return "feed '". $feed["title"] ."' reset.";
Dries's avatar
   
Dries committed
127
128
}

Dries's avatar
   
Dries committed
129
function import_refresh($feed) {
130

Dries's avatar
   
Dries committed
131
132
133
134
  /*
  ** Check whether the feed is properly configured:
  */

Dries's avatar
   
Dries committed
135
136
  if (!ereg("^http://|ftp://", $feed["url"])) {
    watchdog("warning", "import: invalid or missing URL for '". $feed["title"] ."'");
Dries's avatar
   
Dries committed
137
138
139
  }

  /*
Dries's avatar
   
Dries committed
140
  ** Grab the news items:
Dries's avatar
   
Dries committed
141
142
  */

Dries's avatar
   
Dries committed
143
  if ($fp = @fopen($feed["url"], "r")) {
144
    // fetch data:
Dries's avatar
   
Dries committed
145
146
147
    while (!feof($fp)) {
      $data .= fgets($fp, 128);
    }
Dries's avatar
Dries committed
148
    fclose($fp);
Dries's avatar
   
Dries committed
149
150
151
152
153

    // initialize the translation table:
    $tt = array_flip(get_html_translation_table(HTML_ENTITIES));
    $tt["&apos;"] = "'";

Dries's avatar
   
Dries committed
154
155
156
    /*
    ** Remove unsupported tags or sub-elements:
    */
Dries's avatar
   
Dries committed
157

Dries's avatar
   
Dries committed
158
159
    $data = ereg_replace("<textinput([^s].*)</textinput>", "", $data);
    $data = ereg_replace("<image([^s].*)</image>", "", $data);
Dries's avatar
   
Dries committed
160

Dries's avatar
   
Dries committed
161
162
163
    /*
    ** Extract and process channel information:
    */
164

Dries's avatar
   
Dries committed
165
    $channel = ereg_replace("<item([^s].*)</item>", "", $data);
Dries's avatar
   
Dries committed
166

Dries's avatar
   
Dries committed
167
168
169
    eregi("<title>(.*)</title>", $channel, $title);
    eregi("<link>(.*)</link>", $channel, $link);
    eregi("<description>(.*)</description>", $channel, $description);
Dries's avatar
   
Dries committed
170

Dries's avatar
   
Dries committed
171
172
173
174
175
176
177
178
    /*
    ** Strip invalid tags and provide default values (if required):
    */

    $link = strip_tags($link[1]);
    $description = filter(strtr($description[1], $tt));

    db_query("UPDATE feed SET timestamp = '". time() ."', link = '". check_input($link) ."', description = '". check_input($description) ."' WHERE fid = '". $feed["fid"] ."'");
Dries's avatar
   
Dries committed
179

Dries's avatar
   
Dries committed
180
181
182
    /*
    ** Extract and process individual items:
    */
Dries's avatar
   
Dries committed
183

Dries's avatar
   
Dries committed
184
185
    eregi("<item([^s].*)</item>", $data, $data);
    // print "<pre>". htmlentities($data[0]) ."</pre>";
186

Dries's avatar
   
Dries committed
187
    $items = array_reverse(explode("</item>", $data[0]));
Dries's avatar
   
Dries committed
188

Dries's avatar
   
Dries committed
189
190
    foreach ($items as $item) {
      unset($title, $link, $author, $description);
Dries's avatar
   
Dries committed
191

Dries's avatar
   
Dries committed
192
193
194
195
      $t = eregi("<title>(.*)</title>", $item, $title);
      $l = eregi("<link>(.*)</link>", $item, $link);
      $a = eregi("<author>(.*)</author>", $item, $author);
      $d = eregi("<description>(.*)</description>", $item, $description);
Dries's avatar
   
Dries committed
196

Dries's avatar
   
Dries committed
197
      if ($t || $l || $a || $d) {
198

Dries's avatar
   
Dries committed
199
200
201
        /*
        ** Strip invalid tags and provide default values (if required):
        */
Dries's avatar
Dries committed
202

Dries's avatar
   
Dries committed
203
        $title = strip_tags(strtr($title[1] ? $title[1] : substr(strip_tags(strtr($description[1], $tt)), 0, 30), $tt));
Dries's avatar
   
Dries committed
204
205
206
        $link = strip_tags($link[1] ? $link[1] : $feed["link"]);
        $author = strip_tags($author[1]);
        $description = filter(strtr($description[1], $tt));
Dries's avatar
Dries committed
207

Dries's avatar
   
Dries committed
208
        // print "<pre>title = ". htmlentities($title) ."\n\ndescription = ". htmlentities($description) ."\n\nlink = ". htmlentities($link) ."</pre><hr />";
Dries's avatar
   
Dries committed
209

Dries's avatar
   
Dries committed
210
        /*
Dries's avatar
   
Dries committed
211
212
213
        ** Save this item.  Try to avoid duplicate entries as much as
        ** possible.  If we find a duplicate entry, we resolve it and
        ** pass along its ID such that we can update it (when needed).
Dries's avatar
   
Dries committed
214
        */
Dries's avatar
   
Dries committed
215

Dries's avatar
   
Dries committed
216
217
218
219
220
221
222
223
        if ($link && $link != $feed["link"] && $link != $feed["url"]) {
          $entry = db_fetch_object(db_query("SELECT iid FROM item WHERE fid = '". check_query($feed["fid"]) ."' AND link = '". check_query($link) ."'"));
        }
        else {
          $entry = db_fetch_object(db_query("SELECT iid FROM item WHERE fid = '". check_query($feed["fid"]) ."' AND title = '". check_query($title) ."'"));
        }

        import_save_item(array(iid => $entry->iid, fid => $feed["fid"], title => $title, link => $link, author => $author, description => $description, attributes => $feed["attributes"]));
224
225
      }
    }
Dries's avatar
   
Dries committed
226
227

    /*
Dries's avatar
   
Dries committed
228
    ** Remove all the old, expired items:
Dries's avatar
   
Dries committed
229
230
231
232
233
234
235
236
237
238
    */

    unset($items);

    $result = db_query("SELECT iid FROM item WHERE fid = '". $feed["fid"] ."' ORDER BY timestamp");

    while ($item = db_fetch_object($result)) {
      $items[] = "iid = '$item->iid'";
    }

Dries's avatar
   
Dries committed
239
    if (sizeof($items) > 50) {
Dries's avatar
   
Dries committed
240
241
242
      db_query("DELETE FROM item WHERE ". implode(" OR ", array_slice($items, 0, - 50)));
    }

Dries's avatar
   
Dries committed
243
244
  }
  else {
Dries's avatar
   
Dries committed
245
    watchdog("warning", "import: failed to syndicate from '". $feed["title"] ."'". ($errstr ? ": $errstr" : ""));
246
  }
Dries's avatar
   
Dries committed
247

Dries's avatar
   
Dries committed
248
  return "feed '". $feed["title"] ."' updated.";
249
250
}

Dries's avatar
   
Dries committed
251
function import_save_item($edit) {
Dries's avatar
   
Dries committed
252
253
  if ($edit["iid"] && $edit["title"]) {
    db_query("UPDATE item SET title = '". check_input($edit["title"]) ."', link = '". check_input($edit["link"]) ."', author = '". check_input($edit["author"]) ."', description = '". check_input($edit["description"]) ."', attributes = '". check_input($edit["attributes"]) ."' WHERE iid = '". check_input($edit["iid"]) ."'");
254
  }
Dries's avatar
   
Dries committed
255
256
  else if ($edit["iid"]) {
    db_query("DELETE FROM item WHERE iid = '". check_input($edit["iid"]) ."'");
257
  }
Dries's avatar
   
Dries committed
258
  else if ($edit["title"] && $edit["link"]) {
Dries's avatar
   
Dries committed
259
    db_query("INSERT INTO item (fid, title, link, author, description, attributes, timestamp) VALUES ('". check_input($edit["fid"]) ."', '". check_input($edit["title"]) ."', '". check_input($edit["link"]) ."', '". check_input($edit["author"]) ."', '". check_input($edit["description"]) ."', '". check_input($edit["attributes"]) ."', '". time() ."')");
260
261
262
  }
}

Dries's avatar
   
Dries committed
263
function import_form_bundle($edit = array()) {
264

Dries's avatar
   
Dries committed
265
266
  $form .= form_textfield("Title", "title", $edit["title"], 50, 64, "The name of the bundle.");
  $form .= form_textfield("Attributes", "attributes", $edit["attributes"], 50, 128, "A comma-seperated list of keywords describing the bundle.");
267
268
269

  $form .= form_submit("Submit");

Dries's avatar
   
Dries committed
270
  if ($edit["bid"]) {
Dries's avatar
   
Dries committed
271
    $form .= form_submit("Delete");
Dries's avatar
   
Dries committed
272
    $form .= form_hidden("bid", $edit["bid"]);
273
274
  }

Dries's avatar
   
Dries committed
275
  return form($form);
276
277
}

Dries's avatar
   
Dries committed
278
function import_save_bundle($edit) {
Dries's avatar
   
Dries committed
279
280
  if ($edit["bid"] && $edit["title"]) {
    db_query("UPDATE bundle SET title = '". check_input($edit["title"]) ."', attributes = '". check_input($edit["attributes"]) ."' WHERE bid = '". check_input($edit["bid"]) ."'");
281
  }
Dries's avatar
   
Dries committed
282
283
  else if ($edit["bid"]) {
    db_query("DELETE FROM bundle WHERE bid = '". check_input($edit["bid"]) ."'");
284
  }
Dries's avatar
   
Dries committed
285
286
  else if ($edit["title"]) {
    db_query("INSERT INTO bundle (title, attributes) VALUES ('". check_input($edit["title"]) ."', '". check_input($edit["attributes"]) ."')");
287
  }
Dries's avatar
   
Dries committed
288
289

  module_rehash_blocks("import");
290
291
}

Dries's avatar
   
Dries committed
292
function import_form_feed($edit = array()) {
293
294
295

  $period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 172800 => format_interval(172800), 259200 => format_interval(259200), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200));

Dries's avatar
   
Dries committed
296
297
298
  if ($edit["refresh"] == "") {
    $edit["refresh"] = 3600;
  }
Dries's avatar
   
Dries committed
299

Dries's avatar
   
Dries committed
300
301
302
303
  $form .= form_textfield("Title", "title", $edit["title"], 50, 64, "The name of the feed; typically the name of the website you syndicate content from.");
  $form .= form_textfield("Url", "url", $edit["url"], 50, 128, "The fully-qualified URL of the feed.");
  $form .= form_textfield("Attributes", "attributes", $edit["attributes"], 50, 128, "A comma-seperated list of keywords describing the feed.");
  $form .= form_select("Update interval", "refresh", $edit["refresh"], $period, "The refresh interval indicating how often you want to update this feed.  Requires crontab.");
304
305
306

  $form .= form_submit("Submit");

Dries's avatar
   
Dries committed
307
  if ($edit["fid"]) {
Dries's avatar
   
Dries committed
308
    $form .= form_submit("Delete");
Dries's avatar
   
Dries committed
309
    $form .= form_hidden("fid", $edit["fid"]);
310
311
  }

Dries's avatar
   
Dries committed
312
  return form($form);
313
314
}

Dries's avatar
   
Dries committed
315
function import_save_feed($edit) {
Dries's avatar
   
Dries committed
316
317
318
  if ($edit["fid"] && $edit["title"]) {
    db_query("UPDATE feed SET title = '". check_input($edit["title"]) ."', url = '". check_input($edit["url"]) ."', attributes = '". check_input($edit["attributes"]) ."', refresh = '". check_input($edit["refresh"]) ."' WHERE fid = '". check_input($edit["fid"]) ."'");
    db_query("DELETE FROM item WHERE fid = '". check_input($edit["fid"]) ."'");
319
  }
Dries's avatar
   
Dries committed
320
321
322
  else if ($edit["fid"]) {
    db_query("DELETE FROM feed WHERE fid = '". check_input($edit["fid"]) ."'");
    db_query("DELETE FROM item WHERE fid = '". check_input($edit["fid"]) ."'");
323
  }
Dries's avatar
   
Dries committed
324
325
  else if ($edit["title"]) {
    db_query("INSERT INTO feed (title, url, attributes, refresh) VALUES ('". check_input($edit["title"]) ."', '". check_input($edit["url"]) ."', '". check_input($edit["attributes"]) ."', '". check_input($edit["refresh"]) ."')");
326
327
328
  }
}

Dries's avatar
   
Dries committed
329
function import_save_attributes($edit) {
Dries's avatar
   
Dries committed
330
  foreach ($edit as $iid => $value) {
331
    db_query("UPDATE item SET attributes = '". check_input($value) ."' WHERE iid = '". check_input($iid) ."'");
332
333
334
335
  }
  return "attributes has been saved";
}

Dries's avatar
   
Dries committed
336
function import_get_feed($fid) {
337
338
339
  return db_fetch_array(db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"));
}

Dries's avatar
   
Dries committed
340
function import_get_bundle($bid) {
341
342
343
  return db_fetch_array(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'"));
}

Dries's avatar
   
Dries committed
344
function import_view() {
Dries's avatar
   
Dries committed
345
  $result = db_query("SELECT f.*, COUNT(i.iid) AS items FROM feed f LEFT JOIN item i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.timestamp, f.attributes, f.link, f.description ORDER BY f.title");
346

Dries's avatar
   
Dries committed
347
348
  $output .= "<h3>Feed overview</h3>";
  $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
349
  $output .= " <tr><th>title</th><th>attributes</th><th>items</th><th>last update</th><th>next update</th><th colspan=\"3\">operations</th></tr>\n";
350
  while ($feed = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
351
    $output .= " <tr><td>". check_output($feed->title) ."</td><td>". check_output($feed->attributes) ."</td><td>". format_plural($feed->items, "item", "items") ."</td><td>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</td><td>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</td><td><a href=\"admin.php?mod=import&type=feed&op=edit&id=$feed->fid\">edit feed</a></td><td><a href=\"admin.php?mod=import&type=feed&op=remove&id=$feed->fid\">remove items</a></td><td><a href=\"admin.php?mod=import&type=feed&op=update&id=$feed->fid\">update items</a></td></tr>\n";
352
  }
Dries's avatar
   
Dries committed
353
  $output .= "</table>\n";
354
355
356

  $result = db_query("SELECT * FROM bundle ORDER BY title");

Dries's avatar
   
Dries committed
357
358
359
  $output .= "<h3>Bundle overview</h3>";
  $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
  $output .= " <tr><th>title</th><th>attributes</th><th>operations</th></tr>\n";
360
  while ($bundle = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
361
    $output .= " <tr><td>". check_output($bundle->title) ."</td><td>". check_output($bundle->attributes) ."</td><td><a href=\"admin.php?mod=import&type=bundle&op=edit&id=$bundle->bid\">edit bundle</a></td></tr>\n";
362
  }
Dries's avatar
   
Dries committed
363
  $output .= "</table>\n";
364
365
366
367

  return $output;
}

Dries's avatar
   
Dries committed
368
369
function import_fd_form() {

Dries's avatar
   
Dries committed
370
  $form .= form_textfield("Feed directory file", "url", "http://", 64, 128, "The fully-qualified URL of the feed directory file.");
Dries's avatar
   
Dries committed
371
372
  $form .= form_submit("Collect feeds");

Dries's avatar
   
Dries committed
373
  return form($form);
Dries's avatar
   
Dries committed
374
375
376
377
378
379
}

function import_fd_collect($edit) {

  set_time_limit(180);

Dries's avatar
   
Dries committed
380
  if ($fp = @fopen($edit["url"], "r")) {
Dries's avatar
   
Dries committed
381
382
383
384
    // fetch data:
    while (!feof($fp)) {
      $data .= fgets($fp, 128);
    }
Dries's avatar
Dries committed
385
    fclose($fp);
Dries's avatar
   
Dries committed
386
387
388
389
390
391
392
393

    // initialize the translation table:
    $tt = array_flip(get_html_translation_table(HTML_ENTITIES));
    $tt["&apos;"] = "'";

    $items = explode("</channel>", $data);

    foreach ($items as $item) {
Dries's avatar
   
Dries committed
394
      unset($link, $title);
Dries's avatar
   
Dries committed
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411

      // print "<pre>item = ". htmlentities($item) ."\n\n</pre>";

      eregi("<link>(.*)</link>", $item, $link);
      eregi("<title>(.*)</title>", $item, $title);

      $link = strip_tags(strtr($link[1], $tt));
      $title = strip_tags(strtr($title[1], $tt));

      // print "<b>title = $title, link = $link<br /></b>";
      if ($link && $link && !db_fetch_array(db_query("SELECT * FROM feed WHERE url = '". check_input($link) ."'"))) {
        $output .= "<input type=\"checkbox\" name=\"edit[$title]\" value=\"$link\"> ". strtr($title, $tt) ."<br />";
      }
    }

    $output .= "<input type=\"submit\" name=\"op\" value=\"Import feeds\" />\n";

Dries's avatar
   
Dries committed
412
    return form($output);
Dries's avatar
   
Dries committed
413
414
  }
  else {
Dries's avatar
   
Dries committed
415
    print status("failed to open '". $edit["url"] ."': $errstr.");
Dries's avatar
   
Dries committed
416
417
418
  }
}

Dries's avatar
   
Dries committed
419
function import_fd_import($edit) {
Dries's avatar
   
Dries committed
420
421
  if ($edit) {
    foreach ($edit as $title => $link) {
Dries's avatar
   
Dries committed
422
      import_save_feed(array("title" => $title, "url" => $link, "refresh" => 3600));
Dries's avatar
   
Dries committed
423
    }
Dries's avatar
   
Dries committed
424
425
426
  }
}

Dries's avatar
   
Dries committed
427
function import_tag() {
428

Dries's avatar
Dries committed
429
  $result = db_query("SELECT i.*, f.title AS feed FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.iid DESC LIMIT 50");
430

Dries's avatar
   
Dries committed
431
432
  $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
  $output .= " <tr><th>time</th><th>feed</th><th>item</th></tr>\n";
433
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
434
    $output .= " <tr><td valign=\"top\" nowrap=\"nowrap\">". format_date($item->timestamp, "custom", "m/d/y") ."<br />". format_date($item->timestamp, "custom", "H:i") ."</td><td align=\"center\" valign=\"top\" nowrap=\"nowrap\"><a href=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</a></td><td><a href=\"". check_output($item->link) ."\">". check_output($item->title) ."</a>". ($item->description ? "<br /><small><i>". check_output($item->description, 1) ."</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" /></td></tr>\n";
435
  }
Dries's avatar
   
Dries committed
436
437
  $output .= "</table>\n";
  $output .= "<input type=\"submit\" name=\"op\" value=\"Save attributes\" />\n";
438

Dries's avatar
   
Dries committed
439
  return form($output);
440
441
}

Dries's avatar
   
Dries committed
442
function import_admin() {
Dries's avatar
   
Dries committed
443
  global $op, $id, $type, $edit;
Dries's avatar
   
Dries committed
444

Dries's avatar
   
Dries committed
445
  if (user_access("administer news feeds")) {
Dries's avatar
   
Dries committed
446

Dries's avatar
   
Dries committed
447
    print "<small><a href=\"admin.php?mod=import&type=feed&op=add\">add new feed</a> | <a href=\"admin.php?mod=import&type=bundle&op=add\">add new bundle</a> | <a href=\"admin.php?mod=import&op=fd\">import feeds</a> | <a href=\"admin.php?mod=import&op=tag\">tag items</a> | <a href=\"admin.php?mod=import&op=view\">overview</a> | <a href=\"admin.php?mod=import&op=help\">help</a></small><hr />";
Dries's avatar
   
Dries committed
448

Dries's avatar
   
Dries committed
449
    switch ($op) {
Dries's avatar
   
Dries committed
450
451
452
453
      case "help":
        print import_help();
        break;
      case "add":
Dries's avatar
   
Dries committed
454
        if ($type == "bundle") {
Dries's avatar
   
Dries committed
455
          print import_form_bundle();
Dries's avatar
   
Dries committed
456
457
        }
        else {
Dries's avatar
   
Dries committed
458
          print import_form_feed();
Dries's avatar
   
Dries committed
459
        }
Dries's avatar
   
Dries committed
460
461
        break;
      case "edit":
Dries's avatar
   
Dries committed
462
        if ($type == "bundle") {
Dries's avatar
   
Dries committed
463
          print import_form_bundle(import_get_bundle($id));
Dries's avatar
   
Dries committed
464
465
        }
        else {
Dries's avatar
   
Dries committed
466
          print import_form_feed(import_get_feed($id));
Dries's avatar
   
Dries committed
467
        }
Dries's avatar
   
Dries committed
468
        break;
Dries's avatar
   
Dries committed
469
470
471
472
473
474
475
476
477
478
      case "fd":
        print import_fd_form();
        break;
      case "Collect feeds":
        print import_fd_collect($edit);
        break;
      case "Import feeds":
        print import_fd_import($edit);
        print import_view();
        break;
Dries's avatar
   
Dries committed
479
480
      case "remove":
        print status(import_remove(import_get_feed($id)));
Dries's avatar
   
Dries committed
481
        print import_view();
Dries's avatar
   
Dries committed
482
483
        break;
      case "update":
Dries's avatar
   
Dries committed
484
485
        print status(import_refresh(import_get_feed($id)));
        print import_view();
Dries's avatar
   
Dries committed
486
        break;
Dries's avatar
   
Dries committed
487
488
489
      case "tag":
        print import_tag();
        break;
Dries's avatar
   
Dries committed
490
491
      case "Save attributes":
        print status(import_save_attributes($edit));
Dries's avatar
   
Dries committed
492
        print import_tag();
Dries's avatar
   
Dries committed
493
494
        break;
      case "Delete":
Dries's avatar
   
Dries committed
495
        $edit["title"] = 0;
Dries's avatar
   
Dries committed
496
497
        // fall through:
      case "Submit":
Dries's avatar
   
Dries committed
498
        if ($type == "bundle") {
Dries's avatar
   
Dries committed
499
          print status(import_save_bundle($edit));
Dries's avatar
   
Dries committed
500
501
        }
        else {
Dries's avatar
   
Dries committed
502
          print status(import_save_feed($edit));
Dries's avatar
   
Dries committed
503
        }
Dries's avatar
   
Dries committed
504
505
        // fall through:
      default:
Dries's avatar
   
Dries committed
506
        print import_view();
Dries's avatar
   
Dries committed
507
508
509
510
    }
  }
  else {
    print message_access();
511
512
513
  }
}

Dries's avatar
   
Dries committed
514
515
516
function import_page_info() {
  global $theme;

Dries's avatar
   
Dries committed
517
518
519
520
  $links[] = "<a href=\"module.php?mod=import\" title=\"". t("Read the latest news from syndicated websites.") ."\">". t("latest news") ."</a>";
  $links[] = "<a href=\"module.php?mod=import&op=feeds\" title=\"". t("View the latest headlines sorted by source.") ."\">". t("news by source") ."</a>";
  $links[] = "<a href=\"module.php?mod=import&op=bundles\" title=\"". t("View the latest headlines sorted by topic.") ."\">". t("news by topic") ."</a>";
  $links[] = "<a href=\"module.php?mod=import&op=sources\" title=\"". t("View a list of all the websites we syndicate from.") ."\">". t("news sources") ."</a>";
Dries's avatar
   
Dries committed
521
522
523
524

  return "<div align=\"center\">". $theme->links($links) ."</div>";
}

Dries's avatar
   
Dries committed
525
function import_page_last() {
Dries's avatar
   
Dries committed
526
527
528
  global $theme;

  $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.iid DESC LIMIT ". variable_get("import_page_limit", 75));
Dries's avatar
   
Dries committed
529
530

  $output .= "<table border=\"0\" cellpadding=\"4\" cellspacing=\"2\">";
Dries's avatar
   
Dries committed
531
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
532
533
    $links[] = "<a href=\"module.php?mod=node&op=add&type=blog&iid=$item->iid\" title=\"". t("Comment on this news item in your personal blog.") ."\">". t("blog it") ."</a>";
    $links[] = "<a href=\"module.php?mod=import&op=feed&id=$item->fid\" title=\"". t("Read more syndicated news from this feed.") ."\">". t("feed") ."</a>";
Dries's avatar
   
Dries committed
534
535

    if ($item->link) {
Dries's avatar
   
Dries committed
536
      $output .= "<tr><td>". format_url($item->link, $item->title) ." &middot; <a href=\"module.php?mod=import&op=feed&id=$item->fid\" title=\"". t("View more information about this feed.") ."\">$item->ftitle</a></td><td align=\"right\" nowrap=\"nowrap\" valign=\"top\">". $theme->links($links) ."</td></tr>\n";
Dries's avatar
   
Dries committed
537
    }
Dries's avatar
   
Dries committed
538

Dries's avatar
   
Dries committed
539
    if ($item->description) {
Dries's avatar
Dries committed
540
      $output .= "<tr><td colspan=\"2\"><div style=\"margin-left: 20px;\">". check_output($item->description, 1) ."</div><br /></td></tr>";
Dries's avatar
   
Dries committed
541
542
543
    }

    unset($links);
Dries's avatar
   
Dries committed
544
  }
Dries's avatar
   
Dries committed
545
  $output .= "</table>\n";
Dries's avatar
   
Dries committed
546
547

  $theme->header();
Dries's avatar
   
Dries committed
548
  $theme->box(t("News feeds"), import_page_info());
Dries's avatar
   
Dries committed
549
  $theme->box(t("Latest news"), $output);
Dries's avatar
   
Dries committed
550
551
552
553
554
555
  $theme->footer();
}

function import_page_feed($fid) {
  global $theme;

Dries's avatar
   
Dries committed
556
  $feed = db_fetch_object(db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"));
Dries's avatar
   
Dries committed
557

Dries's avatar
   
Dries committed
558
  $header .= "<p><b>". t("Website") .":</b><div style=\"margin-left: 20px;\">". format_url($feed->link) ."</div></p>";
Dries's avatar
Dries committed
559
  $header .= "<p><b>". t("Description") .":</b><div style=\"margin-left: 20px;\">". check_output($feed->description, 1) ."</div></p>";
Dries's avatar
   
Dries committed
560
  $header .= "<p><b>". t("Last update") .":</b><div style=\"margin-left: 20px;\">". format_interval(time() - $feed->timestamp) ." ". t("ago") ."<a href=\"$feed->url\"><img src=\"". $theme->image("xml.gif") ."\" width=\"36\" height=\"14\" align=\"right\" border=\"0\" /></a><br /><br /></div></p>\n";
Dries's avatar
   
Dries committed
561
562

  $result = db_query("SELECT * FROM item WHERE fid = '". check_input($fid) ."' ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75));
Dries's avatar
   
Dries committed
563
564

  $output .= "<table border=\"0\" cellpadding=\"4\" cellspacing=\"2\">";
Dries's avatar
   
Dries committed
565
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
566
    $links[] = "<a href=\"module.php?mod=node&op=add&type=blog&iid=$item->iid\" title=\"". t("Comment on this news item in your personal blog.") ."\">". t("blog it") ."</a>";
Dries's avatar
   
Dries committed
567
    $links[] = "<a href=\"$item->link\">". t("visit") ."</a>";
Dries's avatar
   
Dries committed
568

Dries's avatar
   
Dries committed
569
    if ($item->link) {
Dries's avatar
   
Dries committed
570
      $output .= "<tr><td>". format_url($item->link, $item->title) ."</td><td align=\"right\" nowrap=\"nowrap\" valign=\"top\">". $theme->links($links) ."</td></tr>\n";
Dries's avatar
   
Dries committed
571
572
    }
    if ($item->description) {
Dries's avatar
Dries committed
573
      $output .= "<tr><td colspan=\"2\"><div style=\"margin-left: 20px;\">". check_output($item->description, 1) ."</div><br /></td></tr>";
Dries's avatar
   
Dries committed
574
575
576
577
578
    }

    unset($links);
  }
  $output .= "</table>\n";
Dries's avatar
   
Dries committed
579
580

  $theme->header();
Dries's avatar
   
Dries committed
581
582
  $theme->box(check_output($feed->title), $header);
  $theme->box(t("Latest news"), $output);
Dries's avatar
   
Dries committed
583
584
585
586
587
588
  $theme->footer();
}

function import_page_bundle($bid) {
  global $theme;

Dries's avatar
   
Dries committed
589
590
591
592
  $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'"));

  $header .= "<p><b>". t("Website") .":</b><div style=\"margin-left: 20px;\">". format_url("module.php?mod=import&op=bundle&id=$bundle->bid") ."</div></p>";
  $header .= "<p><b>". t("Description") .":</b><div style=\"margin-left: 20px;\">". t("A composite news feed about") ." ". check_output($bundle->attributes) .".</div></p>";
Dries's avatar
   
Dries committed
593
594
595
596
597

  $keys = explode(",", $bundle->attributes);
  foreach ($keys as $key) $where[] = "i.attributes LIKE '%". trim($key) ."%'";
  $result = db_query("SELECT i.*, f.title AS ftitle, f.link AS flink FROM item i, feed f WHERE (". implode(" OR ", $where) .") AND i.fid = f.fid ORDER BY iid DESC LIMIT ". variable_get("import_page_limit", 75));

Dries's avatar
   
Dries committed
598
  $output .= "<table border=\"0\" cellpadding=\"4\" cellspacing=\"2\">";
Dries's avatar
   
Dries committed
599
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
600
601
    $links[] = "<a href=\"module.php?mod=node&op=add&type=blog&iid=$item->iid\" title=\"". t("Comment on this news item in your personal blog.") ."\">". t("blog it") ."</a>";
    $links[] = "<a href=\"module.php?mod=import&op=feed&id=$item->fid\" title=\"". t("Read more syndicated news from this feed.") ."\">". t("feed") ."</a>";
Dries's avatar
   
Dries committed
602
603
604
    $links[] = "<a href=\"$item->link\">". t("visit") ."</a>";

    if ($item->link) {
Dries's avatar
   
Dries committed
605
      $output .= "<tr><td>". format_url($item->link, $item->title) ." &middot; <a href=\"module.php?mod=import&op=feed&id=$item->fid\" title=\"". t("View more information about this feed.") ."\">$item->ftitle</a></td><td align=\"right\" nowrap=\"nowrap\" valign=\"top\">". $theme->links($links) ."</td></tr>\n";
Dries's avatar
   
Dries committed
606
    }
Dries's avatar
   
Dries committed
607

Dries's avatar
   
Dries committed
608
    if ($item->description) {
Dries's avatar
Dries committed
609
      $output .= "<tr><td colspan=\"2\"><div style=\"margin-left: 20px;\">". check_output($item->description, 1) ."</div><br /></td></tr>";
Dries's avatar
   
Dries committed
610
611
612
    }

    unset($links);
Dries's avatar
   
Dries committed
613
  }
Dries's avatar
   
Dries committed
614
  $output .= "</table>\n";
Dries's avatar
   
Dries committed
615
616

  $theme->header();
Dries's avatar
   
Dries committed
617
618
  $theme->box(check_output($bundle->title), $header);
  $theme->box(t("Latest news"), $output);
Dries's avatar
   
Dries committed
619
  $theme->footer();
Dries's avatar
   
Dries committed
620

Dries's avatar
   
Dries committed
621
622
}

Dries's avatar
   
Dries committed
623
624
625
626
627
628
629
function import_page_sources() {
  global $theme;

  $result = db_query("SELECT * FROM feed ORDER BY title");

  while ($feed = db_fetch_object($result)) {
    $output .= format_url("module.php?mod=import&op=feed&id=$feed->fid", $feed->title);
Dries's avatar
   
Dries committed
630
    $output .= "<div style=\"margin-left: 20px;\">". check_output($feed->description, 1) ."</div><br />";
Dries's avatar
   
Dries committed
631
632
  }

Dries's avatar
   
Dries committed
633
  $output .= "<a href=\"module.php?mod=import&op=fd\" title=\"". t("View the list of syndicated websites in XML format.") ."\"><img src=\"". $theme->image("xml.gif") ."\" width=\"36\" height=\"14\" align=\"right\" border=\"0\" /></a><br />\n";
Dries's avatar
   
Dries committed
634

Dries's avatar
   
Dries committed
635
636
637
638
639
640
  $theme->header();
  $theme->box(t("News feeds"), import_page_info());
  $theme->box(t("News sources"), $output);
  $theme->footer();
}

Dries's avatar
   
Dries committed
641
642
643
644
645
function import_page_fd() {

  $result = db_query("SELECT * FROM feed ORDER BY title");

  $output .= "<?xml version=\"1.0\"?>\n\n";
Dries's avatar
   
Dries committed
646
  $output .= "<rssfeeds version=\"0.1\">\n\n";
Dries's avatar
   
Dries committed
647
648
649
650
651
652
653
654

  while ($feed = db_fetch_object($result)) {
    $output .= "<channel>\n";
    $output .= " <title>". htmlentities($feed->title) ."</title>\n";
    $output .= " <link>". htmlentities($feed->url) ."</link>\n";
    $output .= "</channel>\n\n";
  }

Dries's avatar
   
Dries committed
655
656
  $output .= "</rssfeeds>\n";

Dries's avatar
   
Dries committed
657
  header("Content-Type: text/xml");
Dries's avatar
   
Dries committed
658
659
660
661

  print $output;
}

Dries's avatar
   
Dries committed
662
function import_page_bundles() {
Dries's avatar
   
Dries committed
663
  import_page_blocks(import_get_bundles());
Dries's avatar
   
Dries committed
664
665
666
}

function import_page_feeds() {
Dries's avatar
   
Dries committed
667
  import_page_blocks(import_get_feeds());
Dries's avatar
   
Dries committed
668
669
670
671
672
673
674
675
676
677
678
679
680
}

function import_page_blocks($blocks) {
  global $theme;

  $count = count($blocks);
  $items = ceil($count / 3);
  $c1 = min($items, $count);
  $c2 = min(2 * $items, $count);
  $c3 = $count;
  $i = 0;

  $theme->header();
Dries's avatar
   
Dries committed
681
  $theme->box(t("News feeds"), import_page_info());
Dries's avatar
   
Dries committed
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
  print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n";
  print " <tr>\n";
  print "  <td width=\"33%\" valign=\"top\">\n";
  for ($i; $i < $c1; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
  print "  </td>\n";
  print "  <td width=\"33%\" valign=\"top\">\n";
  for ($i; $i < $c2; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
  print "  </td>\n";
  print "  <td width=\"33%\" valign=\"top\">\n";
  for ($i; $i < $c3; $i++) $theme->box($blocks[$i]["subject"], $blocks[$i]["content"]);
  print "  </td>\n";
  print " </tr>\n";
  print "</table>\n";
  $theme->footer();
}

function import_page() {
  global $op, $id;

  if (user_access("access news feeds")) {
Dries's avatar
   
Dries committed
702
    switch ($op) {
Dries's avatar
   
Dries committed
703
704
705
706
707
708
      case "feed":
        import_page_feed($id);
        break;
      case "bundle":
        import_page_bundle($id);
        break;
Dries's avatar
   
Dries committed
709
710
711
      case "feeds":
        import_page_feeds();
        break;
Dries's avatar
   
Dries committed
712
713
714
      case "bundles":
        import_page_bundles();
        break;
Dries's avatar
   
Dries committed
715
716
      case "sources":
        import_page_sources();
Dries's avatar
   
Dries committed
717
        break;
Dries's avatar
   
Dries committed
718
719
720
      case "fd":
        import_page_fd();
        break;
Dries's avatar
   
Dries committed
721
      default:
Dries's avatar
   
Dries committed
722
        import_page_last();
Dries's avatar
   
Dries committed
723
724
725
    }
  }
}
Dries's avatar
   
Dries committed
726

727
?>