d9ad35ecdbe56e083359d6478cae36dda1717f9d
[platal.git] / massmailer.inc.php
1 <?php
2 /***************************************************************************
3 * Copyright (C) 2003-2007 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
21
22 require_once("xorg.misc.inc.php");
23
24 // {{{ class MassMailer
25
26 abstract class MassMailer
27 {
28 private $_tpl;
29 private $_css;
30 private $_prefix;
31
32 public $_id;
33 public $_shortname;
34 public $_title;
35 public $_title_mail;
36
37 public $_head;
38
39 function __construct($tpl, $css, $prefix)
40 {
41 $this->_tpl = $tpl;
42 $this->_css = $css;
43 $this->_prefix = $prefix;
44 }
45
46 public function id()
47 {
48 return is_null($this->_shortname) ? $this->_id : $this->_shortname;
49 }
50
51 public function title($mail = false)
52 {
53 return $mail ? $this->_title_mail : $this->_title;
54 }
55
56 public function head($prenom = null, $nom = null, $sexe = null, $type = 'text')
57 {
58 if (is_null($prenom)) {
59 return $this->_head;
60 } else {
61 $head = $this->_head;
62 $head = str_replace('<cher>', $sexe ? 'Chère' : 'Cher', $head);
63 $head = str_replace('<prenom>', $prenom, $head);
64 $head = str_replace('<nom>', $nom, $head);
65 return format_text($head, $type, 2, 64);
66 }
67 }
68
69 public function css(&$page = null)
70 {
71 if (!is_null($page)) {
72 $page->addCssLink($this->_css);
73 return true;
74 } else {
75 $css = file_get_contents(dirname(__FILE__) . '/../htdocs/css/' . $this->_css);
76 return preg_replace('@/\*.*?\*/@s', '', $css);
77 }
78 }
79
80 public function toText(&$page, $prenom, $nom, $sexe)
81 {
82 $this->css($page);
83 $page->assign('is_mail', false);
84 $page->assign('html_version', false);
85 $page->assign('prenom', $prenom);
86 $page->assign('nom', $nom);
87 $page->assign('sexe', $sexe);
88 $this->assignData($page);
89 }
90
91 public function toHtml(&$page, $prenom, $nom, $sexe)
92 {
93 $this->css($page);
94 $page->assign('prefix', $this->_prefix . '/' . $this->id());
95 $page->assign('is_mail', false);
96 $page->assign('html_version', true);
97 $page->assign('prenom', $prenom);
98 $page->assign('nom', $nom);
99 $page->assign('sexe', $sexe);
100 $this->assignData($page);
101 }
102
103 public function sendTo($prenom, $nom, $login, $sexe, $html)
104 {
105 global $globals;
106
107 $mailer = new PlMailer($this->_tpl);
108 $this->assignData($mailer);
109 $mailer->assign('is_mail', true);
110 $mailer->assign('prenom', $prenom);
111 $mailer->assign('nom', $nom);
112 $mailer->assign('sexe', $sexe);
113 $mailer->assign('prefix', null);
114 $mailer->addTo("\"$prenom $nom\" <$login@{$globals->mail->domain}>");
115 $mailer->send($html);
116 }
117
118 public function sendToAll()
119 {
120 $this->setSent();
121 $query = "SELECT u.user_id, a.alias,
122 u.prenom, IF(u.nom_usage='', u.nom, u.nom_usage),
123 FIND_IN_SET('femme', u.flags),
124 q.core_mail_fmt AS pref
125 FROM {$this->subscriptionTable()} AS ni
126 INNER JOIN auth_user_md5 AS u USING(user_id)
127 INNER JOIN auth_user_quick AS q ON(q.user_id = u.user_id)
128 INNER JOIN aliases AS a ON(u.user_id=a.id AND FIND_IN_SET('bestalias',a.flags))
129 LEFT JOIN emails AS e ON(e.uid=u.user_id AND e.flags='active')
130 WHERE ni.last < {?} AND ({$this->subscriptionWhere()}) AND e.email IS NOT NULL
131 GROUP BY u.user_id
132 LIMIT 60";
133 while (true) {
134 $res = XDB::iterRow($query, $this->_id);
135 if (!$res->total()) {
136 exit;
137 }
138 $sent = array();
139 while (list($uid, $bestalias, $prenom, $nom, $sexe, $fmt) = $res->next()) {
140 $sent[] = "user_id='$uid'";
141 $this->sendTo($prenom, $nom, $bestalias, $sexe, $fmt=='html');
142 }
143 XDB::execute("UPDATE {$this->subscriptionTable()}
144 SET last = {?}
145 WHERE " . implode(' OR ', $sent), $this->_id);
146 sleep(60);
147 }
148 }
149
150 abstract protected function assignData(&$smarty);
151 abstract protected function setSent();
152
153 abstract protected function subscriptionTable();
154 abstract protected function subscriptionWhere();
155 }
156
157 // }}}
158 // {{{ Functions
159
160 function justify($text,$n)
161 {
162 $arr = explode("\n",wordwrap($text,$n));
163 $arr = array_map('trim',$arr);
164 $res = '';
165 foreach ($arr as $key => $line) {
166 $nxl = isset($arr[$key+1]) ? trim($arr[$key+1]) : '';
167 $nxl_split = preg_split('! +!',$nxl);
168 $nxw_len = count($nxl_split) ? strlen($nxl_split[0]) : 0;
169 $line = trim($line);
170
171 if (strlen($line)+1+$nxw_len < $n) {
172 $res .= "$line\n";
173 continue;
174 }
175
176 if (preg_match('![.:;]$!',$line)) {
177 $res .= "$line\n";
178 continue;
179 }
180
181 $tmp = preg_split('! +!',trim($line));
182 $words = count($tmp);
183 if ($words <= 1) {
184 $res .= "$line\n";
185 continue;
186 }
187
188 $len = array_sum(array_map('strlen',$tmp));
189 $empty = $n - $len;
190 $sw = floatval($empty) / floatval($words-1);
191
192 $cur = 0;
193 $l = '';
194 foreach ($tmp as $word) {
195 $l .= $word;
196 $cur += $sw + strlen($word);
197 $l = str_pad($l,intval($cur+0.5));
198 }
199 $res .= trim($l)."\n";
200 }
201 return trim($res);
202 }
203
204 function format_text($input, $format, $indent = 0, $width = 68)
205 {
206 if ($format == 'text') {
207 return enriched_to_text($input, false, true, $indent, $width);
208 }
209 return enriched_to_text($input, true);
210 }
211
212 function enriched_to_text($input,$html=false,$just=false,$indent=0,$width=68)
213 {
214 $text = trim($input);
215 if ($html) {
216 $text = htmlspecialchars($text);
217 $text = str_replace('[b]','<strong>', $text);
218 $text = str_replace('[/b]','</strong>', $text);
219 $text = str_replace('[i]','<em>', $text);
220 $text = str_replace('[/i]','</em>', $text);
221 $text = str_replace('[u]','<span style="text-decoration: underline">', $text);
222 $text = str_replace('[/u]','</span>', $text);
223 $text = preg_replace("!(\\s*\n)*\[title\]!",'<h1>',$text);
224 $text = preg_replace("!\[\/title\](\\s*\n)*!", '</h1>',$text);
225 $text = preg_replace("!(\\s*\n)*\[subtitle\]!",'<h2>',$text);
226 $text = preg_replace("!\[\/subtitle\](\\s*\n)*!",'</h2>',$text);
227
228 require_once('url_catcher.inc.php');
229 $text = url_catcher($text);
230 return nl2br($text);
231 } else {
232 $text = preg_replace('!\[\/?b\]!','*',$text);
233 $text = preg_replace('!\[\/?u\]!','_',$text);
234 $text = preg_replace('!\[\/?i\]!','/',$text);
235 $text = preg_replace('!\[\/?title\]!','***', $text);
236 $text = preg_replace('!\[\/?subtitle\]!','**', $text);
237 $text = preg_replace('!(((https?|ftp)://|www\.)[^\r\n\t ]*)!','[\1]', $text);
238 $text = preg_replace('!(([a-zA-Z0-9\-_+.]*@[a-zA-Z0-9\-_+.]*)(?:\?[^\r\n\t ]*)?)!','[mailto:\1]', $text);
239 $text = $just ? justify($text,$width-$indent) : wordwrap($text,$width-$indent);
240 if($indent) {
241 $ind = str_pad('',$indent);
242 $text = $ind.str_replace("\n","\n$ind",$text);
243 }
244 return $text;
245 }
246 }
247
248 // }}}
249
250 // vim:set et sw=4 sts=4 sws=4:
251 ?>