00001 <?php
00007 namespace Habari;
00008
00014 class AdminCommentsHandler extends AdminHandler
00015 {
00020 public function form_comment( $comment, $actions )
00021 {
00022 $form = new FormUI( 'comment' );
00023
00024 $user = User::identify();
00025
00026
00027 $top = $form->append( FormControlWrapper::create( 'buttons_1', null, array( 'class' => array( 'container', 'buttons', 'comment', 'overview' ) ) ) );
00028 $top->append( FormControlStatic::create( 'overview', null )->set_static( $this->theme->fetch( 'comment.overview' ) ) );
00029 $buttons_1 = $top->append( FormControlWrapper::create( 'buttons_1', null, array( 'class' => array( 'item', 'buttons' ) ) ) );
00030
00031 foreach ( $actions as $status => $action ) {
00032 $id = $action . '_1';
00033 $buttons_1->append( FormControlSubmit::create( $id , null, array( 'class' => array('status', 'button', $action ) ) )->set_caption( MUltiByte::ucfirst( _t( $action ) ) ) );
00034 if ( Comment::status_name( $comment->status ) == $status ) {
00035 $buttons_1->$id->add_class( 'active' );
00036 $buttons_1->$id->set_properties( array( 'disabled' => true ) );
00037 }
00038 else {
00039 $buttons_1->$id->set_properties( array( 'disabled' => false ) );
00040 }
00041 }
00042
00043
00044 $form->append( FormControlWrapper::create( 'content_wrapper' ) );
00045 $form->content_wrapper->append( FormControlLabel::wrap( _t( 'Comment' ), FormControlTextArea::create( 'content', null, array( 'class' => 'resizable' ) )->set_value( $comment->content ) ) );
00046
00047
00048 $comment_controls = $form->append( FormControlTabs::create( 'comment_controls' ) );
00049
00050
00051 $author = $comment_controls->append( FormControlFieldset::create( 'authorinfo' )->set_caption( _t( 'Author' ) ) );
00052
00053 $author->append( FormControlLabel::wrap( _t( 'Author Name' ), FormControlText::create( 'author_name' )->set_value( $comment->name ) ) );
00054 $author->append( FormControlLabel::wrap( _t( 'Author Email' ), FormControlText::create( 'author_email' )->set_value( $comment->email ) ) );
00055 $author->append( FormControlLabel::wrap( _t( 'Author URL' ), FormControlText::create( 'author_url' )->set_value( $comment->url ) ) );
00056 $author->append( FormControlLabel::wrap( _t( 'IP Address:' ), FormControlText::create( 'author_ip' )->set_value( $comment->ip ) ) );
00057
00058
00059
00060 $settings = $comment_controls->append( FormControlFieldset::create( 'settings' )->set_caption( _t( 'Settings' ) ) );
00061
00062 $settings->append( FormControlLabel::wrap( _t( 'Date:' ), FormControlText::create( 'comment_date' )->set_value( $comment->date->get( 'Y-m-d H:i:s' ) ) ) );
00063 $settings->append( FormControlLabel::wrap( _t( 'Post ID:' ), FormControlText::create( 'comment_post' )->set_value( $comment->post->id ) ) );
00064
00065 $statuses = Comment::list_comment_statuses( false );
00066 $statuses = Plugins::filter( 'admin_publish_list_comment_statuses', $statuses );
00067 $settings->append( FormControlLabel::wrap( _t( 'Status' ), FormControlSelect::create( 'comment_status' )->set_options( $statuses)->set_value( $comment->status ) ) );
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 $buttons_2 = $form->append( FormControlWrapper::create( 'buttons_2', null, array( 'class'=> array( 'container', 'buttons', 'comment' ) ) ) );
00081
00082 foreach ( $actions as $status => $action ) {
00083 $id = $action . '_2';
00084 $buttons_2->append( FormControlSubmit::create( $id , null, array( 'class' => array('status', 'button', $action ) ) )->set_caption( MUltiByte::ucfirst( _t( $action ) ) ) );
00085 if ( Comment::status_name( $comment->status ) == $status ) {
00086 $buttons_2->$id->add_class( 'active' );
00087 $buttons_2->$id->set_properties( array( 'disabled' => true ) );
00088 }
00089 else {
00090 $buttons_2->$id->set_properties( array( 'disabled' => false ) );
00091 }
00092 }
00093
00094
00095 Plugins::act( 'form_comment_edit', $form, $comment );
00096
00097 return $form;
00098 }
00099
00103 public function get_comment( $update = false )
00104 {
00105 if ( isset( $this->handler_vars['id'] ) && $comment = Comment::get( $this->handler_vars['id'] ) ) {
00106 $this->theme->comment = $comment;
00107
00108
00109 $actions = array(
00110 'deleted' => 'delete',
00111 'spam' => 'spam',
00112 'unapproved' => 'unapprove',
00113 'approved' => 'approve',
00114 'saved' => 'save'
00115 );
00116
00117 $form = $this->form_comment( $comment, $actions );
00118
00119 if ( $update ) {
00120
00121 $form->process();
00122
00123 foreach ( $actions as $key => $action ) {
00124 $id_one = $action . '_1';
00125 $id_two = $action . '_2';
00126 if ( $form->$id_one->value != null || $form->$id_two->value != null ) {
00127 if ( $action == 'delete' ) {
00128 $comment->delete();
00129 Utils::redirect( URL::get( 'display_comments' ) );
00130 }
00131 if ( $action != 'save' ) {
00132 foreach ( Comment::list_comment_statuses() as $status ) {
00133 if ( $status == $key ) {
00134 $comment->status = Comment::status_name( $status );
00135 $set_status = true;
00136 }
00137 }
00138 }
00139 }
00140 }
00141
00142 $comment->content = $form->content->value;
00143 $comment->name = $form->author_name->value;
00144 $comment->url = $form->author_url->value;
00145 $comment->email = $form->author_email->value;
00146 $comment->ip = $form->author_ip->value;
00147
00148 $comment->date = DateTime::create( $form->comment_date->value );
00149 $comment->post_id = $form->comment_post->value;
00150
00151 if ( ! isset( $set_status ) ) {
00152 $comment->status = $form->comment_status->value;
00153 }
00154
00155 $comment->update();
00156
00157 Plugins::act( 'comment_edit', $comment, $form );
00158
00159 Utils::redirect();
00160 }
00161
00162 $comment->content = $form;
00163 $this->theme->form = $form;
00164
00165 $this->display( 'comment' );
00166 }
00167 else {
00168 Utils::redirect( URL::get( 'display_comments' ) );
00169 }
00170 }
00171
00175 public function post_comment()
00176 {
00177 $this->get_comment( true );
00178 }
00179
00183 public function get_comments()
00184 {
00185 $this->post_comments();
00186 }
00187
00192 public function post_comments()
00193 {
00194
00195 $statuses = Comment::list_comment_statuses();
00196 $labels = array_map(
00197 function($a) {return MultiByte::ucfirst(Plugins::filter("comment_status_display", $a));},
00198 $statuses
00199 );
00200 $terms = array_map(
00201 function($a) {return "status:{$a}";},
00202 $statuses
00203 );
00204 $statuses = array_combine( $terms, $labels );
00205
00206
00207 $types = Comment::list_comment_types();
00208 $labels = array_map(
00209 function($a) {return MultiByte::ucfirst(Plugins::filter("comment_type_display", $a, "singular")) ;},
00210 $types
00211 );
00212 $terms = array_map(
00213 function($a) {return "type:{$a}";},
00214 $types
00215 );
00216 $types = array_combine( $terms, $labels );
00217
00218 $this->theme->special_searches = array_merge( $statuses, $types );
00219
00220 $this->fetch_comments();
00221 $this->display( 'comments' );
00222 }
00223
00227 public function fetch_comments( $params = array() )
00228 {
00229
00230 $locals = array(
00231 'do_delete' => false,
00232 'do_spam' => false,
00233 'do_approve' => false,
00234 'do_unapprove' => false,
00235 'comment_ids' => null,
00236 'nonce' => '',
00237 'timestamp' => '',
00238 'password_digest' => '',
00239 'mass_spam_delete' => null,
00240 'mass_delete' => null,
00241 'type' => 'All',
00242 'limit' => 20,
00243 'offset' => 0,
00244 'search' => '',
00245 'status' => 'All',
00246 'orderby' => 'date DESC',
00247 );
00248 foreach ( $locals as $varname => $default ) {
00249 $$varname = isset( $this->handler_vars[$varname] ) ? $this->handler_vars[$varname] : ( isset( $params[$varname] ) ? $params[$varname] : $default );
00250 $this->theme->{$varname} = $$varname;
00251 }
00252
00253
00254 if ( isset( $mass_spam_delete ) && $status == 'spam' ) {
00255
00256 Comments::delete_by_status( 'spam' );
00257
00258 $result = DB::query( 'OPTIMIZE TABLE {comments}' );
00259 Session::notice( _t( 'Deleted all spam comments' ) );
00260 EventLog::log( _t( 'Deleted all spam comments' ), 'info' );
00261 Utils::redirect();
00262 }
00263 elseif ( isset( $mass_delete ) && $status == 'unapproved' ) {
00264
00265 Comments::delete_by_status( 'unapproved' );
00266 Session::notice( _t( 'Deleted all unapproved comments' ) );
00267 EventLog::log( _t( 'Deleted all unapproved comments' ), 'info' );
00268 Utils::redirect();
00269 }
00270
00271 elseif ( ( $do_delete || $do_spam || $do_approve || $do_unapprove ) && isset( $comment_ids ) ) {
00272 $okay = true;
00273 if ( empty( $nonce ) || empty( $timestamp ) || empty( $password_digest ) ) {
00274 $okay = false;
00275 }
00276 $wsse = Utils::WSSE( $nonce, $timestamp );
00277 if ( $password_digest != $wsse['digest'] ) {
00278 $okay = false;
00279 }
00280 if ( $okay ) {
00281 if ( $do_delete ) {
00282 $action = 'delete';
00283 }
00284 elseif ( $do_spam ) {
00285 $action = 'spam';
00286 }
00287 elseif ( $do_approve ) {
00288 $action = 'approve';
00289 }
00290 elseif ( $do_unapprove ) {
00291 $action = 'unapprove';
00292 }
00293 $ids = array();
00294 foreach ( $comment_ids as $id => $id_value ) {
00295 if ( ! isset( ${'$comment_ids['.$id.']'} ) ) {
00296 $ids[] = $id;
00297 }
00298 }
00299 $to_update = Comments::get( array( 'id' => $ids ) );
00300 $modstatus = array(
00301 _t( 'Deleted %d comments' ) => 0,
00302 _t( 'Marked %d comments as spam' ) => 0,
00303 _t( 'Approved %d comments' ) => 0,
00304 _t( 'Unapproved %d comments' ) => 0,
00305 _t( 'Edited %d comments' ) => 0
00306 );
00307 Plugins::act( 'admin_moderate_comments', $action, $to_update, $this );
00308
00309 switch ( $action ) {
00310
00311 case 'delete':
00312
00313 $to_update = $this->comment_access_filter( $to_update, 'delete' );
00314 Comments::delete_these( $to_update );
00315 $modstatus[_t( 'Deleted %d comments' )] = count( $to_update );
00316 break;
00317
00318 case 'spam':
00319
00320 $to_update = $this->comment_access_filter( $to_update, 'edit' );
00321 Comments::moderate_these( $to_update, 'spam' );
00322 $modstatus[_t( 'Marked %d comments as spam' )] = count( $to_update );
00323 break;
00324
00325 case 'approve':
00326 case 'approved':
00327
00328 $to_update = $this->comment_access_filter( $to_update, 'edit' );
00329 Comments::moderate_these( $to_update, 'approved' );
00330 $modstatus[_t( 'Approved %d comments' )] = count( $to_update );
00331 foreach ( $to_update as $comment ) {
00332 $modstatus[_t( 'Approved comments on these posts: %s' )] = ( isset( $modstatus[_t( 'Approved comments on these posts: %s' )] )? $modstatus[_t( 'Approved comments on these posts: %s' )] . ' · ' : '' ) . '<a href="' . $comment->post->permalink . '">' . $comment->post->title . '</a> ';
00333 }
00334 break;
00335
00336 case 'unapprove':
00337 case 'unapproved':
00338
00339 $to_update = $this->comment_access_filter( $to_update, 'edit' );
00340 Comments::moderate_these( $to_update, 'unapproved' );
00341 $modstatus[_t( 'Unapproved %d comments' )] = count( $to_update );
00342 break;
00343
00344 case 'edit':
00345 $to_update = $this->comment_access_filter( $to_update, 'edit' );
00346 foreach ( $to_update as $comment ) {
00347
00348 if ( $_POST['name_' . $comment->id] != null ) {
00349 $comment->name = $_POST['name_' . $comment->id];
00350 }
00351 if ( $_POST['email_' . $comment->id] != null ) {
00352 $comment->email = $_POST['email_' . $comment->id];
00353 }
00354
00355 if ( $_POST['url_' . $comment->id] != null ) {
00356 $comment->url = $_POST['url_' . $comment->id];
00357 }
00358 if ( $_POST['content_' . $comment->id] != null ) {
00359 $comment->content = $_POST['content_' . $comment->id];
00360 }
00361
00362 $comment->update();
00363 }
00364 $modstatus[_t( 'Edited %d comments' )] = count( $to_update );
00365 break;
00366
00367 }
00368
00369 foreach ( $modstatus as $key => $value ) {
00370 if ( $value ) {
00371 Session::notice( sprintf( $key, $value ) );
00372 }
00373 }
00374
00375 }
00376
00377 Utils::redirect();
00378
00379 }
00380
00381
00382
00383 $this->theme->wsse = Utils::WSSE();
00384
00385 $arguments = array(
00386 'type' => $type,
00387 'status' => $status,
00388 'limit' => $limit,
00389 'offset' => $offset,
00390 'orderby' => $orderby,
00391 );
00392
00393
00394 if ( !User::identify()->can( 'manage_all_comments' ) ) {
00395 $arguments['post_author'] = User::identify()->id;
00396 }
00397
00398
00399
00400 $this->theme->search_args = '';
00401 if ( $type == 'All' ) {
00402 unset( $arguments['type'] );
00403 }
00404 else {
00405 $this->theme->search_args = 'type:' . Comment::type_name( $type ) . ' ';
00406 }
00407
00408 if ( $status == 'All' ) {
00409 unset ( $arguments['status'] );
00410 }
00411 else {
00412 $this->theme->search_args .= 'status:' . Comment::status_name( $status );
00413 }
00414
00415 if ( '' != $search ) {
00416 $arguments = array_merge( $arguments, Comments::search_to_get( $search ) );
00417 }
00418
00419 $this->theme->comments = Comments::get( $arguments );
00420 $monthcts = Comments::get( array_merge( $arguments, array( 'month_cts' => 1 ) ) );
00421 $years = array();
00422 foreach ( $monthcts as $month ) {
00423 if ( isset( $years[$month->year] ) ) {
00424 $years[$month->year][] = $month;
00425 }
00426 else {
00427 $years[$month->year] = array( $month );
00428 }
00429 }
00430 $this->theme->years = $years;
00431
00432 $baseactions = array();
00433 $statuses = Comment::list_comment_statuses();
00434 foreach ( $statuses as $statusid => $statusname ) {
00435 $baseactions[$statusname] = array( 'url' => 'javascript:itemManage.update(\'' . $statusname . '\',__commentid__);', 'title' => _t( 'Change this comment\'s status to %s', array( $statusname ) ), 'label' => Comment::status_action( $statusid ), 'access' => 'edit' );
00436 }
00437
00438
00439 $baseactions['delete'] = array( 'url' => 'javascript:itemManage.update(\'delete\',__commentid__);', 'title' => _t( 'Delete this comment' ), 'label' => _t( 'Delete' ), 'access' => 'delete' );
00440 $baseactions['edit'] = array( 'url' => URL::get( 'edit_comment', 'id=__commentid__' ), 'title' => _t( 'Edit this comment' ), 'label' => _t( 'Edit' ), 'access' => 'edit' );
00441
00442
00443 $actions = Plugins::filter( 'comments_actions', $baseactions, $this->theme->comments );
00444
00445 foreach ( $this->theme->comments as $comment ) {
00446
00447 $comment_access = $comment->get_access();
00448 $menu = array();
00449 foreach ( $actions as $name => $action ) {
00450 if ( !isset( $action['access'] ) || ACL::access_check( $comment_access, $action['access'] ) ) {
00451 $menu[$name] = $action;
00452 }
00453 }
00454
00455 unset( $menu[Comment::status_name( $comment->status )] );
00456 $comment->menu = Plugins::filter( 'comment_actions', $menu, $comment );
00457 }
00458 }
00459
00467 public function comment_access_filter( $comments, $access )
00468 {
00469 $result = array();
00470 foreach ( $comments as $comment ) {
00471 if ( ACL::access_check( $comment->get_access(), $access ) ) {
00472 $result[] = $comment;
00473 }
00474 }
00475 return $result;
00476 }
00477
00481 public function ajax_comments()
00482 {
00483 Utils::check_request_method( array( 'GET', 'HEAD' ) );
00484
00485 $this->create_theme();
00486 $this->theme->theme = $this->theme;
00487
00488 $params = $_GET;
00489
00490 $this->fetch_comments( $params );
00491 $items = $this->theme->fetch( 'comments_items' );
00492 $timeline = $this->theme->fetch( 'timeline_items' );
00493
00494 $item_ids = array();
00495
00496 foreach ( $this->theme->comments as $comment ) {
00497 $item_ids['p' . $comment->id] = 1;
00498 }
00499
00500 $ar = new AjaxResponse();
00501 $ar->data = array(
00502 'items' => $items,
00503 'item_ids' => $item_ids,
00504 'timeline' => $timeline,
00505 );
00506 $ar->out();
00507 }
00508
00512 public function ajax_update_comment( $handler_vars )
00513 {
00514
00515 Utils::check_request_method( array( 'POST' ) );
00516 $ar = new AjaxResponse();
00517
00518
00519 $wsse = Utils::WSSE( $handler_vars['nonce'], $handler_vars['timestamp'] );
00520 if ( $handler_vars['digest'] != $wsse['digest'] ) {
00521 $ar->message = _t( 'WSSE authentication failed.' );
00522 $ar->out();
00523 return;
00524 }
00525
00526 $ids = array();
00527
00528 foreach ( $_POST as $id => $update ) {
00529
00530 if ( preg_match( '/^p\d+$/', $id ) && $update ) {
00531 $ids[] = (int) substr( $id, 1 );
00532 }
00533 }
00534
00535 if ( ( ! isset( $ids ) || empty( $ids ) ) && $handler_vars['action'] == 'delete' ) {
00536 $ar->message = _t( 'No comments selected.' );
00537 $ar->out();
00538 return;
00539 }
00540
00541 $comments = Comments::get( array( 'id' => $ids, 'nolimit' => true ) );
00542 Plugins::act( 'admin_moderate_comments', $handler_vars['action'], $comments, $this );
00543 $status_msg = _t( 'Unknown action "%s"', array( $handler_vars['action'] ) );
00544
00545 switch ( $handler_vars['action'] ) {
00546 case 'delete_spam':
00547 Comments::delete_by_status( 'spam' );
00548 $status_msg = _t( 'Deleted all spam comments' );
00549 break;
00550 case 'delete_unapproved':
00551 Comments::delete_by_status( 'unapproved' );
00552 $status_msg = _t( 'Deleted all unapproved comments' );
00553 break;
00554 case 'delete':
00555
00556 Comments::delete_these( $comments );
00557 $status_msg = sprintf( _n( 'Deleted %d comment', 'Deleted %d comments', count( $ids ) ), count( $ids ) );
00558 break;
00559 case 'spam':
00560
00561 Comments::moderate_these( $comments, 'spam' );
00562 $status_msg = sprintf( _n( 'Marked %d comment as spam', 'Marked %d comments as spam', count( $ids ) ), count( $ids ) );
00563 break;
00564 case 'approve':
00565 case 'approved':
00566
00567 Comments::moderate_these( $comments, 'approved' );
00568 $status_msg = sprintf( _n( 'Approved %d comment', 'Approved %d comments', count( $ids ) ), count( $ids ) );
00569 break;
00570 case 'unapprove':
00571 case 'unapproved':
00572
00573 Comments::moderate_these( $comments, 'unapproved' );
00574 $status_msg = sprintf( _n( 'Unapproved %d comment', 'Unapproved %d comments', count( $ids ) ), count( $ids ) );
00575 break;
00576 default:
00577
00578 $status_msg = Plugins::filter( 'admin_comments_action', $status_msg, $handler_vars['action'], $comments );
00579 break;
00580 }
00581
00582 $ar->message = $status_msg;
00583 $ar->out();
00584 }
00585
00586 }
00587 ?>