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

Dries's avatar
   
Dries committed
4
function import_help() {
5
 ?>
Dries's avatar
   
Dries committed
6
  <p>In Drupal you have <i>feeds</i> and <i>bundles</i>.   Feeds define news sources and bundles categorize 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>
Dries's avatar
   
Dries committed
7
  <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>
Dries's avatar
   
Dries committed
8
  <p>To verify whether your feed works, press "update items" at the overview page.  The number of news items that have been sucessfully fetched, should then become visible in the third column of the feed overview.</p>
Dries's avatar
   
Dries committed
9
10
  <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
}

14
function import_system($field){
Kjartan's avatar
Kjartan committed
15
  $system["description"] = t("Used to aggregate syndicated content (RSS and RDF).");
16
17
18
  return $system[$field];
}

19
function import_settings() {
Dries's avatar
   
Dries committed
20
  $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);
Dries's avatar
   
Dries committed
21
22
  $output .= form_select("Items per block", "import_block_limit", variable_get("import_block_limit", 15), $number, "The maximum number of news 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 news items displayed on one page.");
Dries's avatar
   
Dries committed
23

Dries's avatar
   
Dries committed
24
25
26
  return $output;
}

Dries's avatar
   
Dries committed
27
function import_perm() {
Dries's avatar
   
Dries committed
28
  return array("administer news feeds", "access news feeds");
Dries's avatar
   
Dries committed
29
30
31
}

function import_link($type) {
Dries's avatar
   
Dries committed
32
33

  if ($type == "page" && user_access("access news feeds")) {
Dries's avatar
   
Dries committed
34
    $links[] = l(t("news feeds"), "import", array("title" => t("Read the latest news from syndicated websites.")));
Dries's avatar
   
Dries committed
35
36
  }

Dries's avatar
   
Dries committed
37
  if ($type == "admin" && user_access("administer news feeds")) {
Dries's avatar
   
Dries committed
38
39
40
41
42
43
44
45
    $help["general"] = "Several websites, especially news related sites, syndicate parts of their site content for other web sites to display. Usually, the syndicated content includes the latest headlines with a direct link to that story on the remote site. Some syndicated content also includes a description of the headline. The standard method of syndication is using the XML based Rich Site Summary (RSS).";
    $help["bundles"] = "Bundles provide a generalized way of creating composite feeds. They allow you, for example, to combine various sport-related feeds into one bundle called <i>Sport</i>.";
    menu("admin/syndication", "content syndication", NULL, NULL, 5);
    menu("admin/syndication/news", "news aggregation", "import_admin", $help["general"]);
    menu("admin/syndication/news/add feed", "add new feed", "import_admin", NULL, 2);
    menu("admin/syndication/news/add bundle", "add new bundle", "import_admin", $help["bundles"], 3);
    menu("admin/syndication/news/tag", "tag news items", "import_admin", NULL, 4);
    menu("admin/syndication/news/help", "help", "import_help", NULL, 9);
Dries's avatar
   
Dries committed
46
47
  }

Dries's avatar
   
Dries committed
48
  return $links ? $links : array();
Dries's avatar
   
Dries committed
49
50
}

Dries's avatar
   
Dries committed
51
function import_cron() {
Dries's avatar
   
Dries committed
52
53
54
55
56
57
58
  $result = db_query("SELECT * FROM feed WHERE timestamp + refresh < ". time());
  while ($feed = db_fetch_array($result)) {
    import_refresh($feed);
  }
}

function import_update() {
59
60
  $result = db_query("SELECT * FROM feed");
  while ($feed = db_fetch_array($result)) {
Dries's avatar
   
Dries committed
61
62
63
64
    import_refresh($feed);
  }
}

Dries's avatar
   
Dries committed
65
function import_format_item($item, $feed = 0) {
Dries's avatar
   
Dries committed
66
  global $user;
Dries's avatar
   
Dries committed
67

Dries's avatar
   
Dries committed
68
  if ($user->uid && user_access("maintain personal blog")) {
Dries's avatar
   
Dries committed
69
    $output .= l("<img src=\"". theme("image", "blog.gif") ."\" border=\"0\" width=\"12\" height=\"16\" alt=\"". t("Blog this item") ."\" />", "node/add/blog&amp;iid=$item->iid", array("title" => t("Comment on this news item in your personal blog.")));
Dries's avatar
   
Dries committed
70
71
  }

Dries's avatar
   
Dries committed
72
  // external link
Dries's avatar
   
Dries committed
73
  $output .= "<a href=\"$item->link\">$item->title</a>";
74

Dries's avatar
   
Dries committed
75
  return $output ."<br />";
76
77
}

Dries's avatar
   
