]>
src.bluestatic.org Git - bugdar.git/blob - includes/class_notification.php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Bugdar [#]version[#]
5 || # Copyright ©2002-[#]year[#] Blue Static
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
25 * This class determines which emails need to be sent out based on user
26 * options and bug changes, and then it sends said emails.
29 * @copyright Copyright ©2002 - [#]year[#], Blue Static
34 class NotificationCenter
48 var $original = array ();
55 var $modified = array ();
58 * Global bugsys registry
65 * Role list: a list of user IDs with their relations to the bug
70 '-notapplicable-' => array (),
71 'reporter' => array (),
72 'assignee' => array (),
73 'favorite' => array (),
75 'commenter' => array ()
86 * A list of notices per-user that are combined together in NotificationCenter::finalize()
90 var $notices = array ();
92 // ###################################################################
94 * Constructor: set database objects
98 function __construct ()
102 $this- > registry
=& $bugsys ;
105 // ###################################################################
107 * (PHP 4) Constructor
111 function NotificationCenter ()
113 $this- > __construct ();
116 // ###################################################################
118 * Sets the bug data so that all methods in this class have access to
119 * it when sending emails.
123 * @param array Original bug data
124 * @param array Modified bug data
126 function set_bug_data ( $original , $modified = array ())
128 if ( sizeof ( $modified ) > 0 )
130 $this- > bug
= $modified ;
134 $this- > bug
= $original ;
137 $this- > original
= $original ;
138 $this- > modified
= $modified ;
140 $this- > roles
[ '-notapplicable-' ] = ( sizeof ( $modified ) > 0 ? array ( $original [ 'assignedto' ], $modified [ 'assignedto' ]) : array ( $original [ 'assignedto' ]));
141 $this- > roles
[ 'reporter' ] = array ( $original [ 'userid' ]);
142 $this- > roles
[ 'assignee' ] = ( sizeof ( $modified ) > 0 ? array ( $modified [ 'assignedto' ]) : array ( $original [ 'assignedto' ]));
144 $this- > fetch_user_cache ();
147 // ###################################################################
149 * Fetches all the users who could be related to the bug and sticks
150 * their information into an array.
154 function fetch_user_cache ()
156 // reset all the data each time we do this, just in case it changes within the lifespan of the object
157 $this- > users
= array ();
158 foreach ( $this- > roles
AS $role => $users )
160 $this- > roles
[ " $role" ] = array();
163 $newbuggers = $this- >registry->db->query(" SELECT userid FROM
" . TABLE_PREFIX . " useremail WHERE relation
= " . $this- >registry->emailoptions['relations']['-notapplicable-'] . " AND mask
& " . $this- >registry->emailoptions['notifications']['newbug']);
164 while ( $newbug = $this- >registry->db->fetch_array( $newbuggers ))
166 $this- >roles['-notapplicable-'][" $newbug [ userid
] "] = $newbug ['userid'];
169 $favorites = $this- >registry->db->query(" SELECT userid FROM
" . TABLE_PREFIX . " favorite WHERE bugid
= " . $this- >registry->clean( $this- >bug['bugid'], TYPE_UINT));
170 while ( $fav = $this- >registry->db->fetch_array( $favorites ))
172 $this- >roles['favorite'][" $fav [ userid
] "] = $fav ['userid'];
175 $voters = $this- >registry->db->query_first(" SELECT userids FROM
" . TABLE_PREFIX . " vote WHERE bugid
= " . $this- >registry->clean( $this- >bug['bugid'], TYPE_UINT));
176 $this- >roles['voter'] = preg_split('#,#', $voters ['userids'], 0, PREG_SPLIT_NO_EMPTY);
178 $commenters = $this- >registry->db->query(" SELECT userid FROM
" . TABLE_PREFIX . " comment WHERE bugid
= " . $this- >registry->clean( $this- >bug['bugid'], TYPE_UINT));
179 while ( $comment = $this- >registry->db->fetch_array( $commenters ))
181 $this- >roles['commenter'][" $comment [ userid
] "] = $comment ['userid'];
184 $masterids = array_merge( $this- >roles['-notapplicable-'], $this- >roles['reporter'], $this- >roles['assignee'], $this- >roles['favorite'], $this- >roles['voter'], $this- >roles['commenter']);
185 $masterids = $this- >registry->funct->array_strip_empty(array_unique( $masterids ));
187 if (is_array( $masterids ) AND sizeof( $masterids ) > 0)
189 $userinfo = $this- >registry->db->query("
190 SELECT user
.*, useremail
.*
191 FROM
" . TABLE_PREFIX . " useremail
AS useremail
192 LEFT JOIN
" . TABLE_PREFIX . " user
AS user
193 ON ( user
. userid
= useremail
. userid
)
194 WHERE useremail
. userid
IN ( " . implode(',', $masterids ) . " )
196 while ( $user = $this- >registry->db->fetch_array( $userinfo ))
198 if (!is_array( $this- >users[" $user [ userid
] "]))
200 $this- >users[" $user [ userid
] "] = $user ;
201 unset( $this- >users[" $user [ userid
] "]['mask'], $this- >users[" $user [ userid
] "]['relation']);
203 $this- >users[" $user [ userid
] "]['options'][" $user [ relation
] "] = $user ['mask'];
208 // ###################################################################
210 * Sends the appropriate emails for changes to bugs. This function
211 * works a lot like the Logging class by taking BugAPI->objdata and
212 * BugAPI->values and then comparing the two arries and sending emails
213 * with the differences.
217 function send_bug_changes_notice()
219 if (!isset( $this- >modified['bugid']))
224 // fields with custom mask information
225 if ( $this- >original['assignedto'] != $this- >modified['assignedto'])
227 if ( $this- >original['assignedto'] != '')
229 $this- >notice_no_longer_assigned( $this- >original['assignedto']);
231 if ( $this- >modified['assignedto'] != '')
233 $this- >notice_now_assigned( $this- >modified['assignedto']);
236 if ( $this- >original['status'] != $this- >modified['status'])
238 $this- >notice_status_change( $this- >original['status'], $this- >modified['status']);
240 if ( $this- >original['resolution'] != $this- >modified['resolution'])
242 $this- >notice_resolution_change( $this- >original['resolution'], $this- >modified['resolution']);
244 if ( $this- >original['duplicates'] != $this- >modified['duplicates'])
246 $this- >notice_duplicates_change( $this- >original['duplicates'], $this- >modified['duplicates']);
249 // other standard fields that don't have custom masks
250 if ( $this- >original['severity'] != $this- >modified['severity'])
252 $this- >notice_severity_change( $this- >original['severity'], $this- >modified['severity']);
254 if ( $this- >original['priority'] != $this- >modified['priority'])
256 $this- >notice_priority_change( $this- >original['priority'], $this- >modified['priority']);
258 if (( $this- >original['product'] != $this- >modified['product']) OR ( $this- >original['component'] != $this- >modified['component']) OR ( $this- >original['version'] != $this- >modified['version']))
260 $this- >notice_pcv_change(array( $this- >original['product'], $this- >original['component'], $this- >original['version']), array( $this- >modified['product'], $this- >modified['component'], $this- >modified['version']));
268 foreach ( $dofields AS $field => $lookup )
270 if ( $this- >original[" $field" ] != $this- > modified
[ " $field" ])
272 $this- >notice_other_change( $field , $this- >original[" $field" ], $this- > modified
[ " $field" ]);
277 // ###################################################################
279 * Sends an email to the specified user ID that they are no longer the
280 * person assigned to the bug.
284 * @param integer User ID to send to
286 function notice_no_longer_assigned( $userid )
288 if ( $this- >users[" $userid" ][ 'options' ][ 0 ] & $this- > registry
-> emailoptions
[ 'notifications' ][ 'assignedto' ] AND in_array ( $userid , $this- > roles
[ '-notapplicable-' ]))
290 $user = construct_user_display ( $this- > registry
-> userinfo
, false );
291 eval ( ' $part = "' . $this- > registry
-> template
-> fetch ( 'email/notice_unassigned.part' ) . '";' );
292 $this- > notices
[ " $userid" ][] = $part ;
296 // ###################################################################
298 * Informs the user that they have been made the assignee of the bug.
302 * @param integer User ID
304 function notice_now_assigned( $userid )
306 if ( $this- >users[" $userid" ][ 'options' ][ 0 ] & $this- > registry
-> emailoptions
[ 'notifications' ][ 'assignedto' ] AND in_array ( $userid , $this- > roles
[ '-notapplicable-' ]))
308 $user = construct_user_display ( $this- > registry
-> userinfo
, false );
309 eval ( ' $email = "' . $this- > registry
-> template
-> fetch ( 'email/notice_assigned.part' ) . '";' );
310 $this- > notices
[ " $userid" ][] = $email ;
314 // ###################################################################
316 * Sends a message to inform users that the status has changed.
320 * @param integer Old status
321 * @param integer New status
323 function notice_status_change( $old , $new )
325 $userlist = $this- >fetch_users_with_on_bit('statusresolve');
326 foreach ( $userlist AS $userid => $user )
328 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_status
. part
') . ' ";');
329 $this- >notices[" $user [ userid
] "][] = $email ;
333 // ###################################################################
335 * Sends an email to inform users that the resolution has changed.
339 * @param integer Old resolution
340 * @param integer New resolution
342 function notice_resolution_change( $old , $new )
344 $userlist = $this- >fetch_users_with_on_bit('statusresolve');
345 foreach ( $userlist AS $userid => $user )
347 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_resolution
. part
') . ' ";');
348 $this- >notices[" $user [ userid
] "][] = $email ;
352 // ###################################################################
354 * Informs users that the duplicates list has changed.
358 * @param string Old duplicates list
359 * @param string New duplicates list
361 function notice_duplicates_change( $old , $new )
363 $userlist = $this- >fetch_useres_with_on_bit('duplicates');
364 foreach ( $userlist AS $userid => $user )
366 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_duplicates
. part
') . ' ";');
367 $this- >notices[" $user [ userid
] "][] = $email ;
371 // ###################################################################
373 * Sends an email to inform users that the severity has changed.
377 * @param integer Old severity
378 * @param integer New severity
380 function notice_severity_change( $old , $new )
382 $userlist = $this- >fetch_users_with_on_bit('otherfield');
383 foreach ( $userlist AS $userid => $user )
385 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_severity
. part
') . ' ";');
386 $this- >notices[" $user [ userid
] "][] = $email ;
390 // ###################################################################
392 * Informs users that the priority changed.
396 * @param integer Old priority
397 * @param integer New priority
399 function notice_priority_change( $old , $new )
401 $userlist = $this- >fetch_users_with_on_bit('otherfield');
402 foreach ( $userlist AS $userid => $user )
404 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_priority
. part
') . ' ";');
405 $this- >notices[" $user [ userid
] "][] = $email ;
409 // ###################################################################
411 * Sends an email telling users that the product, component, or version
412 * has changed. This is done all at once because you really need to see
413 * the whole thing in the notice.
417 * @param array Original PCV
418 * @param array Modified PCV
420 function notice_pcv_change( $old , $new )
422 $userlist = $this- >fetch_users_with_on_bit('otherfield');
424 $old = $this- >registry->datastore['product'][" $old [ 0 ] "]['title'] . '/' . ( $old [1] ? $this- >registry->datastore['product'][" $old [ 1 ] "]['title'] . '/' : '') . $this- >registry->datastore['version'][" $old [ 2 ] "]['version'];
425 $new = $this- >registry->datastore['product'][" $new [ 0 ] "]['title'] . '/' . ( $new [1] ? $this- >registry->datastore['product'][" $new [ 1 ] "]['title'] . '/' : '') . $this- >registry->datastore['version'][" $new [ 2 ] "]['version'];
427 foreach ( $userlist AS $userid => $user )
429 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_product
. part
') . ' ";');
430 $this- >notices[" $user [ userid
] "][] = $email ;
434 // ###################################################################
436 * Sends the appropriate users information about a new comment being
437 * posted to the bug report.
441 * @param array CommentAPI->values array
443 function send_new_comment_notice( $comment )
445 $userlist = $this- >fetch_users_with_on_bit('newcomment');
446 foreach ( $userlist AS $userid => $user )
448 $user = construct_user_display( $this- >registry->userinfo, false);
449 $date = $this- >registry->modules['date']->format( $this- >registry->options['dateformat'], $comment ['dateline']);
451 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_comment
. part
') . ' ";');
452 $this- >notices[" $userid" ][] = $email ;
456 // ###################################################################
458 * A notice for an individual field changing.
462 * @param string Field name
463 * @param mixed Original value
464 * @param mixed Modified value
466 function notice_other_change ( $name , $old , $new )
468 $userlist = $this- > fetch_users_with_on_bit ( 'otherfield' );
469 foreach ( $userlist AS $userid => $user )
471 eval ( ' $email = "' . $this- > registry
-> template
-> fetch ( 'email/notice_other.part' ) . '";' );
472 $this- > notices
[ " $user [userid]" ][] = $email ;
476 // ###################################################################
478 * Sends appropriate users a notice when a new attachment has been
483 * @param array AttachmentAPI->values array
484 * @param array List of all attachments made obsolete
485 * @param array Newly-inserted attachment ID
487 function send_new_attachment_notice ( $attachment , $obsolete , $id )
489 $userlist = $this- > fetch_users_with_on_bit ( 'newattachment' );
490 foreach ( $userlist AS $userid => $user )
492 $user = construct_user_display ( $this- > registry
-> userinfo
, false );
493 $obsoletes = implode ( ', ' , ( array ) $obsolete );
495 eval ( ' $email = "' . $this- > registry
-> template
-> fetch ( 'email/notice_attachment.part' ) . '";' );
496 $this- > notices
[ " $userid" ][] = $email ;
500 // ###################################################################
502 * Sends a new bug notification notice to all those who have the option
503 * turned no. This does not use fetch_users_with_on_bit() because a
504 * query is more effective.
508 * @param array Bug values array
509 * @param array Comment values array
511 function send_new_bug_notice( $bug , $comment )
513 $userinfo = $this- >registry->db->query("
514 SELECT user
.*, useremail
.*
515 FROM
" . TABLE_PREFIX . " useremail
AS useremail
516 LEFT JOIN
" . TABLE_PREFIX . " user
AS user
517 ON ( user
. userid
= useremail
. userid
)
518 WHERE useremail
. relation
= 0
519 AND useremail
. mask
& " . $this- >registry->emailoptions['notifications']['newbug'] . "
521 while ( $userInfo = $this- >registry->db->fetch_array( $userinfo ))
523 if (!is_array( $this- >users[" $userInfo [ userid
] "]))
525 $user = construct_user_display( $this- >registry->userinfo, false);
526 $product = $this- >registry->datastore['product'][" $bug [ product
] "]['title'] . '/' . ( $bug ['component'] ? $this- >registry->datastore['product'][" $bug [ component
] "]['title'] . '/' : '') . $this- >registry->datastore['version'][" $bug [ version
] "]['version'];
527 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_new_bug
. part
') . ' ";');
528 $this- >notices[" $userInfo [ userid
] "][] = $email ;
529 $this- >users[" $userInfo [ userid
] "] = $userInfo ;
530 unset( $this- >users[" $userInfo [ userid
] "]['mask'], $this- >users[" $userInfo [ userid
] "]['relation']);
532 $this- >users[" $userInfo [ userid
] "]['options'][" $userInfo [ relation
] "] = $userInfo ['mask'];
536 // ###################################################################
538 * Generates an array of users who have a given email notification flag
539 * turned on in their bitfields.
543 * @param string Notification bitfield name
545 * @return array Array of users and their data
547 function fetch_users_with_on_bit( $bitname )
551 foreach ( $this- >users AS $user )
553 foreach ( $this- >registry->emailoptions['relations'] AS $name => $bit )
555 if (in_array( $user ['userid'], $this- >roles[" $name" ]) AND $user [ 'options' ][ " $bit" ] & $this- >registry->emailoptions['notifications'][" $bitname" ])
557 $idlist [] = $user [ 'userid' ];
562 $masters = array_unique ( $idlist );
565 foreach ( $masters AS $userid )
567 $return [ " $userid" ] =& $this- >users[" $userid" ];
573 // ###################################################################
575 * Compiles and sends the actual emails to users.
581 // get the current bug for permissions checks
582 $bug = $this- > registry
-> db
-> query_first ( "SELECT * FROM " . TABLE_PREFIX
. "bug WHERE bugid = " . $this- > bug
[ 'bugid' ]);
583 foreach ( $this- > notices
AS $userid => $noticelist )
585 if ( $userid == $this- > registry
-> userinfo
[ 'userid' ])
587 $this- > registry
-> debug ( "skipping user $userid because they're the one doing the thing" );
591 // we wouldn't want people who favorite bugs getting hidden notices
592 if (! check_bug_permissions ( $bug , $this- > users
[ " $userid" ]))
594 $this- >registry->debug(" skipping user
$userid ({ $this
-> users
[ $userid
][ 'email' ]}) because of permissions
");
598 $parts = implode(" \n\n
", $noticelist );
600 eval(' $email = " ' . $this- >registry->template->fetch(' email
/ bugnotification
. xml
') . ' ";');
601 $email = $this- >registry->xml->parse( $email );
602 $this- >registry->mail->setSubject( $email ['email']['subject']['value']);
603 $this- >registry->mail->setBodyText( $email ['email']['bodyText']['value']);
605 if (!empty( $this- >users[" $userid" ][ 'email' ]))
607 $this- > registry
-> mail
-> send ( $this- > users
[ " $userid" ]['email'], $this- >users[" $userid" ][ 'displayname' ]);
611 $this- > registry
-> debug ( "not sending an email to " . $userid . " because they don't have one?" );
617 /*=====================================================================*\
618 || ###################################################################
621 || ###################################################################
622 \*=====================================================================*/