Index: trunk/extensions/CodeReview/CodeRevision.php |
— | — | @@ -76,4 +76,70 @@ |
77 | 77 | __METHOD__ |
78 | 78 | ); |
79 | 79 | } |
| 80 | + |
| 81 | + function saveComment( $text, $review, $parent=null ) { |
| 82 | + global $wgUser; |
| 83 | + $ts = wfTimestamp( TS_MW ); |
| 84 | + $sortkey = $this->threadedSortkey( $parent, $ts ); |
| 85 | + |
| 86 | + $dbw = wfGetDB( DB_SLAVE ); |
| 87 | + $dbw->insert( 'code_comment', |
| 88 | + array( |
| 89 | + 'cc_repo_id' => $this->mRepo, |
| 90 | + 'cc_rev_id' => $this->mId, |
| 91 | + 'cc_text' => $text, |
| 92 | + 'cc_parent' => $parent, |
| 93 | + 'cc_user' => $wgUser->getId(), |
| 94 | + 'cc_user_text' => $wgUser->getName(), |
| 95 | + 'cc_timestamp' => $dbw->timestamp( $ts ), |
| 96 | + 'cc_review' => $review, |
| 97 | + 'cc_sortkey' => $sortkey ), |
| 98 | + __METHOD__ ); |
| 99 | + } |
| 100 | + |
| 101 | + protected function threadedSortKey( $parent, $ts ) { |
| 102 | + if( $parent ) { |
| 103 | + // We construct a threaded sort key by concatenating the timestamps |
| 104 | + // of all our parent comments |
| 105 | + $dbw = wfGetDB( DB_SLAVE ); |
| 106 | + $parentKey = $dbw->selectRow( 'code_comment', |
| 107 | + array( 'cc_sortkey' ), |
| 108 | + array( 'cc_id' => $parent ), |
| 109 | + __METHOD__ ); |
| 110 | + if( $parentKey ) { |
| 111 | + return $parentKey . ',' . $ts; |
| 112 | + } else { |
| 113 | + // hmmmm |
| 114 | + throw new MWException( 'Invalid parent submission' ); |
| 115 | + } |
| 116 | + } else { |
| 117 | + return $ts; |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + function getComments() { |
| 122 | + $dbr = wfGetDB( DB_SLAVE ); |
| 123 | + $result = $dbr->select( 'code_comment', |
| 124 | + array( |
| 125 | + 'cc_id', |
| 126 | + 'cc_text', |
| 127 | + 'cc_parent', |
| 128 | + 'cc_user', |
| 129 | + 'cc_user_text', |
| 130 | + 'cc_timestamp', |
| 131 | + 'cc_review' ), |
| 132 | + array( |
| 133 | + 'cc_repo_id' => $this->mRepo, |
| 134 | + 'cc_rev_id' => $this->mId ), |
| 135 | + __METHOD__, |
| 136 | + array( |
| 137 | + 'ORDER BY' => 'cc_sortkey' ) ); |
| 138 | + |
| 139 | + $comments = array(); |
| 140 | + foreach( $result as $row ) { |
| 141 | + $comments[] = new CodeComment( $this, $row ); |
| 142 | + } |
| 143 | + $result->free(); |
| 144 | + return $comments; |
| 145 | + } |
80 | 146 | } |
Index: trunk/extensions/CodeReview/SpecialCode.php |
— | — | @@ -7,11 +7,12 @@ |
8 | 8 | } |
9 | 9 | |
10 | 10 | function execute( $subpage ) { |
11 | | - global $wgOut, $wgRequest, $wgUser; |
| 11 | + global $wgOut, $wgRequest, $wgUser, $wgScriptPath; |
12 | 12 | |
13 | 13 | wfLoadExtensionMessages( 'CodeReview' ); |
14 | 14 | |
15 | 15 | $this->setHeaders(); |
| 16 | + $wgOut->addStyle( "$wgScriptPath/extensions/CodeReview/codereview.css" ); |
16 | 17 | |
17 | 18 | if( $subpage == '' ) { |
18 | 19 | $view = new CodeRepoListView(); |
— | — | @@ -214,6 +215,9 @@ |
215 | 216 | $view->execute(); |
216 | 217 | return; |
217 | 218 | } |
| 219 | + |
| 220 | + $this->checkPostings(); |
| 221 | + |
218 | 222 | $repoLink = $wgUser->getSkin()->link( SpecialPage::getTitleFor( 'Code', $this->mRepo->getName() ), |
219 | 223 | htmlspecialchars( $this->mRepo->getName() ) ); |
220 | 224 | $rev = $this->mRev->getId(); |
— | — | @@ -240,12 +244,35 @@ |
241 | 245 | <tr><td valign="top">' . wfMsgHtml( 'code-rev-paths' ) . '</td><td valign="top">' . $paths . '</td></tr> |
242 | 246 | </table>'; |
243 | 247 | $html .= |
| 248 | + "<h2>Diff</h2>" . |
244 | 249 | "<div class='mw-codereview-diff'>" . |
245 | 250 | $this->formatDiff() . |
246 | 251 | "</div>"; |
| 252 | + |
| 253 | + $html .= |
| 254 | + "<h2>Comments</h2>" . |
| 255 | + $this->formatComments(); |
247 | 256 | $wgOut->addHtml( $html ); |
248 | 257 | } |
249 | 258 | |
| 259 | + function checkPostings() { |
| 260 | + global $wgRequest, $wgUser; |
| 261 | + if( $wgRequest->wasPosted() |
| 262 | + && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) { |
| 263 | + // Look for a posting... |
| 264 | + $text = $wgRequest->getText( 'wpTextbox1' ); |
| 265 | + $parent = $wgRequest->getIntOrNull( 'wpParent' ); |
| 266 | + $review = $wgRequest->getInt( 'wpReview' ); |
| 267 | + $isPreview = $wgRequest->getCheck( 'wpCommentPreview' ); |
| 268 | + if( $isPreview ) { |
| 269 | + // NYI |
| 270 | + } else { |
| 271 | + $this->mRev->saveComment( $text, $review, $parent ); |
| 272 | + // fixme -- won't show up in slave load |
| 273 | + } |
| 274 | + } |
| 275 | + } |
| 276 | + |
250 | 277 | function formatPathLine( $path, $action ) { |
251 | 278 | $desc = wfMsgHtml( 'code-rev-modified-'.strtolower( $action ) ); |
252 | 279 | $encPath = htmlspecialchars( $path ); |
— | — | @@ -266,4 +293,53 @@ |
267 | 294 | $diff = $this->mRepo->getDiff( $this->mRev->getId() ); |
268 | 295 | return "<pre>" . htmlspecialchars( $diff ) . "</pre>"; |
269 | 296 | } |
270 | | -} |
| 297 | + |
| 298 | + function formatComments() { |
| 299 | + return "<div class='mw-codereview-comments'>" . |
| 300 | + implode( "\n", |
| 301 | + array_map( |
| 302 | + array( $this, 'formatComment' ), |
| 303 | + $this->mRev->getComments() ) ) . |
| 304 | + $this->postCommentForm() . |
| 305 | + "</div>"; |
| 306 | + } |
| 307 | + |
| 308 | + function formatComment( $comment ) { |
| 309 | + global $wgOut, $wgLang; |
| 310 | + return '<div class="mw-codereview-comment">' . |
| 311 | + '<div class="mw-codereview-comment-meta">' . |
| 312 | + 'Comment by ' . |
| 313 | + $this->mSkin->userLink( $comment->user, $comment->userText ) . |
| 314 | + $this->mSkin->userToolLinks( $comment->user, $comment->userText ) . |
| 315 | + ' ' . |
| 316 | + $wgLang->timeanddate( $comment->timestamp ) . |
| 317 | + '</div>' . |
| 318 | + '<div class="mw-codereview-comment-text">' . |
| 319 | + $wgOut->parse( $comment->text ) . |
| 320 | + '</div>' . |
| 321 | + '</div>'; |
| 322 | + } |
| 323 | + |
| 324 | + function postCommentForm( $parent=null ) { |
| 325 | + global $wgUser; |
| 326 | + return '<div class="mw-codereview-post-comment">' . |
| 327 | + Xml::openElement( 'form', |
| 328 | + array( |
| 329 | + 'action' => '', // fixme |
| 330 | + 'method' => 'post' ) ) . |
| 331 | + Xml::hidden( 'wpEditToken', $wgUser->editToken() ) . |
| 332 | + Xml::hidden( 'wpCodeRepo', $this->mRepo->getName() ) . |
| 333 | + Xml::hidden( 'wpCodeRev', $this->mRev->getId() ) . |
| 334 | + ($parent ? Xml::hidden( 'wpCodeParent', $parent ) : '') . |
| 335 | + '<div>' . |
| 336 | + Xml::textArea( 'wpTextbox1', '' ) . |
| 337 | + '</div>' . |
| 338 | + '<div>' . |
| 339 | + Xml::submitButton( 'Submit comment', array( 'name' => 'wpSave' ) ) . |
| 340 | + ' ' . |
| 341 | + Xml::submitButton( 'Preview', array( 'name' => 'wpPreview' ) ) . |
| 342 | + '</div>' . |
| 343 | + '</div>' . |
| 344 | + '</form>'; |
| 345 | + } |
| 346 | +} |
\ No newline at end of file |
Index: trunk/extensions/CodeReview/CodeReview.php |
— | — | @@ -24,6 +24,7 @@ |
25 | 25 | |
26 | 26 | $wgAutoloadClasses['CodeRepository'] = $dir . 'CodeRepository.php'; |
27 | 27 | $wgAutoloadClasses['CodeRevision'] = $dir . 'CodeRevision.php'; |
| 28 | +$wgAutoloadClasses['CodeComment'] = $dir . 'CodeComment.php'; |
28 | 29 | $wgAutoloadClasses['SpecialCode'] = $dir . 'SpecialCode.php'; |
29 | 30 | $wgAutoloadClasses['SpecialRepoAdmin'] = $dir . 'SpecialRepoAdmin.php'; |
30 | 31 | $wgAutoloadClasses['SubversionAdaptor'] = $dir . 'Subversion.php'; |
Index: trunk/extensions/CodeReview/CodeComment.php |
— | — | @@ -0,0 +1,13 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class CodeComment { |
| 5 | + function __construct( $repo, $row ) { |
| 6 | + $this->repo = $repo; |
| 7 | + $this->id = $row->cc_id; |
| 8 | + $this->text = $row->cc_text; // fixme |
| 9 | + $this->user = $row->cc_user; |
| 10 | + $this->userText = $row->cc_user_text; |
| 11 | + $this->timestamp = wfTimestamp( TS_MW, $row->cc_timestamp ); |
| 12 | + $this->review = $row->cc_review; |
| 13 | + } |
| 14 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/CodeReview/CodeComment.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 15 | + native |
Index: trunk/extensions/CodeReview/codereview.css |
— | — | @@ -0,0 +1,15 @@ |
| 2 | +.mw-codereview-comment { |
| 3 | + border: solid 1px #aaaab3; |
| 4 | + padding: 0px; |
| 5 | + background: #eee; |
| 6 | + margin-bottom: 8px; |
| 7 | +} |
| 8 | + |
| 9 | +.mw-codereview-comment-meta { |
| 10 | + padding: 4px 8px; |
| 11 | +} |
| 12 | + |
| 13 | +.mw-codereview-comment-text { |
| 14 | + background: white; |
| 15 | + padding: 16px; |
| 16 | +} |
Property changes on: trunk/extensions/CodeReview/codereview.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 17 | + native |