Dries committed
78
79
function import_bundle_block($attributes) {

80
81
82
  if ($attributes) {
    $keys = explode(",", $attributes);
    foreach ($keys as $key) $where[] = "attributes LIKE '%". trim($key) ."%'";
83

Dries's avatar
   
Dries committed
84
    $result = db_query_range("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY iid DESC", 0, variable_get("import_block_limit", 15));
Dries's avatar
   
Dries committed
85
  }
86

Dries's avatar
   
Dries committed
87
88
  while ($item = db_fetch_object($result)) {
    $output .= import_format_item($item);
89
  }
Dries's avatar
   
Dries committed
90
91

  return $output;
92
93
}

Dries's avatar
   
Dries committed
94
function import_feed_block($feed) {
95
  $result = db_query_range("SELECT * FROM item WHERE fid = '%s' ORDER BY iid DESC ", $feed->fid, 0, variable_get("import_block_limit", 15));
96

Dries's avatar
   
Dries committed
97
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
98
    $output .= import_format_item($item);
Dries's avatar
   
Dries committed
99
  }
Dries's avatar
   
Dries committed
100

Dries's avatar
   
Dries committed
101
102
103
  return $output;
}

Dries's avatar
   
Dries committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
function import_block($op, $delta) {
  if ($op == "list") {
    $result = db_query("SELECT * FROM bundle ORDER BY title");
    while ($bundle = db_fetch_object($result)) {
      $block[$bundle->bid]["info"] = "$bundle->title bundle";
    }

    $result = db_query("SELECT * FROM feed ORDER BY fid");
    while ($feed = db_fetch_object($result)) {
      $block[$feed->fid]["info"] = "$feed->title feed";
    }

    return $block;
  }
  else {
    $feed = db_fetch_object(db_query("SELECT * FROM feed WHERE fid = '%d'", $delta));
    if ($feed) {
      $block["subject"] = $feed->title;
Dries's avatar
   
Dries committed
122
      $block["content"] = import_feed_block($feed) ."<div align=\"right\">". l(t("more"), "import/feed/$feed->fid", array("title" => t("View this feed's recent news."))) ."</div>";
Dries's avatar
   
Dries committed
123
124
125
126
127
    }
    else {
      // it was a bundle. this is NOT elegant
      $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '%d'", $delta));
      $block["subject"] = $bundle->title;
Dries's avatar
   
Dries committed
128
      $block["content"] = import_bundle_block($bundle->attributes) ."<div align=\"right\">". l(t("more"), "import/bundle/$bundle->bid", array("title" => t("View this bundle's recent news."))) ."</div>";
Dries's avatar
   
Dries committed
129
130
131
132
    }

    return $block;
  }
Dries's avatar
   
Dries committed
133
134
}

Dries's avatar
   
Dries committed
135
function import_get_bundles($attributes = 0) {
Dries's avatar
   
Dries committed
136

Dries's avatar
   
Dries committed
137
138
139
  $block = array();

  $result = db_query("SELECT * FROM bundle ORDER BY title");
Dries's avatar
   
Dries committed
140
  while ($bundle = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
141
    $block[$bundle->bid]["subject"] = $bundle->title;
Dries's avatar
Dries committed
142
    $block[$bundle->bid]["content"] = import_bundle_block($bundle->attributes) ."<div align=\"right\">". l(t("more"), "import/bundle/$bundle->bid", array("title" => t("View this bundle's recent news."))) ."</div>";
Dries's avatar
   
Dries committed
143
    $block[$bundle->bid]["info"] = "$bundle->title bundle";
Dries's avatar
   
Dries committed
144
  }
Dries's avatar
   
Dries committed
145

Dries's avatar
   
Dries committed
146
  return $block;
Dries's avatar
   
Dries committed
147
148
}

Dries's avatar
   
Dries committed
149
function import_get_feeds($attributes = 0) {
Dries's avatar
   
Dries committed
150

Dries's avatar
   
Dries committed
151
152
153
  $block = array();

  $result = db_query("SELECT * FROM feed ORDER BY fid");
Dries's avatar
   
Dries committed
154
  while ($feed = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
155
    $block[$feed->fid]["subject"] = $feed->title;
Dries's avatar
   
Dries committed
156
    $block[$feed->fid]["content"] = import_feed_block($feed) ."<div align=\"right\">". l(t("more"), "import/feed/$feed->fid", array("title" => t("View this feed's recent news."))) ."</div>";
Dries's avatar
   
Dries committed
157
    $block[$feed->fid]["info"] = "$feed->title feed";
Dries's avatar
   
Dries committed
158
159
  }

Dries's avatar
   
Dries committed
160
  return $block;
Dries's avatar
   
Dries committed
161
162
}

Dries's avatar
   
Dries committed
163
function import_remove($feed) {
Dries's avatar
   
Dries committed
164
  db_query("DELETE FROM item WHERE fid = '%s'", $feed["fid"]);
165
  return t("removed news items from '%site'.", array("%site" => $feed["title"]));
Dries's avatar
   
Dries committed
166
167
}

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// Call-back function used by XML parser:
function import_element_start($parser, $name, $attributes) {
  global $item, $tag;

  if ($name == "ITEM") {
    $item += 1;
  }

  $tag = $name;
}

