2 require_once 'MTrackWeb.php';
4 class MTrackWeb_Cron_Notify extends MTrackWeb
9 $ff = HTML_FlexyFramework::get();
13 HTML_FlexyFramework::ensureSingle(__FILE__, $this);
20 DB_DataObject::debugLevel(1);
21 date_default_timezone_set('UTC');
23 // what's the baserul..
26 $MAX_DIFF = 200 * 1024;
27 $USE_BATCHING = false;
30 $e= DB_DataObject::factory('Events');
31 $e->action = 'MTRACK.NOTIFY';
33 $e->selectAdd('MAX(event_when) as event_when');
35 if (!$e->find(true)) {
36 $e->event_when = date('Y-m-d H:i:s', 0); // should be a long time ago..
41 stream_filter_register("mtrackcanonical", 'CanonicalLineEndingFilter');
42 stream_filter_register("mtrackunix", 'UnixLineEndingFilter');
44 $w = DB_DataObject::factory('core_watch');
45 // returns a list of user with the objects they are watching..
46 $watches = $w->watched('email');
48 $CS = DB_DataObject::factory('mtrack_change');
52 foreach($watches as $uid => $ar) {
53 // we can now query mtrack_change for anything that occured in that list..
54 $messages = $CS->gatherChanges($e->event_when, $uid, $ar);
55 //print_R($messages);exit;
56 // we should cache the emails. = as multiple people might be getting the same email.
58 // should be like a list of tickets
59 foreach ($messages as $m=>$ar) {
60 $lr = explode(':', $m);
61 $o = DB_DataObject::Factory($lr[0]);
63 if (!isset($cache[implode(',', $ar)])) {
65 $cs->whereAddIn('mtrack_change.id', $ar, 'int');
67 $cache[implode(',', $ar)] = $cs->fetchAll();
69 $u = DB_DataObject::factory('Person');
71 $method = 'notify_'. $lr[0] ;
72 if (method_exists($this,$method)) {
73 $this->$method($o, $cache[implode(',', $ar)], $u);
84 // print_R($messages);
91 /* For each watcher, compute the changes.
92 * Group changes by ticket, sending one email per ticket.
93 * Group tickets into batch updates if the only fields that changed are
94 * bulk update style (milestone, assignment etc.)
96 * For the wiki repo, group by file so that serial edits within the batch
97 * period show up as a single email.
105 * - from (system or a specific user.)
110 function calcAddress($changes, $user) {
111 $ff = HTML_FlexyFramework::get();
114 $headers['To'] = '"'. addslashes($user->name). '" <' . $user->email .'>';
115 $headers['From'] = $ff->MTrack['email_address']; // could be the user who made the change...
117 //if (count($from) > 1) {
119 // array_shift($from);
120 // foreach ($from as $email) {
121 // $rep[] = make_email($email[0], $email[1]);
123 $headers['Reply-To'] = $ff->MTrack['email_address'];
129 * convert notification into an email..
131 * @param object $ticket the DataObject
132 * @param array $items the ids of the mtrack_change's
133 * @parem object $user DataObject of the user..
137 function notify_mtrack_ticket($ticket, $changes, $user)
141 // from is always the system.. ??
142 // unless all the changers are the same..
143 $headers = $this->calcAddress($changes, $user);
146 //$headers['To'] = '"'. addslashes($user->name). '" <' . $user->email .'>';
147 //$headers['From'] = make_email($from[0][0], $from[0][1]);
148 //if (count($from) > 1) {
150 // array_shift($from);
151 // foreach ($from as $email) {
152 // $rep[] = make_email($email[0], $email[1]);
154 //$headers['Reply-To'] = join(', ', $rep);
158 'MIME-Version' => '1.0',
159 'Content-Type' => 'text/plain; charset="UTF-8"',
160 'Content-Transfer-Encoding' => 'quoted-printable',
164 $mid = $ticket->id . '@' . php_uname('n');
170 // $headers['Message-ID'] = "<$mid>";
172 //$headers['Message-ID'] = "<$T->updated.$mid>";
173 //$headers['In-Reply-To'] = "<$mid>";
174 //$headers['References'] = "<$mid>";
176 /* find related project(s) */
177 $p = $ticket->project();
179 $subj = "[" . $p->code . ' - ' . $p->name . "] ";
181 $headers['X-mtrack-project-list'] = $p->code;
182 //foreach ($projects as $pname) {
183 // $headers["X-mtrack-project-$pname"] = $pname;
184 // $headers['X-mtrack-project'][] = $pname;
190 $headers['Subject'] = sprintf("%s#%s %s (%s %s)",
191 $subj, $ticket->id, $ticket->summary, $ticket->status_name, $ticket->classification_id_name);
193 $owner = strlen($ticket->owner) ? $ticket->owner_id_name : 'nobody';
196 sprintf("%s%s/Ticket.php/%s\n\n", $this->HTTP_HOST, $this->baseURL, $ticket->ident) .
197 sprintf("#%s: %s (%s %s)\n", $ticket->id, $ticket->summary, $ticket->status_name, $ticket->classification_id_name) .
198 sprintf("Responsible: %s (%s / %s)\n", $owner, $ticket->priority, $ticket->severity) .
200 //sprintf("Milestone: %s\n", join(', ', $T->getMilestones()));
201 //sprintf("Component: %s\n", join(', ', $T->getComponents()));
204 // Display changed fields grouped by the person that last changed them
205 //$who_changed = array();
206 //foreach ($field_changers as $field => $who) {
207 // $who_changed[$who][] = $field;
210 foreach ($changes as $change) {
212 $body .= "{$change->changedate}: Change by {$change->person_id_name}\n";
213 $body .= str_repeat('-', 80) . "\n";
214 if (!empty($change->reason)) {
215 $body.= $change->reason;
217 $ar = $change->cachedAudit();
218 foreach($ar as $audit) {
220 switch($audit->field()) {
222 continue; //??? ignore?
226 // foreach (preg_split("/\s*,\s*/", $old_values[$field]) as $id) {
227 /* if (!strlen($id)) continue;
228 $c = get_component($id);
229 $old[$id] = $c->name;
231 $value = $T->getComponents();
232 $field = 'Component';
238 // foreach (preg_split("/\s*,\s*/", $old_values[$field]) as $id) {
239 /* if (!strlen($id)) continue;
240 $m = get_milestone($id);
241 $old[$id] = $m->name;
244 $value = $T->getMilestones();
245 $field = 'Milestone';
253 $value = $T->getKeywords();
260 if (!strlen($audit->oldvalue)) {
261 $body .= "Set {$audit->field()} to: {$audit->value}\n";
264 if (!strlen($audit->value)) {
265 $body .= "Removed {$audit->field()} - was: {$audit->oldvalue}\n";
268 $body .= "Changed {$audit->field()} from :{$audit->oldvalue} -> {$audit->value}\n";
274 $body .= sprintf("%s%s/Ticket.php/%s\n\n", $this->HTTP_HOST, $this->baseURL, $ticket->id);
278 // send_mail($udata['email'], $plain);
284 class CanonicalLineEndingFilter extends php_user_filter {
285 function filter($in, $out, &$consumed, $closing)
287 while ($bucket = stream_bucket_make_writeable($in)) {
288 $bucket->data = preg_replace("/\r?\n/", "\r\n", $bucket->data);
289 $consumed += $bucket->datalen;
290 stream_bucket_append($out, $bucket);
295 class UnixLineEndingFilter extends php_user_filter {
296 function filter($in, $out, &$consumed, $closing)
298 while ($bucket = stream_bucket_make_writeable($in)) {
299 $bucket->data = preg_replace("/\r?\n/", "\n", $bucket->data);
300 $consumed += $bucket->datalen;
301 stream_bucket_append($out, $bucket);