Changeset 171
- Timestamp:
- Jan 29, 2007 11:38:31 PM (6 years ago)
- Location:
- trunk/jpdd
- Files:
-
- 6 edited
-
class.dkg.site.php (modified) (6 diffs)
-
class.jpdd.php (modified) (2 diffs)
-
config.inc.php (modified) (1 diff)
-
sql/basics.sql (modified) (2 diffs)
-
sql/db.sql (modified) (5 diffs)
-
web/styles.css (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/jpdd/class.dkg.site.php
r169 r171 135 135 136 136 // we're relying on a functioning mail() function. 137 function mail($type, $to,$subj,$body, $hdrs = array()) { 137 // returning true means it actually was queued for delivery. 138 // returning false means it was never queued. 139 function mail($type, $to,$subj,$body, $hdrs = array(), $broadcast_id = NULL) { 138 140 if (!is_array($hdrs)) 139 141 $hdrs = array($hdrs); … … 142 144 143 145 // log it: 144 $this->executeSQL('INSERT INTO mail_log (mail_from, mail_to, subject, body, extra_headers, message_type, actually_sent ) VALUES ('.$this->escStr($this->_site_email_from).','.146 $this->executeSQL('INSERT INTO mail_log (mail_from, mail_to, subject, body, extra_headers, message_type, actually_sent, broadcast_id) VALUES ('.$this->escStr($this->_site_email_from).','. 145 147 $this->escStr($to).','. 146 148 $this->escStr($subj).','. … … 148 150 $this->escStr($hdrs).','. 149 151 $this->escStr($type).','. 150 ($this->_actually_send_email ? 'true' : 'false'). 152 ($this->_actually_send_email ? 'true' : 'false').','. 153 $this->intOrDefault($broadcast_id). 151 154 ')', false); 152 155 if ($this->_actually_send_email) 153 mail($to, $subj, $body, $hdrs); 156 return mail($to, $subj, $body, $hdrs); 157 else 158 return false; // we didn't actually send the mail. 154 159 } 155 160 … … 185 190 186 191 function getAllowedActions() { 187 return array('edit', 'login', 'logout', 'resetpass', 'newacct' );192 return array('edit', 'login', 'logout', 'resetpass', 'newacct', 'broadcast'); 188 193 } 189 194 … … 963 968 } 964 969 } 970 } elseif ($this->_action == 'broadcast') { 971 if ($this->_authenticated_user->HasAllOfThesePrivileges('Send Broadcast')) { 972 if ($_SERVER['REQUEST_METHOD'] == 'POST') { 973 if ($_POST['submit'] == 'Send') { 974 return $this->sendBroadcastEmails(); 975 } else { 976 return $this->getBroadcastEmailForm(); 977 } 978 } else { 979 return $this->getBroadcastEmailForm(); 980 } 981 } else 982 return $this->permissionDenied('Broadcast not allowed.'); 965 983 } else { 966 984 return $this->getMainContentExtended(); 967 985 } 986 } 987 988 function getBroadcastSelectors() { 989 // override to return an array that maps internal keys to 990 // visible labels and SQL statements. For example: 991 return array('all' => array('description' => 'Every account with a confirmed e-mail', 992 'sql' => 'SELECT * FROM person WHERE pass IS NOT NULL')); 993 } 994 995 function getAllowedTemplates() { 996 // override to return an array that maps selectors to 997 // array('description' = "human readable", 'function' => actual 998 // php function) 999 return array('[[NAME]]' => array('description' => 'The person\'s name', 1000 'function' => create_function('$x', 'return $x->getTitle();'))); 1001 } 1002 1003 function getAllowedTemplateLegend() { 1004 $temps = $this->getAllowedTemplates(); 1005 return "<div class=\"template-legend\">Allowed personalization terms:<dl>\n". 1006 join('', array_map(create_function('$x,$y', 'return "<dt>".$x."</dt>\n<dd>".$y["description"]."</dd>\n";'), 1007 array_keys($temps), $temps))."</dl>\n</div>\n"; 1008 } 1009 1010 function getBroadcastSelectorInput() { 1011 $selectors = $this->getBroadcastSelectors(); 1012 return '<select name="selector"> 1013 '.join("\n", array_map(create_function('$v, $l', 'global $dkg_site; return "<option value=\"".$v."\">".$l["description"]." (".$dkg_site->getValueFromSQL("SELECT COUNT(*) AS count FROM (".$l["sql"].") AS selector", "count").")</option>";'), array_keys($selectors), $selectors)).' 1014 </select> 1015 '; 1016 } 1017 1018 // $txt can be either a string or an array of strings. the return 1019 // value will match. 1020 function applyBroadcastTemplate($txt, $user) { 1021 $temps = $this->getAllowedTemplates(); 1022 $vals = array(); 1023 reset($temps); 1024 while(list($temp,$x) = each($temps)) { 1025 $vals[] = $x['function']($user); 1026 } 1027 return str_ireplace(array_keys($temps), $vals, $txt); 1028 } 1029 1030 function sendBroadcastEmails() { 1031 if ($_SERVER['REQUEST_METHOD'] != 'POST') { 1032 $this->addWarning('You cannot send broadcasts with a GET request.'); 1033 return ''; 1034 } 1035 1036 $subj = $_POST['subject']; 1037 $content = $_POST['content']; 1038 1039 $selector_name = $_POST['selector']; 1040 $selectors = $this->getBroadcastSelectors(); 1041 if (!array_key_exists($selector_name, $selectors)) { 1042 $this->addWarning('You chose an unavailable selector!'); 1043 return ''; 1044 } 1045 $selector = $selectors[$selector_name]; 1046 1047 // store this broadcast template in the database: 1048 $bid = $this->insertBroadcast($subj, $content, $selector_name); 1049 1050 // we're gonna grab some peops: 1051 $map = $this->prepClass('person'); 1052 $cname = $map['classname']; 1053 $objs = $this->getSeriesFromSQL($selector['sql'], $cname); 1054 $attempted = 0; 1055 $succeeded = 0; 1056 reset($objs); 1057 while(list(,$obj) = each($objs)) { 1058 $to = $obj->_email; 1059 $subj = trim(str_replace("\n", '', $this->applyBroadcastTemplate($subj, $obj))); 1060 $body = trim(wordwrap($this->applyBroadcastTemplate($content, $obj))); 1061 $attempted++; 1062 if ($this->mail('broadcast', $to,$subj,$body, array(), $bid)) 1063 $succeeded++; 1064 } 1065 return $succeeded.' out of '.$attempted.' mails sent.'; 1066 } 1067 1068 function getBroadcastEmailForm() { 1069 $subj = ''; 1070 $content = ''; 1071 $preview = ''; 1072 $ret = ''; 1073 1074 if ($_SERVER['REQUEST_METHOD'] == 'POST') { 1075 if ($this->_actually_send_email) 1076 $this->addWarning('Sending e-mail is actually enabled. Please be careful with this!'); 1077 else 1078 $ret .= '<div>Sending e-mail is currently disabled. Messages will be logged, but not actually sent.</div>'; 1079 $subj = $_POST['subject']; 1080 $content = $_POST['content']; 1081 1082 $selector = $_POST['selector']; 1083 $selectors = $this->getBroadcastSelectors(); 1084 if (!array_key_exists($selector, $selectors)) { 1085 $this->addWarning('You chose an unavailable selector!'); 1086 return ''; 1087 } 1088 $selector = $selectors[$selector]; 1089 1090 $preview = '<fieldset><legend>Preview Example:</legend>'; 1091 1092 // we're gonna grab a person: 1093 $map = $this->prepClass('person'); 1094 $cname = $map['classname']; 1095 $data = $this->getSingletonFromSQL($selector['sql'].' LIMIT 1', false); 1096 if (is_null($data)) { 1097 $preview .= '<span class="error">There are no selectors which match <q>'.$selector['description'].'</q></span>'; 1098 } else { 1099 $obj = new $cname(array('data' => $data)); 1100 $preview .= '<pre>To: '.$obj->_email.' 1101 Subject: '.htmlentities(trim(str_replace("\n", '', $this->applyBroadcastTemplate($subj, $obj)))).' 1102 1103 '.htmlentities(trim(wordwrap($this->applyBroadcastTemplate($content, $obj)))).'</pre>'; 1104 } 1105 $preview .= '</fieldset>'; 1106 } 1107 1108 return $ret.'<form name="broadcast" action="'.$this->Path('broadcast').'" method="post"> 1109 '.$this->getFormTokenHiddenInput().' 1110 <fieldset><legend>Send to:</legend> 1111 '.$this->getBroadcastSelectorInput().' 1112 </fieldset> 1113 '.$preview.' 1114 <fieldset><legend>Message Content:</legend> 1115 '.$this->getAllowedTemplateLegend().' 1116 <label>Subject:<br /> 1117 <input name="subject" type="text" size="60" value="'.htmlentities($subj).'" /><br /> 1118 <label>Body:<br /> 1119 <textarea name="content" rows="20" cols="72">'.htmlentities($content). 1120 '</textarea> 1121 </label><br/> 1122 <input type="submit" class="submit" name="submit" value="Preview"/> 1123 '.($_SERVER['REQUEST_METHOD'] == 'POST' ? '<input class="submit" type="submit" name="submit" value="Send"/>' : '').' 1124 </fieldset> 1125 </form>'; 968 1126 } 969 1127 … … 1033 1191 } 1034 1192 1193 function insertBroadcast($subj, $body, $selector) { 1194 $this->executeSQL('INSERT INTO broadcast (subj, body, selector, sender_id) VALUES ('.$this->escStr($subj).', '. 1195 $this->escStr($body).', '. 1196 $this->escStr($selector).', '. 1197 (int)$this->_authenticated_user->getID().')'); 1198 // return the last id from the log: 1199 return (int)$this->getValueFromSQL('SELECT currval(\'broadcast_id_seq\') AS broadcast_id', 'broadcast_id'); 1200 } 1201 1035 1202 function log($data) { 1036 1203 $this->executeSQL('INSERT INTO log (data, backtrace, servervars) VALUES ('.$this->escStr($data).', '. -
trunk/jpdd/class.jpdd.php
r168 r171 45 45 } 46 46 47 48 function getBroadcastSelectors() { 49 // override to return an array that maps internal keys to 50 // visible labels and SQL statements. For example: 51 return array_merge(array('dkg' => array('description' => 'People named Gillmor', 52 'sql' => 'SELECT * FROM person WHERE last_name = '.$this->escStr('Gillmor'))), 53 parent::getBroadcastSelectors() 54 ); 55 } 56 47 57 function getNavLink($title,$targ) { 48 58 return '<a '.(($this->_action == $targ || (in_array($this->_action, array('view', 'edit')) && $this->_type == $targ)) ? 'class="current" ' : '').'href='.$this->Path($targ).'>'.$title.'</a>'; … … 63 73 if ($this->_authenticated_user->hasAllOfThesePrivileges('Update Workshops', 'Edit People', 'Edit Categories')) 64 74 $links['Review Signups'] = 'overview'; 75 if ($this->_authenticated_user->hasAllOfThesePrivileges('Send Broadcast')) 76 $links['E-mail Alert'] = 'broadcast'; 65 77 } else { 66 78 if ($this->_action != 'newacct') -
trunk/jpdd/config.inc.php
r169 r171 30 30 // if this is set to false, no e-mail will actually go out, though 31 31 // it will be written to the log. Defaults to true. 32 'actually_send_email' => false,32 'actually_send_email' => true, 33 33 ); -
trunk/jpdd/sql/basics.sql
r144 r171 72 72 -- 73 73 74 SELECT pg_catalog.setval(pg_catalog.pg_get_serial_sequence('privilege', 'id'), 7, true);74 SELECT pg_catalog.setval(pg_catalog.pg_get_serial_sequence('privilege', 'id'), 8, true); 75 75 76 76 … … 87 87 6 List People This allows users to see a list of all people signed up for the conference 88 88 7 Edit Categories This allows users to modify the available categories 89 8 Send Broadcast This allows users to broadcast templated messages to groups of signed-up users 89 90 \. 90 91 -
trunk/jpdd/sql/db.sql
r169 r171 81 81 82 82 ALTER TABLE public.audience_by_organization OWNER TO dkg; 83 84 -- 85 -- Name: broadcast; Type: TABLE; Schema: public; Owner: dkg; Tablespace: 86 -- 87 88 CREATE TABLE broadcast ( 89 id serial NOT NULL, 90 subj character varying NOT NULL, 91 body text NOT NULL, 92 selector character varying NOT NULL, 93 sender_id integer NOT NULL 94 ); 95 96 97 ALTER TABLE public.broadcast OWNER TO dkg; 83 98 84 99 -- … … 123 138 whattime timestamp with time zone DEFAULT now() NOT NULL, 124 139 actually_sent boolean DEFAULT true NOT NULL, 125 message_type character varying DEFAULT 'newacct'::character varying NOT NULL 140 message_type character varying DEFAULT 'newacct'::character varying NOT NULL, 141 broadcast_id integer 126 142 ); 127 143 … … 272 288 273 289 -- 290 -- Name: broadcast_pkey; Type: CONSTRAINT; Schema: public; Owner: dkg; Tablespace: 291 -- 292 293 ALTER TABLE ONLY broadcast 294 ADD CONSTRAINT broadcast_pkey PRIMARY KEY (id); 295 296 297 -- 274 298 -- Name: category_pkey; Type: CONSTRAINT; Schema: public; Owner: dkg; Tablespace: 275 299 -- … … 453 477 ALTER TABLE ONLY attendance 454 478 ADD CONSTRAINT attendance_workshop_id_fkey FOREIGN KEY (workshop_id) REFERENCES workshop(id); 479 480 481 -- 482 -- Name: broadcast_sender_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: dkg 483 -- 484 485 ALTER TABLE ONLY broadcast 486 ADD CONSTRAINT broadcast_sender_id_fkey FOREIGN KEY (sender_id) REFERENCES person(id); 487 488 489 -- 490 -- Name: mail_log_broadcast_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: dkg 491 -- 492 493 ALTER TABLE ONLY mail_log 494 ADD CONSTRAINT mail_log_broadcast_id_fkey FOREIGN KEY (broadcast_id) REFERENCES broadcast(id); 455 495 456 496 … … 574 614 575 615 -- 616 -- Name: broadcast; Type: ACL; Schema: public; Owner: dkg 617 -- 618 619 REVOKE ALL ON TABLE broadcast FROM PUBLIC; 620 REVOKE ALL ON TABLE broadcast FROM dkg; 621 GRANT ALL ON TABLE broadcast TO dkg; 622 GRANT INSERT ON TABLE broadcast TO "www-data"; 623 624 625 -- 626 -- Name: broadcast_id_seq; Type: ACL; Schema: public; Owner: dkg 627 -- 628 629 REVOKE ALL ON TABLE broadcast_id_seq FROM PUBLIC; 630 REVOKE ALL ON TABLE broadcast_id_seq FROM dkg; 631 GRANT ALL ON TABLE broadcast_id_seq TO dkg; 632 GRANT SELECT,UPDATE ON TABLE broadcast_id_seq TO "www-data"; 633 634 635 -- 576 636 -- Name: category; Type: ACL; Schema: public; Owner: dkg 577 637 -- -
trunk/jpdd/web/styles.css
r157 r171 102 102 } 103 103 104 105 .template-legend { 106 background: silver; 107 color: black; 108 padding: 1em; 109 margin: 0.5em; 110 } 111 .template-legend dl dt { 112 font-weight: bold; 113 } 114 .template-legend dl dd { 115 font-style: italic; 116 } 117 104 118 @media print { 105 119
Note: See TracChangeset
for help on using the changeset viewer.

