]>
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 $this- > notices
[ " $userid" ][] = eval(' $part = " ' . $this- >registry->template->fetch(' email
/ notice_unassigned
. part
') . ' ";');
295 // ###################################################################
297 * Informs the user that they have been made the assignee of the bug.
301 * @param integer User ID
303 function notice_now_assigned( $userid )
305 if ( $this- >users[" $userid" ][ 'options' ][ 0 ] & $this- > registry
-> emailoptions
[ 'notifications' ][ 'assignedto' ] AND in_array ( $userid , $this- > roles
[ '-notapplicable-' ]))
307 $user = construct_user_display ( $this- > registry
-> userinfo
, false );
308 $this- > notices
[ " $userid" ][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_assigned
. part
') . ' ";');
312 // ###################################################################
314 * Sends a message to inform users that the status has changed.
318 * @param integer Old status
319 * @param integer New status
321 function notice_status_change( $old , $new )
323 $userlist = $this- >fetch_users_with_on_bit('statusresolve');
324 foreach ( $userlist AS $userid => $user )
326 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_status
. part
') . ' ";');
330 // ###################################################################
332 * Sends an email to inform users that the resolution has changed.
336 * @param integer Old resolution
337 * @param integer New resolution
339 function notice_resolution_change( $old , $new )
341 $userlist = $this- >fetch_users_with_on_bit('statusresolve');
342 foreach ( $userlist AS $userid => $user )
344 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_resolution
. part
') . ' ";');
348 // ###################################################################
350 * Informs users that the duplicates list has changed.
354 * @param string Old duplicates list
355 * @param string New duplicates list
357 function notice_duplicates_change( $old , $new )
359 $userlist = $this- >fetch_useres_with_on_bit('duplicates');
360 foreach ( $userlist AS $userid => $user )
362 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_duplicates
. part
') . ' ";');
366 // ###################################################################
368 * Sends an email to inform users that the severity has changed.
372 * @param integer Old severity
373 * @param integer New severity
375 function notice_severity_change( $old , $new )
377 $userlist = $this- >fetch_users_with_on_bit('otherfield');
378 foreach ( $userlist AS $userid => $user )
380 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_severity
. part
') . ' ";');
384 // ###################################################################
386 * Informs users that the priority changed.
390 * @param integer Old priority
391 * @param integer New priority
393 function notice_priority_change( $old , $new )
395 $userlist = $this- >fetch_users_with_on_bit('otherfield');
396 foreach ( $userlist AS $userid => $user )
398 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_priority
. part
') . ' ";');
402 // ###################################################################
404 * Sends an email telling users that the product, component, or version
405 * has changed. This is done all at once because you really need to see
406 * the whole thing in the notice.
410 * @param array Original PCV
411 * @param array Modified PCV
413 function notice_pcv_change( $old , $new )
415 $userlist = $this- >fetch_users_with_on_bit('otherfield');
417 $old = $this- >registry->datastore['product'][" $old [ 0 ] "]['title'] . '/' . ( $old [1] ? $this- >registry->datastore['product'][" $old [ 1 ] "]['title'] . '/' : '') . $this- >registry->datastore['version'][" $old [ 2 ] "]['version'];
418 $new = $this- >registry->datastore['product'][" $new [ 0 ] "]['title'] . '/' . ( $new [1] ? $this- >registry->datastore['product'][" $new [ 1 ] "]['title'] . '/' : '') . $this- >registry->datastore['version'][" $new [ 2 ] "]['version'];
420 foreach ( $userlist AS $userid => $user )
422 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_product
. part
') . ' ";');
426 // ###################################################################
428 * Sends the appropriate users information about a new comment being
429 * posted to the bug report.
433 * @param array CommentAPI->values array
435 function send_new_comment_notice( $comment )
437 $userlist = $this- >fetch_users_with_on_bit('newcomment');
438 foreach ( $userlist AS $userid => $user )
440 $user = construct_user_display( $this- >registry->userinfo, false);
441 $date = $this- >registry->modules['date']->format( $this- >registry->options['dateformat'], $comment ['dateline']);
443 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_comment
. part
') . ' ";');
447 // ###################################################################
449 * A notice for an individual field changing.
453 * @param string Field name
454 * @param mixed Original value
455 * @param mixed Modified value
457 function notice_other_change( $name , $old , $new )
459 $userlist = $this- >fetch_users_with_on_bit('otherfield');
460 foreach ( $userlist AS $userid => $user )
462 $this- >notices[" $user [ userid
] "][] = eval(' $email = " ' . $this- >registry->template->fetch(' email
/ notice_other
. part
') . ' ";');
466 // ###################################################################
468 * Sends appropriate users a notice when a new attachment has been
473 * @param array AttachmentAPI->values array
474 * @param array List of all attachments made obsolete
475 * @param array Newly-inserted attachment ID
477 function send_new_attachment_notice( $attachment , $obsolete , $id )
479 $userlist = $this- >fetch_users_with_on_bit('newattachment');
480 foreach ( $userlist AS $userid => $user )
482 $user = construct_user_display( $this- >registry->userinfo, false);
483 $obsoletes = implode(', ', (array) $obsolete );
485 $this- >notices[" $userid" ][] = eval ( ' $email = "' . $this- > registry
-> template
-> fetch ( 'email/notice_attachment.part' ) . '";' );
489 // ###################################################################
491 * Sends a new bug notification notice to all those who have the option
492 * turned no. This does not use fetch_users_with_on_bit() because a
493 * query is more effective.
497 * @param array Bug values array
498 * @param array Comment values array
500 function send_new_bug_notice ( $bug , $comment )
502 $userinfo = $this- > registry
-> db
-> query ( "
503 SELECT user.*, useremail.*
504 FROM " . TABLE_PREFIX
. "useremail AS useremail
505 LEFT JOIN " . TABLE_PREFIX
. "user AS user
506 ON (user.userid = useremail.userid)
507 WHERE useremail.relation = 0
508 AND useremail.mask & " . $this- > registry
-> emailoptions
[ 'notifications' ][ 'newbug' ] . "
510 while ( $user = $this- > registry
-> db
-> fetch_array ( $userinfo ))
512 if (! is_array ( $this- > users
[ " $user [userid]" ]))
514 $user = construct_user_display ( $this- > registry
-> userinfo
, false );
515 $product = $this- > registry
-> datastore
[ 'product' ][ " $bug [product]" ][ 'title' ] . '/' . ( $bug [ 'component' ] ? $this- > registry
-> datastore
[ 'product' ][ " $bug [component]" ][ 'title' ] . '/' : '' ) . $this- > registry
-> datastore
[ 'version' ][ " $bug [version]" ][ 'version' ];
516 $this- > notices
[ " $user [userid]" ][] = eval ( ' $email = "' . $this- > registry
-> template
-> fetch ( 'email/notice_new_bug.part' ) . '";' );
517 $this- > users
[ " $user [userid]" ] = $user ;
518 unset ( $this- > users
[ " $user [userid]" ][ 'mask' ], $this- > users
[ " $user [userid]" ][ 'relation' ]);
520 $this- > users
[ " $user [userid]" ][ 'options' ][ " $user [relation]" ] = $user [ 'mask' ];
524 // ###################################################################
526 * Generates an array of users who have a given email notification flag
527 * turned on in their bitfields.
531 * @param string Notification bitfield name
533 * @return array Array of users and their data
535 function fetch_users_with_on_bit ( $bitname )
539 foreach ( $this- > users
AS $user )
541 foreach ( $this- > registry
-> emailoptions
[ 'relations' ] AS $name => $bit )
543 if ( in_array ( $user [ 'userid' ], $this- > roles
[ " $name" ]) AND $user ['options'][" $bit" ] & $this- > registry
-> emailoptions
[ 'notifications' ][ " $bitname" ])
545 $idlist [] = $user ['userid'];
550 $masters = array_unique( $idlist );
553 foreach ( $masters AS $userid )
555 $return [" $userid" ] =& $this- > users
[ " $userid" ];
561 // ###################################################################
563 * Compiles and sends the actual emails to users.
569 // get the current bug for permissions checks
570 $bug = $this- >registry->db->query_first(" SELECT
* FROM
" . TABLE_PREFIX . " bug WHERE bugid
= " . $this- >bug['bugid']);
571 foreach ( $this- >notices AS $userid => $noticelist )
573 if ( $userid == $this- >registry->userinfo['userid'])
578 // we wouldn't want people who favorite bugs getting hidden notices
579 if (!check_bug_permissions( $bug , $this- >users[" $userid" ]))
581 $this- > registry
-> debug ( "skipping user $userid ( {$this->users[$userid]['email']} ) because of permissions" );
585 $parts = implode ( " \n\n " , $noticelist );
587 eval ( ' $email = "' . $this- > registry
-> template
-> fetch ( 'email/bugnotification.xml' ) . '";' );
588 $email = $this- > registry
-> xml
-> parse ( $email );
589 $this- > registry
-> mail
-> setSubject ( $email [ 'email' ][ 'subject' ][ 'value' ]);
590 $this- > registry
-> mail
-> setBodyText ( $email [ 'email' ][ 'bodyText' ][ 'value' ]);
592 if (! empty ( $this- > users
[ " $userid" ]['email']))
594 $this- >registry->mail->send( $this- >users[" $userid" ][ 'email' ], $this- > users
[ " $userid" ]['displayname']);
598 $this- >registry->debug(" not sending an email to
" . $userid . " because they don
't have one?");
604 /*=====================================================================*\
605 || ###################################################################
608 || ###################################################################
609 \*=====================================================================*/