Merge commit 'origin/fusionax' into account
[platal.git] / include / massmailer.inc.php
1 <?php
2 /***************************************************************************
3 * Copyright (C) 2003-2009 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 // {{{ class MailNotFound
23
24 class MailNotFound extends Exception {
25 }
26
27 // }}}
28
29 // {{{ class MassMailer
30
31 abstract class MassMailer
32 {
33 private $_tpl;
34 private $_css;
35 private $_prefix;
36
37 public $_id;
38 public $_shortname;
39 public $_title;
40 public $_title_mail;
41
42 public $_head;
43
44 protected $_table;
45 protected $_subscriptionTable;
46
47 function __construct($tpl, $css, $prefix, $tbl, $stbl)
48 {
49 $this->_tpl = $tpl;
50 $this->_css = $css;
51 $this->_prefix = $prefix;
52 $this->_table = $tbl;
53 $this->_subscriptionTable = $stbl;
54 }
55
56 public function id()
57 {
58 return is_null($this->_shortname) ? $this->_id : $this->_shortname;
59 }
60
61 private function selectId($where)
62 {
63 $res = XDB::query("SELECT IF (n.short_name IS NULL, n.id, n.short_name)
64 FROM {$this->_table} AS n
65 WHERE n.bits != 'new' AND {$where}
66 LIMIT 1");
67 if ($res->numRows() != 1) {
68 return null;
69 }
70 return $res->fetchOneCell();
71 }
72
73 public function prev()
74 {
75 static $val;
76 if (!isset($val)) {
77 $val = $this->selectId("n.id < {$this->_id} ORDER BY n.id DESC");
78 }
79 return $val;
80 }
81
82 public function next()
83 {
84 static $val;
85 if (!isset($val)) {
86 $val = $this->selectId("n.id > {$this->_id} ORDER BY n.id");
87 }
88 return $val;
89 }
90
91 public function last()
92 {
93 static $val;
94 if (!isset($val)) {
95 $res = XDB::query("SELECT MAX(n.id)
96 FROM {$this->_table} AS n
97 WHERE n.bits != 'new' AND n.id > {?}",
98 $this->_id);
99 if ($res->numRows() != 1) {
100 $val = null;
101 } else {
102 $val = $res->fetchOneCell();
103 }
104 }
105 return $val;
106 }
107
108 public function title($mail = false)
109 {
110 return $mail ? $this->_title_mail : $this->_title;
111 }
112
113 public function head($user = null, $type = 'text')
114 {
115 if (is_null($user)) {
116 return $this->_head;
117 } else {
118 $head = $this->_head;
119 $head = str_replace('<cher>', $user->isFemale() ? 'Chère' : 'Cher', $head);
120 $head = str_replace('<prenom>', $user->displayName(), $head);
121 $head = str_replace('<nom>', '', $head);
122 return format_text($head, $type, 2, 64);
123 }
124 }
125
126 public function css(&$page = null)
127 {
128 if (!is_null($page)) {
129 $page->addCssLink($this->_css);
130 return true;
131 } else {
132 $css = file_get_contents(dirname(__FILE__) . '/../htdocs/css/' . $this->_css);
133 return preg_replace('@/\*.*?\*/@us', '', $css);
134 }
135 }
136
137 public function toText(&$page, $user)
138 {
139 $this->css($page);
140 $page->assign('is_mail', false);
141 $page->assign('mail_part', 'text');
142 $page->assign('user', $user);
143 $this->assignData($page);
144 }
145
146 public function toHtml(&$page, $user)
147 {
148 $this->css($page);
149 $page->assign('prefix', $this->_prefix . '/' . $this->id());
150 $page->assign('is_mail', false);
151 $page->assign('mail_part', 'html');
152 $page->assign('user', $user);
153 $this->assignData($page);
154 }
155
156 private function createHash($line, $key = null)
157 {
158 $hash = implode(time(), $line) . rand();
159 $hash = md5($hash);
160 return $hash;
161 }
162
163 public function sendTo($user, $hash = null)
164 {
165 if (is_null($hash)) {
166 $hash = XDB::fetchOneCell("SELECT hash
167 FROM {$this->_subscriptionTable}
168 WHERE user_id = {?}", $user->id());
169 }
170 if (is_null($hash)) {
171 $hash = $this->createHash(array($user->displayName(), $user->fullName(),
172 $user->isFemale(), $user->isEmailFormatHtml(),
173 rand(), "X.org rulez"));
174 XDB::execute("UPDATE {$this->_subscriptionTable} as ni
175 SET ni.hash = {?}
176 WHERE ni.user_id != {?}",
177 $hash, $user->id());
178 }
179
180 $mailer = new PlMailer($this->_tpl);
181 $this->assignData($mailer);
182 $mailer->assign('is_mail', true);
183 $mailer->assign('user', $user);
184 $mailer->assign('prefix', null);
185 $mailer->assign('hash', $hash);
186 $mailer->addTo('"' . $user->fullName() . '" <' . $user->bestEmail() . '>');
187 $mailer->send($user->isEmailFormatHtml());
188 }
189
190 protected function getAllRecipients()
191 {
192 global $globals;
193 return "SELECT a.uid
194 FROM {$this->_subscriptionTable} AS ni
195 INNER JOIN accounts AS a ON (ni.user_id = a.uid)
196 LEFT JOIN email_options AS eo ON (eo.uid = a.uid)
197 LEFT JOIN emails AS e ON (e.uid = a.uid AND e.flags='active')
198 WHERE ni.last < {?} AND ({$this->subscriptionWhere()}) AND
199 (e.email IS NOT NULL OR FIND_IN_SET('googleapps', eo.storage))
200 GROUP BY a.uid";
201 }
202
203 public function sendToAll()
204 {
205 $this->setSent();
206 $query = XDB::format($this->getAllRecipients(), $this->id()) . ' LIMIT 60';
207 while (true) {
208 $users = User::getBulkUsersWithUIDs(XDB::fetchColumn($query));
209 if (count($users) == 0) {
210 return;
211 }
212 foreach ($users as $user) {
213 $sent[] = XDB::format('user_id = {?}', $user->id());
214 $this->sendTo($user, $hash);
215 }
216 XDB::execute("UPDATE {$this->_subscriptionTable}
217 SET last = {?}
218 WHERE " . implode(' OR ', $sent), $this->_id);
219
220 sleep(60);
221 }
222 }
223
224 abstract protected function assignData(&$smarty);
225 abstract protected function setSent();
226
227 abstract protected function subscriptionWhere();
228 }
229
230 // }}}
231 // {{{ Functions
232
233 function format_text($input, $format, $indent = 0, $width = 68)
234 {
235 if ($format == 'text') {
236 return MiniWiki::WikiToText($input, true, $indent, $width, "title");
237 }
238 return MiniWiki::WikiToHTML($input, "title");
239 }
240
241 // function enriched_to_text($input,$html=false,$just=false,$indent=0,$width=68)
242
243 // }}}
244
245 // vim:set et sw=4 sts=4 sws=4 enc=utf-8:
246 ?>