// Call-back function used by XML parser:
function import_element_end($parser, $name) {
}

// Call-back function used by XML parser:
function import_element_data($parser, $data) {
  global $channel, $items, $item, $tag;

  if ($item) {
    $items[$item][$tag] .= $data;
  }
  else {
    $channel[$tag] .= $data;
  }
}


Dries's avatar
   
Dries committed
196
function import_refresh($feed) {
197

198
199
  global $items, $channel;

Dries's avatar
   
Dries committed
200
201
202
203
  /*
  ** Check whether the feed is properly configured:
  */

Dries's avatar
   
Dries committed
204
  if (!ereg("^http://|ftp://", $feed["url"])) {
205
    return t("failed to parse RSS feed '%site': incorrect or missing URL.", array("%side" => $feed["title"]));
Dries's avatar
   
Dries committed
206
207
208
  }

  /*
Dries's avatar
   
Dries committed
209
  ** Grab the news items:
Dries's avatar
   
Dries committed
210
211
  */

Dries's avatar
   
Dries committed
212
  if ($fp = @fopen($feed["url"], "r")) {
213
    // fetch data:
Dries's avatar
   
Dries committed
214
215
216
    while (!feof($fp)) {
      $data .= fgets($fp, 128);
    }
Dries's avatar
Dries committed
217
    fclose($fp);
Dries's avatar
   
Dries committed
218

219
220
221
222
223
224
225
226
    $xml_parser = xml_parser_create();
    xml_set_element_handler($xml_parser, "import_element_start", "import_element_end");
    xml_set_character_data_handler($xml_parser, "import_element_data");
    if (!xml_parse($xml_parser, $data, 1)) {
      return t("failed to parse RSS feed '%site': %error at line %line.", array("%site" => $feed["title"], "%error" => xml_error_string(xml_get_error_code($xml_parser)), "%line" => xml_get_current_line_number($xml_parser)));
    }
    xml_parser_free($xml_parser);

Dries's avatar
   
Dries committed
227
228
229
230
    // initialize the translation table:
    $tt = array_flip(get_html_translation_table(HTML_ENTITIES));
    $tt["&apos;"] = "'";

Dries's avatar
   
Dries committed
231
232
233
234
    /*
    ** Strip invalid tags and provide default values (if required):
    */

235
236
    $feed["link"] = strip_tags($channel["LINK"]);
    $feed["description"] = filter(strtr($channel["DESCRIPTION"], $tt));
Dries's avatar
   
Dries committed
237

238
    db_query("UPDATE feed SET timestamp = '%d', link = '%s', description = '%s' WHERE fid = '%d'", time(), $feed["link"], $feed["description"], $feed["fid"]);
Dries's avatar
   
Dries committed
239

Dries's avatar
   
Dries committed
240
    /*
241
242
243
    ** We reverse the array such that we store the first item last,
    ** and the last item first.  In the database, the newest item
    ** should be at the top.
Dries's avatar
   
Dries committed
244
    */
Dries's avatar
   
Dries committed
245

246
    $items = array_reverse($items);
Dries's avatar
   
Dries committed
247

Dries's avatar
   
Dries committed
248
249
    foreach ($items as $item) {
      unset($title, $link, $author, $description);
Dries's avatar
   
Dries committed
250

251
252
      // Prepare the description:
      $description = filter(strtr($item["DESCRIPTION"], $tt));
253

254
255
256
257
258
      // Prepare the title:
      if ($item["TITLE"]) {
        $title = strip_tags(strtr($item["TITLE"], $tt));
      }
      else {
Dries's avatar
   
Dries committed
259
        /*
260
261
262
263
264
265
266
267
268
269
270
271
272
273
         ** Use up to 40 characters of the $description, ending at
         ** word boundary, but don't split potential entities.
         */
        $title = preg_replace('/^(.*)[^\w;&].*?$/', "\\1", substr(strip_tags($description), 0, 40));
      }
      if ($item["LINK"]) {
        $link = strip_tags($item["LINK"]);
      }
      elseif ($item["GUID"] && (strncmp($item["GUID"], "http://", 7) == 0)) {
        $link = strip_tags($item["GUID"]);
      }
      else {
        $link = $feed["link"];
      }
Dries's avatar
Dries committed
274

275
      $author = strip_tags($item["AUTHOR"]);
Dries's avatar
   
Dries committed
276

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

279
280
281
282
283
      /*
       ** 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
284

285
286
287
288
289
      if ($link && $link != $feed["link"] && $link != $feed["url"]) {
        $entry = db_fetch_object(db_query("SELECT iid FROM item WHERE fid = '%s' AND link = '%s'", $feed["fid"], $link));
      }
      else {
        $entry = db_fetch_object(db_query("SELECT iid FROM item WHERE fid = '%s' AND title = '%s'", $feed["fid"], $title));
290
      }
291
292

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

    /*
Dries's avatar
   
Dries committed
296
    ** Remove all the old, expired items:
Dries's avatar
   
Dries committed
297
298
299
300
    */

    unset($items);

Dries's avatar
   
Dries committed
301
    $result = db_query("SELECT iid FROM item WHERE fid = '%s' ORDER BY timestamp", $feed["fid"]);
Dries's avatar
   
Dries committed
302
303
304
305
306

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

Dries's avatar
   
Dries committed
307
    if (sizeof($items) > 50) {
Dries's avatar
   
Dries committed
308
309
310
      db_query("DELETE FROM item WHERE ". implode(" OR ", array_slice($items, 0, - 50)));
    }

Dries's avatar
   
Dries committed
311
312
  }
  else {
313
    return t("failed to parse RSS feed '%site': no data.", array("%site" => $feed["tite"]));
314
  }
Dries's avatar
   
Dries committed
315

316
  return t("syndicated content from '%site'.", array("%site" => $feed["title"]));
317
318
}

Dries's avatar
   
Dries committed
319
function import_save_item($edit) {
Dries's avatar
   
Dries committed
320
  if ($edit["iid"] && $edit["title"]) {
Dries's avatar
   
Dries committed
321
    db_query("UPDATE item SET title = '%s', link = '%s', author = '%s', description = '%s', attributes = '%s' WHERE iid = '%s'", $edit["title"], $edit["link"], $edit["author"], $edit["description"], $edit["attributes"], $edit["iid"]);
322
  }
Dries's avatar
   
Dries committed
323
  else if ($edit["iid"]) {
Dries's avatar
   
Dries committed
324
    db_query("DELETE FROM item WHERE iid = '%s'", $edit["iid"]);
325
  }
Dries's avatar
   
Dries committed
326
  else if ($edit["title"] && $edit["link"]) {
Dries's avatar
   
Dries committed
327
    db_query("INSERT INTO item (fid, title, link, author, description, attributes, timestamp) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s')", $edit["fid"], $edit["title"], $edit["link"], $edit["author"], $edit["description"], $edit["attributes"], time());
328
329
330
  }
}

Dries's avatar
   
Dries committed
331
function import_form_bundle($edit = array()) {
332

Dries's avatar
   
Dries committed
333
  $form .= form_textfield("Title", "title", $edit["title"], 50, 64, "The name of the bundle.");
Dries's avatar
   
Dries committed
334
  $form .= form_textfield("Attributes", "attributes", $edit["attributes"], 50, 128, "A comma-separated list of keywords describing the bundle.");
335
336
337

  $form .= form_submit("Submit");

Dries's avatar
   
Dries committed
338
  if ($edit["bid"]) {
Dries's avatar
   
Dries committed
339
    $form .= form_submit("Delete");
Dries's avatar
   
Dries committed
340
    $form .= form_hidden("bid", $edit["bid"]);
341
342
  }

Dries's avatar
   
Dries committed
343
  return form($form);
344
345
}

Dries's avatar
   
Dries committed
346
function import_save_bundle($edit) {
Dries's avatar
   
Dries committed
347
  if ($edit["bid"] && $edit["title"]) {
Dries's avatar
   
Dries committed
348
    db_query("UPDATE bundle SET title = '%s', attributes = '%s' WHERE bid = '%s'", $edit["title"], $edit["attributes"], $edit["bid"]);
349
  }
Dries's avatar
   
Dries committed
350
  else if ($edit["bid"]) {
Dries's avatar
   
Dries committed
351
    db_query("DELETE FROM bundle WHERE bid = '%s'", $edit["bid"]);
352
  }
Dries's avatar
   
Dries committed
353
  else if ($edit["title"]) {
Dries's avatar
   
Dries committed
354
355
356
    // a single unique id for bundles and feeds, to use in blocks
    $next_id = db_next_id("import");
    db_query("INSERT INTO bundle (bid, title, attributes) VALUES ('%d', '%s', '%s')", $next_id, $edit["title"], $edit["attributes"]);
357
358
359
  }
}

Dries's avatar
   
Dries committed
360
function import_form_feed($edit = array()) {
361
362
363

  $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
364
365
366
  if ($edit["refresh"] == "") {
    $edit["refresh"] = 3600;
  }
Dries's avatar
   
Dries committed
367

Dries's avatar
   
Dries committed
368
369
  $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.");
Dries's avatar
   
Dries committed
370
  $form .= form_textfield("Attributes", "attributes", $edit["attributes"], 50, 128, "A comma-separated list of keywords describing the feed.");
Dries's avatar
   
Dries committed
371
  $form .= form_select("Update interval", "refresh", $edit["refresh"], $period, "The refresh interval indicating how often you want to update this feed.  Requires crontab.");
372
373
374

  $form .= form_submit("Submit");

Dries's avatar
   
Dries committed
375
  if ($edit["fid"]) {
Dries's avatar
   
Dries committed
376
    $form .= form_submit("Delete");
Dries's avatar
   
Dries committed
377
    $form .= form_hidden("fid", $edit["fid"]);
378
379
  }

Dries's avatar
   
Dries committed
380
  return form($form);
381
382
}

Dries's avatar
   
Dries committed
383
function import_save_feed($edit) {
Dries's avatar
   
Dries committed
384
  if ($edit["fid"] && $edit["title"]) {
Dries's avatar
   
Dries committed
385
386
    db_query("UPDATE feed SET title = '%s', url = '%s', attributes = '%s', refresh = '%s' WHERE fid = '%s'", $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"], $edit["fid"]);
    db_query("DELETE FROM item WHERE fid = '%s'", $edit["fid"]);
387
  }
Dries's avatar
   
Dries committed
388
  else if ($edit["fid"]) {
Dries's avatar
   
Dries committed
389
390
    db_query("DELETE FROM feed WHERE fid = '%s'", $edit["fid"]);
    db_query("DELETE FROM item WHERE fid = '%s'", $edit["fid"]);
391
  }
Dries's avatar
   
Dries committed
392
  else if ($edit["title"]) {
Dries's avatar
   
Dries committed
393
394
395
    // a single unique id for bundles and feeds, to use in blocks
    $next_id = db_next_id("import");
    db_query("INSERT INTO feed (fid, title, url, attributes, refresh) VALUES ('%d', '%s', '%s', '%s', '%s')", $next_id, $edit["title"], $edit["url"], $edit["attributes"], $edit["refresh"]);
396
397
398
  }
}

Dries's avatar
   
Dries committed
399
function import_save_attributes($edit) {
Dries's avatar
   
Dries committed
400
  foreach ($edit as $iid => $value) {
Dries's avatar
   
Dries committed
401
    db_query("UPDATE item SET attributes = '%s' WHERE iid = '%s'", $value, $iid);
402
403
404
405
  }
  return "attributes has been saved";
}

Dries's avatar
   
Dries committed
406
function import_get_feed($fid) {
Dries's avatar
   
Dries committed
407
  return db_fetch_array(db_query("SELECT * FROM feed WHERE fid = '%s'", $fid));
408
409
}

Dries's avatar
   
Dries committed
410
function import_get_bundle($bid) {
Dries's avatar
   
Dries committed
411
  return db_fetch_array(db_query("SELECT * FROM bundle WHERE bid = '%s'", $bid));
412
413
}

Dries's avatar
   
Dries committed
414
function import_view() {
Dries's avatar
   
Dries committed
415
  $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");
416

Dries's avatar
   
Dries committed
417
  $output .= "<h3>Feed overview</h3>";
Dries's avatar
   
Dries committed
418
419
420

  $header = array(t("title"), t("attributes"), t("items"), t("last update"), t("next update"), array("data" => t("operations"), "colspan" => 3));
  unset($rows);
421
  while ($feed = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
422
    $rows[] = array($feed->title, $feed->attributes, format_plural($feed->items, "1 item", "%count items"), ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never"), ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never"), l(t("edit feed"), "admin/syndication/news/edit/feed/$feed->fid"), l(t("remove items"), "admin/syndication/news/remove/$feed->fid"), l(t("update items"), "admin/syndication/news/update/$feed->fid"));
423
  }
Dries's avatar
   
Dries committed
424
  $output .= table($header, $rows);
425
426
427

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

Dries's avatar
   
Dries committed
428
  $output .= "<h3>Bundle overview</h3>";
Dries's avatar
   
Dries committed
429
430
431

  $header = array(t("title"), t("attributes"), t("operations"));
  unset($rows);
432
  while ($bundle = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
433
    $rows[] = array($bundle->title, $bundle->attributes, l(t("edit bundle"), "admin/syndication/news/edit/bundle/$bundle->bid"));
434
  }
Dries's avatar
   
Dries committed
435
  $output .= table($header, $rows);
436
437
438
439

  return $output;
}

Dries's avatar
   
Dries committed
440
function import_tag() {
441

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

Dries's avatar
   
Dries committed
444
  $header = array(t("date"), t("feed"), t("news item"));
445
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
446
    $rows[] = array(array("data" => format_date($item->timestamp, "small"), "nowrap" => "nowrap", "valign" => "top"), array("data" => l($item->feed, "admin/syndication/news/edit/feed/$item->fid"), "valign" => "top"), "<a href=\"$item->link\">$item->title</a>". ($item->description ? "<br /><small><i>$item->description</i></small>" : "") ."<br /><input type=\"text\" name=\"edit[$item->iid]\" value=\"". check_form($item->attributes) ."\" size=\"50\" />");
447
  }
Dries's avatar
   
Dries committed
448
449

  $output .= table($header, $rows);
Dries's avatar
   
Dries committed
450
  $output .= "<input type=\"submit\" name=\"op\" value=\"Save attributes\" />\n";
451

Dries's avatar
   
Dries committed
452
  return form($output);
453
454
}

