Index: trunk/extensions/CodeReview/CodeRevision.php |
— | — | @@ -4,7 +4,7 @@ |
5 | 5 | class CodeRevision { |
6 | 6 | static function newFromSvn( CodeRepository $repo, $data ) { |
7 | 7 | $rev = new CodeRevision(); |
8 | | - $rev->mRepo = $repo->getId(); |
| 8 | + $rev->mRepo = CodeRepository::newFromId( $repo->getId() ); |
9 | 9 | $rev->mId = intval($data['rev']); |
10 | 10 | $rev->mAuthor = $data['author']; |
11 | 11 | $rev->mTimestamp = wfTimestamp( TS_MW, strtotime( $data['date'] ) ); |
— | — | @@ -45,7 +45,7 @@ |
46 | 46 | |
47 | 47 | static function newFromRow( $row ) { |
48 | 48 | $rev = new CodeRevision(); |
49 | | - $rev->mRepo = intval($row->cr_repo_id); |
| 49 | + $rev->mRepo = CodeRepository::newFromId( intval($row->cr_repo_id) ); |
50 | 50 | $rev->mId = intval($row->cr_id); |
51 | 51 | $rev->mAuthor = $row->cr_author; |
52 | 52 | $rev->mTimestamp = wfTimestamp( TS_MW, $row->cr_timestamp ); |
— | — | @@ -62,6 +62,14 @@ |
63 | 63 | function getAuthor() { |
64 | 64 | return $this->mAuthor; |
65 | 65 | } |
| 66 | + |
| 67 | + function getRepo() { |
| 68 | + return $this->mRepo; |
| 69 | + } |
| 70 | + |
| 71 | + function getWikiUser() { |
| 72 | + return $this->mRepo->authorWikiUser( $this->getAuthor() ); |
| 73 | + } |
66 | 74 | |
67 | 75 | function getTimestamp() { |
68 | 76 | return $this->mTimestamp; |
— | — | @@ -98,7 +106,7 @@ |
99 | 107 | $dbw->update( 'code_rev', |
100 | 108 | array( 'cr_status' => $status ), |
101 | 109 | array( |
102 | | - 'cr_repo_id' => $this->mRepo, |
| 110 | + 'cr_repo_id' => $this->mRepo->getId(), |
103 | 111 | 'cr_id' => $this->mId ), |
104 | 112 | __METHOD__ ); |
105 | 113 | } |
— | — | @@ -109,7 +117,7 @@ |
110 | 118 | |
111 | 119 | $dbw->insert( 'code_rev', |
112 | 120 | array( |
113 | | - 'cr_repo_id' => $this->mRepo, |
| 121 | + 'cr_repo_id' => $this->mRepo->getId(), |
114 | 122 | 'cr_id' => $this->mId, |
115 | 123 | 'cr_author' => $this->mAuthor, |
116 | 124 | 'cr_timestamp' => $dbw->timestamp( $this->mTimestamp ), |
— | — | @@ -127,16 +135,16 @@ |
128 | 136 | 'cr_message' => $this->mMessage, |
129 | 137 | 'cr_path' => $this->mCommonPath ), |
130 | 138 | array( |
131 | | - 'cr_repo_id' => $this->mRepo, |
| 139 | + 'cr_repo_id' => $this->mRepo->getId(), |
132 | 140 | 'cr_id' => $this->mId ), |
133 | 141 | __METHOD__ ); |
134 | 142 | } |
135 | | - |
| 143 | + // Update path tracking used for output and searching |
136 | 144 | if( $this->mPaths ) { |
137 | 145 | $data = array(); |
138 | 146 | foreach( $this->mPaths as $path ) { |
139 | 147 | $data[] = array( |
140 | | - 'cp_repo_id' => $this->mRepo, |
| 148 | + 'cp_repo_id' => $this->mRepo->getId(), |
141 | 149 | 'cp_rev_id' => $this->mId, |
142 | 150 | 'cp_path' => $path['path'], |
143 | 151 | 'cp_action' => $path['action'] ); |
— | — | @@ -155,7 +163,8 @@ |
156 | 164 | return $dbr->select( |
157 | 165 | 'code_paths', |
158 | 166 | array( 'cp_path', 'cp_action' ), |
159 | | - array( 'cp_repo_id' => $this->mRepo, 'cp_rev_id' => $this->mId ), |
| 167 | + array( 'cp_repo_id' => $this->mRepo->getId(), |
| 168 | + 'cp_rev_id' => $this->mId ), |
160 | 169 | __METHOD__ |
161 | 170 | ); |
162 | 171 | } |
— | — | @@ -175,17 +184,47 @@ |
176 | 185 | } |
177 | 186 | |
178 | 187 | function saveComment( $text, $review, $parent=null ) { |
| 188 | + global $wgUser; |
179 | 189 | if( !strlen($text) ) { |
180 | 190 | return 0; |
181 | 191 | } |
182 | 192 | $dbw = wfGetDB( DB_MASTER ); |
183 | 193 | $data = $this->commentData( $text, $review, $parent ); |
| 194 | + |
| 195 | + $dbw->begin(); |
184 | 196 | $data['cc_id'] = $dbw->nextSequenceValue( 'code_comment_cc_id' ); |
185 | | - $dbw->insert( 'code_comment', |
186 | | - $data, |
187 | | - __METHOD__ ); |
| 197 | + $dbw->insert( 'code_comment', $data, __METHOD__ ); |
| 198 | + $commentId = $dbw->insertId(); |
| 199 | + $dbw->commit(); |
| 200 | + |
| 201 | + // Give email notices to committer and commentors |
| 202 | + global $wgCodeReviewENotif, $wgEnableEmail; |
| 203 | + if( $wgCodeReviewENotif && $wgEnableEmail ) { |
| 204 | + // Make list of users to send emails to |
| 205 | + $users = $this->getCommentingUsers(); |
| 206 | + if( $user = $this->getWikiUser() ) { |
| 207 | + $users[$user->getId()] = $user; |
| 208 | + } |
| 209 | + // Get repo and build comment title (for url) |
| 210 | + $title = SpecialPage::getTitleFor( 'Code', $this->mRepo->getName().'/'.$this->mId ); |
| 211 | + $title->setFragment( "#c{$commentId}" ); |
| 212 | + $url = $title->getFullUrl(); |
| 213 | + $preview = htmlspecialchars($text); |
| 214 | + foreach( $users as $userId => $user ) { |
| 215 | + // No sense in notifying this commentor |
| 216 | + if( $wgUser->getId() == $user->getId() ) { |
| 217 | + continue; |
| 218 | + } |
| 219 | + if( $user->canReceiveEmail() ) { |
| 220 | + $user->sendMail( |
| 221 | + wfMsg( 'codereview-email-subj', $repo->getName(), $this->mId ), |
| 222 | + wfMsg( 'codereview-email-body', $wgUser->getName(), $url, $this->mId, $preview ) |
| 223 | + ); |
| 224 | + } |
| 225 | + } |
| 226 | + } |
188 | 227 | |
189 | | - return $dbw->insertId(); |
| 228 | + return $commentId; |
190 | 229 | } |
191 | 230 | |
192 | 231 | protected function commentData( $text, $review, $parent=null ) { |
— | — | @@ -194,7 +233,7 @@ |
195 | 234 | $ts = wfTimestamp( TS_MW ); |
196 | 235 | $sortkey = $this->threadedSortkey( $parent, $ts ); |
197 | 236 | return array( |
198 | | - 'cc_repo_id' => $this->mRepo, |
| 237 | + 'cc_repo_id' => $this->mRepo->getId(), |
199 | 238 | 'cc_rev_id' => $this->mId, |
200 | 239 | 'cc_text' => $text, |
201 | 240 | 'cc_parent' => $parent, |
— | — | @@ -238,7 +277,7 @@ |
239 | 278 | 'cc_review', |
240 | 279 | 'cc_sortkey' ), |
241 | 280 | array( |
242 | | - 'cc_repo_id' => $this->mRepo, |
| 281 | + 'cc_repo_id' => $this->mRepo->getId(), |
243 | 282 | 'cc_rev_id' => $this->mId ), |
244 | 283 | __METHOD__, |
245 | 284 | array( |
— | — | @@ -252,12 +291,30 @@ |
253 | 292 | return $comments; |
254 | 293 | } |
255 | 294 | |
| 295 | + function getCommentingUsers() { |
| 296 | + $dbr = wfGetDB( DB_SLAVE ); |
| 297 | + $res = $dbr->select( 'code_comment', |
| 298 | + 'DISTINCT(cc_user)', |
| 299 | + array( |
| 300 | + 'cc_repo_id' => $this->mRepo->getId(), |
| 301 | + 'cc_rev_id' => $this->mId, |
| 302 | + 'cc_user != 0' // users only |
| 303 | + ), |
| 304 | + __METHOD__ |
| 305 | + ); |
| 306 | + $users = array(); |
| 307 | + while( $row = $res->fetchObject() ) { |
| 308 | + $users[$row->cc_user] = User::newFromId( $row->cc_user ); |
| 309 | + } |
| 310 | + return $users; |
| 311 | + } |
| 312 | + |
256 | 313 | function getTags() { |
257 | 314 | $dbr = wfGetDB( DB_SLAVE ); |
258 | 315 | $result = $dbr->select( 'code_tags', |
259 | 316 | array( 'ct_tag' ), |
260 | 317 | array( |
261 | | - 'ct_repo_id' => $this->mRepo, |
| 318 | + 'ct_repo_id' => $this->mRepo->getId(), |
262 | 319 | 'ct_rev_id' => $this->mId ), |
263 | 320 | __METHOD__ ); |
264 | 321 | |
— | — | @@ -284,7 +341,7 @@ |
285 | 342 | } |
286 | 343 | $result = $dbw->delete( 'code_tags', |
287 | 344 | array( |
288 | | - 'ct_repo_id' => $this->mRepo, |
| 345 | + 'ct_repo_id' => $this->mRepo->getId(), |
289 | 346 | 'ct_rev_id' => $this->mId, |
290 | 347 | 'ct_tag' => $tagsNormal ), |
291 | 348 | __METHOD__ ); |
— | — | @@ -294,7 +351,7 @@ |
295 | 352 | $data = array(); |
296 | 353 | foreach( $tags as $tag ) { |
297 | 354 | $data[] = array( |
298 | | - 'ct_repo_id' => $this->mRepo, |
| 355 | + 'ct_repo_id' => $this->mRepo->getId(), |
299 | 356 | 'ct_rev_id' => $this->mId, |
300 | 357 | 'ct_tag' => $this->normalizeTag( $tag ) ); |
301 | 358 | } |
— | — | @@ -332,7 +389,7 @@ |
333 | 390 | $row = $dbr->selectRow( 'code_rev', |
334 | 391 | 'cr_id', |
335 | 392 | array( |
336 | | - 'cr_repo_id' => $this->mRepo, |
| 393 | + 'cr_repo_id' => $this->mRepo->getId(), |
337 | 394 | "cr_id > $encId" ), |
338 | 395 | __METHOD__, |
339 | 396 | array( |
— | — | @@ -352,7 +409,7 @@ |
353 | 410 | $row = $dbr->selectRow( 'code_rev', |
354 | 411 | 'cr_id', |
355 | 412 | array( |
356 | | - 'cr_repo_id' => $this->mRepo, |
| 413 | + 'cr_repo_id' => $this->mRepo->getId(), |
357 | 414 | "cr_id > $encId", |
358 | 415 | 'cr_status' => array('new','fixme') ), |
359 | 416 | __METHOD__, |
Index: trunk/extensions/CodeReview/CodeReview.php |
— | — | @@ -99,3 +99,4 @@ |
100 | 100 | // The name of a repo which represents the code running on this wiki, used to highlight active revisions |
101 | 101 | $wgWikiSVN = 'MediaWiki'; |
102 | 102 | |
| 103 | +$wgCodeReviewENotif = true; |
Index: trunk/extensions/CodeReview/CodeReview.i18n.php |
— | — | @@ -74,6 +74,11 @@ |
75 | 75 | 'code-rev-submit-next' => 'Commit & next unresolved', |
76 | 76 | |
77 | 77 | 'codereview-reply-link' => 'reply', |
| 78 | + |
| 79 | + 'codereview-email-subj' => '[$1] [r$2]: New comment added', |
| 80 | + 'codereview-email-body' => 'User <b>$1</b> posted the <a href="$2">following comment</a> on r$3: |
| 81 | + |
| 82 | +$4', |
78 | 83 | |
79 | 84 | 'repoadmin' => 'Repository Administration', |
80 | 85 | 'repoadmin-new-legend' => 'Create a new repository', |