MTrackWeb/Cron/Notify.php
[web.mtrack] / MTrackWeb / Cron / Notify.php
1 <?php
2 require_once 'MTrackWeb.php';
3
4 class MTrackWeb_Cron_Notify extends MTrackWeb
5 {
6     
7     function getAuth()
8     {
9         $ff = HTML_FlexyFramework::get();
10         if (!$ff->cli) {
11             die("access denied");
12         }
13         HTML_FlexyFramework::ensureSingle(__FILE__, $this);
14         return true;
15         
16     }
17     
18     function get()    
19     {
20         //DB_DataObject::debugLevel(1);
21         date_default_timezone_set('UTC');
22         
23         // what's the baserul..
24     
25         
26         $MAX_DIFF = 200 * 1024;
27         $USE_BATCHING = false;
28         
29          
30         $e= DB_DataObject::factory('Events');
31         $e->action = 'MTRACK.NOTIFY';
32         $e->selectAdd();
33         $e->selectAdd('MAX(event_when) as event_when');
34         
35         if (!$e->find(true)) {
36             $e->event_when = date('Y-m-d H:i:s', 0); // should be a long time ago..
37         }
38          
39         
40         
41         stream_filter_register("mtrackcanonical", 'CanonicalLineEndingFilter');
42         stream_filter_register("mtrackunix", 'UnixLineEndingFilter');
43         
44         $w = DB_DataObject::factory('core_watch');
45         // returns a list of user with the objects they are watching..
46         $watches = $w->watched('email');
47         
48         $CS = DB_DataObject::factory('mtrack_change');
49         
50         $messages = array();
51         $cache = array();
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.
57             
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]);
62                 $o->autoJoin();
63                 $o->get($lr[1]);
64                 if (!isset($cache[implode(',', $ar)])) {
65                     $cs = clone($CS);
66                     $cs->whereAddIn('mtrack_change.id', $ar, 'int');
67                     $cs->autoJoin();
68                     $cache[implode(',', $ar)] = $cs->fetchAll();
69                 }
70                 $u  = DB_DataObject::factory('Person');
71                 $u->get($uid);
72                 $method =  'notify_'. $lr[0] ;
73                 if (method_exists($this,$method)) {
74                     $this->$method($o,  $cache[implode(',', $ar)], $u);
75                 }
76             }
77             
78             
79             
80             
81             
82             
83             
84         }
85        // print_R($messages);
86         die("done");
87         
88         
89         
90         
91          
92         /* For each watcher, compute the changes.
93          * Group changes by ticket, sending one email per ticket.
94          * Group tickets into batch updates if the only fields that changed are
95          * bulk update style (milestone, assignment etc.)
96          *
97          * For the wiki repo, group by file so that serial edits within the batch
98          * period show up as a single email.
99          */
100          
101     }
102     
103     
104     /**
105      * sets:
106      *   - from (system or a specific user.)
107      *   - replyto (system)
108      *   - to user...
109      *   
110      */
111     function calcAddress($changes, $user) {
112         $ff = HTML_FlexyFramework::get();
113      
114         
115         $headers['To'] = '"'. addslashes($user->name). '" <' . $user->email .'>';
116         $headers['From'] = $ff->MTrackWeb['email_address']; // could be the user who made the change...
117         
118         //if (count($from) > 1) {
119         //    $rep = array();
120         //    array_shift($from);
121          //       foreach ($from as $email) {
122          // $rep[] = make_email($email[0], $email[1]);
123         // }
124         
125         $headers['Reply-To'] =  $ff->MTrackWeb['email_address'];
126         //}
127         return $headers;
128     }
129     
130     /**
131      * convert notification into an email..
132      *
133      * @param object $ticket the DataObject
134      * @param array $items the ids of the mtrack_change's
135      * @parem object $user DataObject of the user..
136      * 
137      */
138     
139     function notify_mtrack_ticket($ticket, $changes, $user)
140     {
141         //global $MAX_DIFF;
142         $ff = HTML_FlexyFramework::get();
143      
144         // from is always the system.. ??
145         // unless all the changers are the same..
146         $headers = $this->calcAddress($changes, $user);
147         
148           
149         //$headers['To'] = '"'. addslashes($user->name). '" <' . $user->email .'>';
150         //$headers['From'] = make_email($from[0][0], $from[0][1]);
151         //if (count($from) > 1) {
152         //    $rep = array();
153         //    array_shift($from);
154          //       foreach ($from as $email) {
155          // $rep[] = make_email($email[0], $email[1]);
156         // }
157         //$headers['Reply-To'] = join(', ', $rep);
158         //}
159      
160         $headers += array(
161             'MIME-Version' => '1.0',
162             'Content-Type' => 'text/plain; charset="UTF-8"',
163             'Content-Transfer-Encoding' => 'quoted-printable',
164         );
165     
166         
167         $mid = $ticket->id . '@' . php_uname('n');
168         
169         
170         
171         
172         //if ($is_initial) {
173         //    $headers['Message-ID'] = "<$mid>";
174         //} else {
175         //$headers['Message-ID'] = "<$T->updated.$mid>";
176         //$headers['In-Reply-To'] = "<$mid>";
177         //$headers['References'] = "<$mid>";
178         //}
179       /* find related project(s) */
180         $p = $ticket->project();
181          
182         $subj = "[" . $p->code . ' - ' . $p->name . "] ";
183     
184         $headers['X-mtrack-project-list'] = $p->code;
185         //foreach ($projects as $pname) {
186         //  $headers["X-mtrack-project-$pname"] = $pname;
187          // $headers['X-mtrack-project'][] = $pname;
188         //}
189         //} else {
190         //$subj = '';
191         // }
192     
193         $headers['Subject'] = sprintf("%s#%s %s (%s %s)",
194           $subj, $ticket->id, $ticket->summary, $ticket->status_name, $ticket->classification_id_name);
195     
196         $owner = strlen($ticket->owner_id) ? $ticket->owner_id_name : 'nobody';
197     
198         $body = 
199             sprintf("%s/Ticket.php/%s\n\n", $ff->MTrackWeb['url'], $ticket->id) .
200             sprintf("#%s: %s (%s %s)\n", $ticket->id, $ticket->summary, $ticket->status_name, $ticket->classification_id_name) .
201             sprintf("Responsible: %s (%s / %s)\n", $owner, $ticket->priority_id_name, $ticket->severity_id_name) .
202     
203             //sprintf("Milestone: %s\n", join(', ', $T->getMilestones()));
204             //sprintf("Component: %s\n", join(', ', $T->getComponents()));
205             "\n";
206     
207       // Display changed fields grouped by the person that last changed them
208         //$who_changed = array();
209         //foreach ($field_changers as $field => $who) {
210         //  $who_changed[$who][] = $field;
211         //}
212         $body.="\n\n";
213         foreach ($changes as $change) {
214             
215             $body .= "{$change->changedate}:  Change by {$change->person_id_name}\n";
216             $body .= str_repeat('-', 80) . "\n";
217             if (!empty($change->reason)) {
218                 $body.= $change->reason;
219             }
220             $ar = $change->cachedAudit();
221             foreach($ar as $audit) {
222                 
223                 switch($audit->field()) {
224                     case 'id':
225                         continue; //??? ignore?
226                     case '@components':
227                         continue;
228                     //  $old = array();
229                     //  foreach (preg_split("/\s*,\s*/", $old_values[$field]) as $id) {
230                      /*   if (!strlen($id)) continue;
231                         $c = get_component($id);
232                         $old[$id] = $c->name;
233                       }
234                       $value = $T->getComponents();
235                       $field = 'Component';
236                       break;
237                      */
238                     case '@milestones':
239                         continue;
240                     //  $old = array();
241                     //  foreach (preg_split("/\s*,\s*/", $old_values[$field]) as $id) {
242                       /*  if (!strlen($id)) continue;
243                         $m = get_milestone($id);
244                         $old[$id] = $m->name;
245                       }
246                       $value = array();
247                       $value = $T->getMilestones();
248                       $field = 'Milestone';
249                       break;
250                       */
251                     case '@keywords':
252                         continue;
253                     /*
254                       $old = array();
255                       $field = 'Keywords';
256                       $value = $T->getKeywords();
257                       break;
258                       */
259                       
260                     //case 'commit?'  
261                       
262                     default:
263                         if (!strlen($audit->oldvalue)) {
264                             $body .= "Set {$audit->field()} to: {$audit->value}\n";
265                             continue;
266                         }
267                         if (!strlen($audit->value)) {
268                             $body .= "Removed {$audit->field()} - was: {$audit->oldvalue}\n";
269                             continue;
270                         }
271                         $body .= "Changed {$audit->field()} from :{$audit->oldvalue} -> {$audit->value}\n";
272                         continue;  
273                 }
274             }
275         }
276         
277         $body .= sprintf("%s/Ticket.php/%s\n\n", $ff->MTrackWeb['url'], $ticket->id);
278         
279         echo $body;   
280     
281         //  send_mail($udata['email'], $plain);
282     }
283     
284 }
285
286
287 class CanonicalLineEndingFilter extends php_user_filter {
288     function filter($in, $out, &$consumed, $closing)
289     {
290       while ($bucket = stream_bucket_make_writeable($in)) {
291         $bucket->data = preg_replace("/\r?\n/", "\r\n", $bucket->data);
292         $consumed += $bucket->datalen;
293         stream_bucket_append($out, $bucket);
294       }
295       return PSFS_PASS_ON;
296     }
297     }
298     class UnixLineEndingFilter extends php_user_filter {
299     function filter($in, $out, &$consumed, $closing)
300     {
301       while ($bucket = stream_bucket_make_writeable($in)) {
302         $bucket->data = preg_replace("/\r?\n/", "\n", $bucket->data);
303         $consumed += $bucket->datalen;
304         stream_bucket_append($out, $bucket);
305       }
306       return PSFS_PASS_ON;
307     }
308     }