Dries's avatar
   
Dries committed
455
function import_admin() {
Dries's avatar
   
Dries committed
456
  global $op, $edit;
Dries's avatar
   
Dries committed
457

Dries's avatar
   
Dries committed
458
  if (user_access("administer news feeds")) {
Dries's avatar
   
Dries committed
459

Dries's avatar
   
Dries committed
460
    if (empty($op)) {
Dries's avatar
   
Dries committed
461
      $op = arg(3);
Dries's avatar
   
Dries committed
462
463
    }

Dries's avatar
   
Dries committed
464
    switch ($op) {
Dries's avatar
   
Dries committed
465
      case "add feed":
Dries's avatar
   
Dries committed
466
        print import_form_feed();
Dries's avatar
   
Dries committed
467
        break;
Dries's avatar
   
Dries committed
468
      case "add bundle":
Dries's avatar
   
Dries committed
469
        print import_form_bundle();
Dries's avatar
   
Dries committed
470
471
        break;
      case "edit":
Dries's avatar
   
Dries committed
472
473
        if (arg(4) == "bundle") {
          print import_form_bundle(import_get_bundle(arg(5)));
Dries's avatar
   
Dries committed
474
475
        }
        else {
Dries's avatar
   
Dries committed
476
          print import_form_feed(import_get_feed(arg(5)));
Dries's avatar
   
Dries committed
477
        }
Dries's avatar
   
Dries committed
478
479
        break;
      case "remove":
Dries's avatar
   
Dries committed
480
        print status(import_remove(import_get_feed(arg(4))));
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
        print status(import_refresh(import_get_feed(arg(4))));
Dries's avatar
   
Dries committed
485
        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 (arg(3) == "add 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
function import_page_info() {
Dries's avatar
   
Dries committed
515

Dries's avatar
   
Dries committed
516

Dries's avatar
   
Dries committed
517
518
519
520
521
  $links[] = l(t("latest news"), "import", array("title" => t("Read the latest news from syndicated websites.")));
  $links[] = l(t("news by source"), "import/feeds", array("title" => t("View the latest headlines sorted by source.")));
  $links[] = l(t("news by topic"), "import/bundles", array("title" => t("View the latest headlines sorted by topic.")));
  $links[] = l(t("news sources"), "import/sources", array("title" => t("View a list of all the websites we syndicate from.")));

522
  if (user_access("administer news feeds")) {
Dries's avatar
   
Dries committed
523
    $links[] = l(t("administer news feeds"), "admin/syndication/news", array("title" => t("View the news feed administrative pages.")));
524
  }
Dries's avatar
   
Dries committed
525

Dries's avatar
   
Dries committed
526
  return "<div align=\"center\">". theme("links", $links) ."</div>";
Dries's avatar
   
Dries committed
527
528
}

Dries's avatar
   
Dries committed
529
function import_page_last() {
Dries's avatar
   
Dries committed
530

Dries's avatar
   
Dries committed
531

Dries's avatar
   
Dries committed
532
  $result = db_query_range("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", 0, variable_get("import_page_limit", 75));
Dries's avatar
   
Dries committed
533
534

  $output .= "<table border=\"0\" cellpadding=\"4\" cellspacing=\"2\">";
Dries's avatar
   
Dries committed
535
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
536
    if (module_exist("blog") && user_access("maintain personal blog")) {
537
      $links[] = l(t("blog it"), "node/add/blog", array("title" => t("Comment on this news item in your personal blog.")), "iid=$item->iid");
538
    }
Dries's avatar
   
Dries committed
539
    $links[] = l(t("feed"), "import/feed/$item->fid", array("title" => t("Read more syndicated news from this feed.")));
Dries's avatar
   
Dries committed
540
541

    if ($item->link) {
Dries's avatar
   
Dries committed
542
      $output .= "<tr><td><a href=\"$item->link\">$item->title</a> &middot; ". l($item->ftitle, "import/feed/$item->fid", array("title" => t("View more information about this feed."))) ."</td><td align=\"right\" nowrap=\"nowrap\" valign=\"top\">". theme("links", $links) ."</td></tr>\n";
Dries's avatar
   
Dries committed
543
    }
Dries's avatar
   
Dries committed
544

Dries's avatar
   
Dries committed
545
    if ($item->description) {
Dries's avatar
   
Dries committed
546
      $output .= "<tr><td colspan=\"2\"><div style=\"margin-left: 20px;\">$item->description</div><br /></td></tr>";
Dries's avatar
   
Dries committed
547
548
549
    }

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

Dries's avatar
   
Dries committed
553
554
555
556
  theme("header");
  theme("box", t("News feeds"), import_page_info());
  theme("box", t("Latest news"), $output);
  theme("footer");
Dries's avatar
   
Dries committed
557
558
559
}

function import_page_feed($fid) {
Dries's avatar
   
Dries committed
560

Dries's avatar
   
Dries committed
561

Dries's avatar
   
Dries committed
562
  $feed = db_fetch_object(db_query("SELECT * FROM feed WHERE fid = '%s'", $fid));
Dries's avatar
   
Dries committed
563

Kjartan's avatar
Kjartan committed
564
  $header .= "<p><b>". t("Website") .":</b><div style=\"margin-left: 20px;\"><a href=\"$feed->link\">$feed->link</a></div></p>";
Dries's avatar
   
Dries committed
565
  $header .= "<p><b>". t("Description") .":</b><div style=\"margin-left: 20px;\">$feed->description</div></p>";
Dries's avatar
   
Dries committed
566
  $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\" alt=\"\" /></a><br /><br /></div></p>\n";
Dries's avatar
   
Dries committed
567

568
  $result = db_query_range("SELECT * FROM item WHERE fid = '%s' ORDER BY iid DESC", $fid, 0, variable_get("import_page_limit", 75));
Dries's avatar
   
Dries committed
569
570

  $output .= "<table border=\"0\" cellpadding=\"4\" cellspacing=\"2\">";
Dries's avatar
   
Dries committed
571
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
572
    if (module_exist("blog") && user_access("maintain personal blog")) {
573
      $links[] = l(t("blog it"), "node/add/blog", array("title" => t("Comment on this news item in your personal blog.")), "iid=$item->iid");
574
    }
Dries's avatar
   
Dries committed
575
    $links[] = "<a href=\"$item->link\">". t("visit") ."</a>";
Dries's avatar
   
Dries committed
576

Dries's avatar
   
Dries committed
577
    if ($item->link) {
Dries's avatar
   
Dries committed
578
      $output .= "<tr><td><a href=\"$item->link\">$item->title</a></td><td align=\"right\" nowrap=\"nowrap\" valign=\"top\">". theme("links", $links) ."</td></tr>\n";
Dries's avatar
   
Dries committed
579
580
    }
    if ($item->description) {
Dries's avatar
   
Dries committed
581
      $output .= "<tr><td colspan=\"2\"><div style=\"margin-left: 20px;\">$item->description</div><br /></td></tr>";
Dries's avatar
   
Dries committed
582
583
584
585
586
    }

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

Dries's avatar
   
Dries committed
588
589
590
591
592
  theme("header");
  theme("box", t("News feeds"), import_page_info());
  theme("box", $feed->title, $header);
  theme("box", t("Latest news"), $output);
  theme("footer");
Dries's avatar
   
Dries committed
593
594
595
}

function import_page_bundle($bid) {
Dries's avatar
   
Dries committed
596

Dries's avatar
   
Dries committed
597

Dries's avatar
   
Dries committed
598
  $bundle = db_fetch_object(db_query("SELECT * FROM bundle WHERE bid = '%s'", $bid));
Dries's avatar
   
Dries committed
599

Dries's avatar
   
Dries committed
600
  $header .= "<p><b>". t("Website") .":</b><div style=\"margin-left: 20px;\">". l($bundle->title, "import/bundle/$bundle->bid") ."</div></p>";
Dries's avatar
   
Dries committed
601
  $header .= "<p><b>". t("Description") .":</b><div style=\"margin-left: 20px;\">". t("A composite news feed about") ." $bundle->attributes.</div></p>";
Dries's avatar
   
Dries committed
602
603
604

  $keys = explode(",", $bundle->attributes);
  foreach ($keys as $key) $where[] = "i.attributes LIKE '%". trim($key) ."%'";
Dries's avatar
   
Dries committed
605
  $result = db_query_range("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", 0, variable_get("import_page_limit", 75));
Dries's avatar
   
Dries committed
606

Dries's avatar
   
Dries committed
607
  $output .= "<table border=\"0\" cellpadding=\"4\" cellspacing=\"2\">";
Dries's avatar
   
Dries committed
608
  while ($item = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
609
    if (module_exist("blog") && user_access("maintain personal blog")) {
610
      $links[] = l(t("blog it"), "node/add/blog", array("title" => t("Comment on this news item in your personal blog.")), "iid=$item->iid");
611
    }
Dries's avatar
   
Dries committed
612
    $links[] = l(t("feed"), "import/feed/$item->fid", array("title" => t("Read more syndicated news from this feed.")));
Dries's avatar
   
Dries committed
613
614
615
    $links[] = "<a href=\"$item->link\">". t("visit") ."</a>";

    if ($item->link) {
Dries's avatar
   
Dries committed
616
      $output .= "<tr><td><a href=\"$item->link\">$item->title</a> &middot; ". l($item->ftitle, "import/feed/$item->fid", array("title" => t("View more information about this feed."))) ."</td><td align=\"right\" nowrap=\"nowrap\" valign=\"top\">". theme("links", $links) ."</td></tr>\n";
Dries's avatar
   
Dries committed
617
    }
Dries's avatar
   
Dries committed
618

Dries's avatar
   
Dries committed
619
    if ($item->description) {
Dries's avatar
   
Dries committed
620
      $output .= "<tr><td colspan=\"2\"><div style=\"margin-left: 20px;\">$item->description</div><br /></td></tr>";
Dries's avatar
   
Dries committed
621
622
623
    }

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

Dries's avatar
   
Dries committed
627
628
629
630
631
  theme("header");
  theme("box", t("News feeds"), import_page_info());
  theme("box", $bundle->title, $header);
  theme("box", t("Latest news"), $output);
  theme("footer");
Dries's avatar
   
Dries committed
632

Dries's avatar
   
Dries committed
633
634
}

Dries's avatar
   
Dries committed
635
function import_page_sources() {
Dries's avatar
   
Dries committed
636

Dries's avatar
   
Dries committed
637
638
639
640

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

  while ($feed = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
641
    $output .= l($feed->title, "import/feed/$feed->fid");
Dries's avatar
   
Dries committed
642
    $output .= "<div style=\"margin-left: 20px;\">$feed->description</div><br />";
Dries's avatar
   
Dries committed
643
644
  }

Dries's avatar
   
Dries committed
645
  $output .= l("<img src=\"". theme("image", "xml.gif") ."\" width=\"36\" height=\"14\" align=\"right\" border=\"0\" />", "import/fd", array("title" => t("View the list of syndicated websites in XML format."))) ."<br />";
Dries's avatar
   
Dries committed
646

Dries's avatar
   
Dries committed
647
648
649
650
  theme("header");
  theme("box", t("News feeds"), import_page_info());
  theme("box", t("News sources"), $output);
  theme("footer");
Dries's avatar
   
Dries committed
651
652
}

Dries's avatar
   
Dries committed
653
654
655
656
657
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
658
  $output .= "<rssfeeds version=\"0.1\">\n\n";
Dries's avatar
   
Dries committed
659
660
661
662
663
664
665
666

  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
667
668
  $output .= "</rssfeeds>\n";

Dries's avatar
   
Dries committed
669
  header("Content-Type: text/xml");
Dries's avatar
   
Dries committed
670
671
672
673

  print $output;
}

Dries's avatar
   
Dries committed
674
function import_page_bundles() {
Dries's avatar
   
Dries committed
675
  import_page_blocks(import_get_bundles());
Dries's avatar
   
Dries committed
676
677
678
}

function import_page_feeds() {
Dries's avatar
   
Dries committed
679
  import_page_blocks(import_get_feeds());
Dries's avatar
   
Dries committed
680
681
682
683
}

function import_page_blocks($blocks) {

Dries's avatar
   
Dries committed
684
685
686

  theme("header");
  theme("box", t("News feeds"), import_page_info());
Dries's avatar
   
Dries committed
687
688
  print "<table cellpadding=\"0\" cellspacing=\"5\" border=\"0\" width=\"100%\">\n";
  print " <tr>\n";
Dries's avatar
   
Dries committed
689
690
691
692
693

  for ($t = 0; $t < 3; $t++) {
    $i = 1;
    print "  <td width=\"33%\" valign=\"top\">\n";
    while ($block = each($blocks)) {
Dries's avatar
   
Dries committed
694
      theme("box", $block["value"]["subject"], $block["value"]["content"]);
Dries's avatar
   
Dries committed
695
696
697
698
699
700
701
702
      if ($i == ceil(count($blocks) / 3)) {
        break;
      }
      $i++;
    }
    print "  </td>\n";
  }

Dries's avatar
   
Dries committed
703
704
  print " </tr>\n";
  print "</table>\n";
Dries's avatar
   
Dries committed
705
  theme("footer");
Dries's avatar
   
Dries committed
706
707
708
709
}

function import_page() {
  if (user_access("access news feeds")) {
Dries's avatar
   
Dries committed
710
    switch (arg(1)) {
Dries's avatar
   
Dries committed
711
      case "feed":
Dries's avatar
   
Dries committed
712
        import_page_feed(arg(2));
Dries's avatar
   
Dries committed
713
714
        break;
      case "bundle":
Dries's avatar
   
Dries committed
715
        import_page_bundle(arg(2));
Dries's avatar
   
Dries committed
716
        break;
Dries's avatar
   
Dries committed
717
718
719
      case "feeds":
        import_page_feeds();
        break;
Dries's avatar
   
Dries committed
720
721
722
      case "bundles":
        import_page_bundles();
        break;
Dries's avatar
   
Dries committed
723
724
      case "sources":
        import_page_sources();
Dries's avatar
   
Dries committed
725
        break;
Dries's avatar
   
Dries committed
726
727
728
      case "fd":
        import_page_fd();
        break;
Dries's avatar
   
Dries committed
729
      default:
Dries's avatar
   
Dries committed
730
        import_page_last();
Dries's avatar
   
Dries committed
731
732
733
    }
  }
}
Dries's avatar
   
Dries committed
734

Dries's avatar
   
Dries committed
735
?>