/[drupal]/contributions/modules/actionfeed/actionfeed.module
ViewVC logotype

Contents of /contributions/modules/actionfeed/actionfeed.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Sat Sep 17 11:38:49 2005 UTC (4 years, 2 months ago) by jareyero
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +500 -0 lines
File MIME type: text/x-php
New ActionFeed module
1 <?php
2 // $Id: actionfeed.module,v 1.1.2.1 2005/09/17 11:14:11 jareyero Exp $
3
4 /**
5 * Implementation of hook_help
6 */
7 function actionfeed_help($section = "admin/help#page") {
8 $output = "";
9
10 switch ($section) {
11 case 'admin/modules#description':
12 $output = t('Lets you manage email alerts from other organizations');
13 break;
14 case 'node/add#actionfeed':
15 $output = t("You can create a mail alias using this yay.");
16 break;
17 case 'admin/help#actionfeed':
18 $output = t("
19 <h3>Introduction</h3>
20 <p>This module, together with <strong>mailhandler</strong> module, allows you to receive and classify incoming e-mails from many organizations or subscription lists.</p>
21 <h3>Creating organizations</h3>
22 <p>You can create any number of organizations, each one of them linked with one or more e-mail address. Received e-mails are linked to each organization depending on the \"From\" e-mail address.</p>
23 <h3>Integration with mailhandler</h3>
24 <p>You need to set up at least one mailhandler mailbox to receive e-mails. The POP or IMAP inbox is the one you have to use for list subscriptions.</p>
25 <p>E-mail received through mailhandler will be authomatically processed by this module, and will be linked to one of your organizations in case the \"From\" e-mail matches. If a matching e-mail address cannot be found, then the e-mail will be processed as usual by mailhandler module.</p>
26 <p>The content type that will be used to store this e-mails is configurable through the module's settings page. The user assigned to each e-mail will be the one who created the specific organization.</p>
27 <p>The desired workflow options for incoming e-mails can be set up adding default commands to the <strong>mailhandler</strong> mailbox.</p>
28 <h3>Filters</h3>
29 <p>You may select, in the module's settings page, any of the available <strong>input filters</strong> to be used for the content submitted. Different input filters for HTML and plain text e-mails can be selected.</p>
30 <p>This module also provides one additional filter to do some basic clean up for HTML e-mails.</p>
31 <p>For plain text e-mails, the <strong>Email filter</strong> provided by mailhandler is recommended.</p>
32 <p>For HTML e-mails, the filter provided by <strong>HTML corrector</strong> module is advised.</p>
33 <h3>Permissions</h3>
34 <p>In addition to this module's specific permissions, you need to make sure that the user who created one organization, has also the right permissions to create whatever content type the e-mails will be stored as -which is a configurable option. Otherwise, the content of the e-mail will not be stored in the system and you'll get just some error log about it.</p>
35 <p>This applies also to any other settings defined per inbox in <strong>mailhandler</strong>, like workflow settings and filter settings.</p>
36 ");
37 break;
38
39 }
40
41 return $output;
42 }
43
44 /**
45 * Implementation of hook_menu
46 */
47 function actionfeed_menu($may_cache) {
48 $items = array();
49 if($may_cache){
50 $items[] = array( 'path' => 'node/add/actionfeed', 'title' => t('actionfeed organization'),
51 'access' => user_access('create actionfeed organizations'));
52
53 $items[] = array('path' => 'actionfeed', 'title' => t('actionfeed'),
54 'callback' => 'actionfeed_page',
55 'access' => user_access('access action feeds'),
56 'type' => MENU_NORMAL_ITEM);
57
58 $items[] = array('path' => 'actionfeed/feed', 'title' => t('Ppipes Feeds'),
59 'callback' => 'actionfeed_feed',
60 'access' => user_access('access action feeds'),
61 'type' => MENU_CALLBACK);
62 }
63 return $items;
64 }
65
66 /**
67 * Implementation of hook_settings
68 */
69
70 function actionfeed_settings(){
71 $output .= form_textfield(t('Header'), 'actionfeed_header', variable_get('actionfeed_header', t('Action Feed')), 70, 100);
72 $output .= form_textarea(t('Header tagline'), 'actionfeed_header_tagline', variable_get('actionfeed_header_tagline', t('Action Feed lets you see email alerts from dozens of organizations in a single location.')), 70, 4);
73
74 // Select node type to save e-mails
75 foreach (node_list() as $type) {
76 $node_type = node_invoke($type, 'node_name');
77 $nodes[$type] = $node_type ? $node_type : $type;
78 }
79 $output .= form_select(t('Content type for e-mails'), 'actionfeed_node_type', variable_get('actionfeed_node_type', 'story'),$nodes, t('This is the content type to save the e-mails as.'));
80
81 $output .= '<h2>'.t("Filter configuration").'</h2>';
82 $output .= form_group(t("Filter for HTML e-mails"),filter_form('actionfeed_filter_html', variable_get('actionfeed_filter_html', FILTER_FORMAT_DEFAULT)));
83 $output .= form_group(t("Filter for plain text e-mails"), filter_form('actionfeed_filter_text', variable_get('actionfeed_filter_text', FILTER_FORMAT_DEFAULT)));
84
85 return $output;
86 }
87
88 /**
89 * Implementation of hook_block
90 */
91 function actionfeed_block($op = "list", $delta = 0) {
92
93 if($op == "list") {
94 $vocabularies = taxonomy_get_vocabularies();
95 $i = 0;
96 foreach ($vocabularies as $vocabulary) {
97 $blocks[$i]["info"] = "<b>Vocab Links:</b> " . $vocabulary->name;
98 $i++;
99 }
100 return $blocks;
101 }
102 else {
103 $vocabularies = taxonomy_get_vocabularies();
104 $i = 0;
105 foreach ($vocabularies as $vocabulary) {
106 if ($i == $delta) {
107 $terms = taxonomy_get_tree($vocabulary->vid);
108 $block["subject"] = $vocabulary->name;
109 $block["content"] = "";
110 foreach($terms as $term) {
111 $imagePath = "misc/actionfeed/" . $term->tid . ".png";
112 if ($term->depth == 0) {
113 $padding = "10px";
114 }
115 else {
116 $padding = 10 + (20 * $term->depth) . "px";
117 }
118 if (file_exists($imagePath)) {
119 $icon = "<img src=\"$imagePath\" style=\"float: left; padding-left: $padding; padding-right: 10px;\">";
120 }
121 $block["content"] .= l(t($icon . $term->name), "actionfeed/latest/" . $term->tid) . "<br><br>";
122 }
123 }
124 $i++;
125 }
126 return $block;
127 }
128 }
129
130 /**
131 * Implementation of hook_cron
132 *
133 * Counts organizations and e-mails
134 */
135 function actionfeed_cron() {
136 variable_set('actionfeed_count_organizations', db_result(db_query("SELECT count(*) FROM {node} WHERE type = 'actionfeed'")));
137 variable_set('actionfeed_count_emails', db_result(db_query("SELECT count(*) FROM {actionfeed_node}")));
138 }
139
140 /**
141 * Implementation of hook_link
142 */
143 function actionfeed_link($type, $node = NULL, $teaser = FALSE){
144 $links = array();
145
146 if ($type == 'node') {
147 if($node->type == 'actionfeed') {
148 $links[]=l(t('see emails from %organization', array('%organization' => $node->title)),'actionfeed/'.$node->nid);
149 } elseif(isset($node->actionfeed) && !(arg(0)=='actionfeed' && is_numeric(arg(1)))) {
150 $links[]=l(t('more emails from %organization', array('%organization' => $node->actionfeed->title)),'actionfeed/'.$node->actionfeed->nid);
151 }
152 }
153
154 return $links;
155 }
156
157 /**
158 * Implementation of hook_nodeapi
159 */
160 function actionfeed_nodeapi(&$node, $op, $teaser = NULL, $page = NULL){
161 if( $node->type == variable_get('actionfeed_node_type', 'story')) {
162 switch($op){
163 case 'load':
164 if($actionfeed = db_fetch_object(db_query("SELECT n.nid, n.title FROM {node} n INNER JOIN {actionfeed_node} p ON n.nid = p.ppnid WHERE p.nid = %d", $node->nid))){
165 $node->ppnid = $actionfeed->nid;
166 $node->actionfeed = $actionfeed;
167 }
168 break;
169 case 'view':
170 if (isset($node->actionfeed)) {
171 $info = '<div class="actionfeed-info">';
172 $info .= t('Mail from %organization', array('%organization' => l($node->actionfeed->title, 'node/'.$node->actionfeed->nid)));
173 $info .= "</div>\n";
174 if($teaser){
175 $node->teaser = $info . $node->teaser;
176 } else {
177 $node->body = $info . $node->body;
178 }
179 }
180 break;
181 case 'form pre':
182 return form_select(t('PPipes organization'), 'ppnid', isset($node->ppnid) ? $node->ppnid : 0, _actionfeed_list_organizations(array('0' => t('<none>'))));
183 case 'validate':
184 break;
185 case 'delete':
186 if (isset($node->ppnid)) {
187 db_query('DELETE FROM {actionfeed_node} WHERE nid = %d', $node->nid);
188 }
189 break;
190 case 'update':
191 db_query('DELETE FROM {actionfeed_node} WHERE nid = %d', $node->nid);
192 case 'insert':
193 if(isset($node->ppnid)){
194 db_query('INSERT INTO {actionfeed_node}(nid, ppnid) VALUES(%d, %d)',$node->nid, $node->ppnid );
195 }
196 break;
197
198 }
199 }
200 }
201
202 /**
203 * Implementation of hook_perm
204 */
205 function actionfeed_perm() {
206 return array("create actionfeed organizations", "edit own actionfeed organizations", "access action feeds");
207 }
208
209 function _actionfeed_list_organizations($list = array()) {
210 $result = db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = 'actionfeed'");
211 while($org = db_fetch_object($result)){
212 $list[$org->nid] = $org->title;
213 }
214 return $list;
215 }
216 /**
217 * Implementation of hook_mailhandler
218 *
219 * Here's where e-mail pre-processing is done
220 */
221 function actionfeed_mailhandler($node, $result, $i, $header, $mailbox) {
222 $fromaddress = mailhandler_get_fromaddress($header, $mailbox);
223 // If node not yet assigned to a user, try to find organization
224 if(!$node->uid && valid_email_address($fromaddress) && $organization = actionfeed_find_organization($fromaddress)) {
225 drupal_set_message(t("Ppipes: processing email from $fromaddress which belongs to $organization->title"));
226 // Set node params
227 $node->ppnid = $organization->nid;
228 $node->actionfeed = $organization;
229 $node->type = variable_get('actionfeed_node_type', 'story');
230 // Now, take care of users.
231 global $user;
232 mailhandler_switch_user(); // Back to original user
233 mailhandler_switch_user($organization->uid);
234 $node->uid = $organization->uid;
235 $node->name = $user->name;
236 // Input format
237 if(preg_match("/<(body|html)[^>]*>/i", $node->body)) {
238 $node->format = variable_get('actionfeed_filter_html', FILTER_FORMAT_DEFAULT);
239 } else {
240 $node->format = variable_get('actionfeed_filter_text', FILTER_FORMAT_DEFAULT);
241 }
242 // Ok, node will be submitted through mailhandler
243 return $node;
244 } else {
245 return $node;
246 }
247 }
248
249 function actionfeed_find_organization($email){
250 if($ppnid = actionfeed_find_email($email)){
251 return node_load(array('nid' => $ppnid));
252 } else {
253 return NULL;
254 }
255 }
256
257 function actionfeed_find_email($email) {
258 $result = db_query("SELECT nid FROM {actionfeed} WHERE sender_email LIKE '%".db_escape_string($email)."%'");
259 $nid = db_result($result);
260 return $nid;
261 }
262
263 /**
264 * Callbacks for pages
265 */
266 function actionfeed_page($arg = NULL){
267 drupal_set_html_head('<style type="text/css">@import url('.drupal_get_path('module','actionfeed').'/actionfeed.css);</style>');
268
269 switch($arg){
270 case 'all':
271 $output = actionfeed_page_latest();
272 break;
273 default:
274 if(is_numeric($arg)) {
275 $output = actionfeed_page_latest($arg);
276 } else {
277 $output = actionfeed_page_default();
278 }
279 break;
280 }
281 print theme('page', $output);
282 }
283
284 function actionfeed_page_default(){
285 drupal_set_title(variable_get('actionfeed_header', t('Action Feed')));
286 $output ='<div class="actionfeed-page actionfeed-page-default">';
287 $output .='<div id="actionfeed-header-tagline">'.variable_get('actionfeed_header_tagline', t('Action Feed lets you see email alerts from dozens of organizations in a single location.'))."</div>\n";
288 $output .='<h3>'.t('Latest message').'</h3>';
289 $latest_nid = db_result(db_query_range("SELECT n.nid FROM {node} n INNER JOIN {actionfeed_node} p USING(nid) WHERE n.status = 1 ORDER BY n.created DESC", 0, 1));
290 if($latest_nid && $latest = node_load(array('nid' => $latest_nid))){
291 $output .= node_view($latest, TRUE);
292 }
293 $output .='<h3>'.t('Read alerts from another organization')."</h3>\n";
294 $result = db_query("SELECT n.nid, n.title FROM {node} n WHERE n.type = 'actionfeed' ORDER BY n.title");
295 $list = array();
296 while($organization = db_fetch_object($result)){
297 $list[] = l($organization->title, 'actionfeed/'.$organization->nid);
298 }
299 $output .= theme('item_list', $list);
300 $output .= "<br />\n";
301 $output .= l(t('Read all latest alerts'), 'actionfeed/all');
302 $output .= "</div>\n"; // End of actionfeed-page
303 return $output;
304 }
305
306 function theme_actionfeed_list_organizations($list = array()){
307 $output = '<div class="actionfeed-list-organizations">';
308 foreach($list as $organization){
309
310 }
311 $output .= "</div>\n";
312 }
313
314 function actionfeed_page_latest($nid = NULL){
315 $output ='<div class="actionfeed-page actionfeed-page-latest">';
316 if(is_numeric($nid)){
317 $organization = node_load(array('nid' => $nid, 'type' => 'actionfeed'));
318 }
319 if(isset($organization->nid)){
320 drupal_set_title(t('Latest Action Feeds from %organization', array('%organization' => $organization->title)));
321 $whereorg = 'AND p.ppnid= '.$nid;
322 } else {
323 drupal_set_title(t('Latest Action Feeds'));
324 $whereorg = '';
325 }
326
327 $result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n INNER JOIN {actionfeed_node} p USING(nid) WHERE n.status = 1 $whereorg ORDER BY n.created DESC"), variable_get('default_nodes_main', 10));
328
329 if (db_num_rows($result)) {
330 drupal_add_link(array('rel' => 'alternate',
331 'type' => 'application/rss+xml',
332 'title' => 'RSS',
333 'href' => url($nid ? 'actionfeed/feed/'.$nid : 'actionfeed/feed', NULL, NULL, TRUE)));
334
335 while ($node = db_fetch_object($result)) {
336 $output .= node_view(node_load(array('nid' => $node->nid)), 1);
337 }
338 $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
339 }
340 $output .= theme('xml_icon', url($nid ? "actionfeed/feed/$nid" : 'actionfeed/feed'));
341 $output .= "</div>\n"; // End of actionfeed-page
342 return $output;
343 }
344
345
346 function actionfeed_feed($nid = NULL){
347 if(is_numeric($nid)){
348 $organization = node_load(array('nid' => $nid, 'type' => 'actionfeed'));
349 }
350 if(isset($organization->nid)){
351 $link = 'actionfeed/feed/'.$nid;
352 $title = t('Latest Action Feeds from %organization', array('%organization' => $organization->title));
353 $whereorg = 'AND p.ppid= '.$nid;
354 } else {
355 $link = 'actionfeed/feed';
356 $title = t('Latest Action Feeds');
357 $whereorg = '';
358 }
359
360 $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n INNER JOIN {actionfeed_node} p USING(nid) WHERE n.status = 1 $wereorg ORDER BY n.created DESC"), 0, variable_get('default_nodes_main', 10));
361 $channel['link'] = url('actionfeed/feed/'.$nid);
362 $channel['title'] = variable_get('site_name', 'drupal') .' - '. t("Action feeds");
363 $channel['description'] = $title;
364
365 node_feed($result, $channel);
366
367 }
368 /**
369 * Implementation of hook filter
370 */
371 function actionfeed_filter($op, $delta = 0, $format = -1, $text = '') {
372 switch ($op) {
373 case 'list':
374 return array(0 => t('HTML E-mail filter'));
375 case 'description':
376 return t("Some basic cleanup for HTML e-mails");
377 case 'no cache':
378 return FALSE;
379 case 'prepare':
380 // Remove HTML before and after <body>
381 $text = preg_replace('|.*?<body[^>]*?>|is', '', $text);
382 $text = preg_replace('|</body.*|is', '', $text);
383
384 // Only one-line tags
385 while(preg_match('/<([^>]*?)\n/s', $text)) {
386 $text = preg_replace('/<([^>]*?)\n/s','<$1 ' , $text);
387 }
388
389 // Remove several style blocks
390 $text = preg_replace('|<style.*?</style[^>]*?>|is', '', $text);
391
392 // Remove JavaScript
393 $text = preg_replace('/<script\W.*?<\/script[^>]*>/is', '', $text);
394 $text = preg_replace('/\Won[a-z]+\s*=[^>]+?>/i', '>', $text);
395
396 // Strip out some images
397 $text = preg_replace('/<img.*?\ssrc\W+(?!=http)[^>]*?>/i', '', $text);
398
399 return $text;
400 case 'process':
401 return $text;
402 case 'settings':
403 return "";
404 default:
405 return $text;
406 }
407 }
408
409 /**
410 * Implementation of hook_filter_tips().
411 */
412 function actionfeed_filter_tips($delta, $format, $long = false) {
413 switch ($delta) {
414 case 0:
415 if($long) {
416 $output = t("Basic cleanup for HTML e-mails");
417 $output .= t("<ul>
418 <li>Extracts HTML &lt;body&gt; element</li>
419 <li>Strip out &lt;style&gt; blocks</li>
420 <li>Strips out JavaScript code</li>
421 <li>Some clean up for images</li>
422 </ul>");
423 return $output;
424 } else {
425 return t("Basic cleanup for HTML e-mails");
426 }
427 }
428 }
429
430 /**
431 * Ppipes node type implementation
432 */
433
434 function actionfeed_access($op, $node) {
435 global $user;
436 switch($op){
437 case 'view':
438 return $node->status;
439 case 'create':
440 return user_access("create actionfeed organizations");
441 case 'update':
442 case 'delete':
443 if($node->uid == $user->uid){
444 return user_access("edit own actionfeed organizations");
445 }
446 break;
447 }
448 }
449
450 function actionfeed_form(&$node) {
451
452 $output .= form_textfield(t("Sender Email Address"), "sender_email", $node->sender_email, 500, 500, t("This can be a single e-mail address or any list of e-mail addresses"));
453 $output .= form_textfield(t("Home Page"), "homepage", $node->homepage, 60, 255, t("Home page of the organization. This must be a full url, starting with http://"));
454
455 if (function_exists("taxonomy_node_form")) {
456 $output .= implode("", taxonomy_node_form("actionfeed", $node));
457 }
458
459 $output .= form_textarea(t("Description"), 'body', $node->body, 20, 10, t("Description for this organization to be displayed."));
460
461 $output .= filter_form('format', $node->format);
462
463 return $output;
464 }
465
466
467 function actionfeed_view(&$node, $teaser = FALSE, $page = FALSE) {
468 $node = node_prepare($node, $teaser);
469 $homepage = $node->homepage ? form_item(t('Home Page'),l(t($node->homepage), $node->homepage)) : '';
470 if($teaser) {
471 $node->teaser = $node->teaser. $homepage;
472 } else {
473 $node->body = $node->body. $homepage;
474 }
475
476 }
477
478 function actionfeed_load($node) {
479 $page = db_fetch_object(db_query("SELECT * FROM {actionfeed} WHERE nid = %d", $node->nid));
480 return $page;
481 }
482
483 function actionfeed_node_name($node) {
484 return t("actionfeed organization");
485 }
486
487 // Db Layer
488
489 function actionfeed_insert($node) {
490 db_query("INSERT INTO {actionfeed} (nid, sender_email, homepage) VALUES (%d, '%s', '%s')", $node->nid, $node->sender_email, $node->homepage);
491 }
492 function actionfeed_update($node) {
493 db_query("UPDATE {actionfeed} SET sender_email = '%s', homepage = '%s' WHERE nid = %d", $node->sender_email, $node->homepage, $node->nid);
494 }
495 function actionfeed_delete(&$node) {
496 db_query("DELETE FROM {actionfeed} WHERE nid = %d", $node->nid);
497 db_query("DELETE FROM {actionfeed_node} WHERE ppnid= %d", $node->nid);
498 }
499
500 ?>

  ViewVC Help
Powered by ViewVC 1.1.2