• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List

system/handlers/admincommentshandler.php

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     // Create the top description
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     // Content
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     // Create the splitter
00048     $comment_controls = $form->append( FormControlTabs::create( 'comment_controls' ) );
00049 
00050     // Create the author info
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     // Create the advanced settings
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     // // Create the stats
00070     // $comment_controls->append('fieldset', 'stats_tab', _t('Stats'));
00071     // $stats = $form->stats_tab->append('wrapper', 'tags_buttons');
00072     // $stats->class = 'container';
00073     //
00074     // $stats->append('static', 'post_count', '<div class="container"><p class="pct25">'._t('Comments on this post:').'</p><p><strong>' . Comments::count_by_id($comment->post->id) . '</strong></p></div><hr />');
00075     // $stats->append('static', 'ip_count', '<div class="container"><p class="pct25">'._t('Comments from this IP:').'</p><p><strong>' . Comments::count_by_ip($comment->ip) . '</strong></p></div><hr />');
00076     // $stats->append('static', 'email_count', '<div class="container"><p class="pct25">'._t('Comments by this author:').'</p><p><strong>' . Comments::count_by_email($comment->email) . '</strong></p></div><hr />');
00077     // $stats->append('static', 'url_count', '<div class="container"><p class="pct25">'._t('Comments with this URL:').'</p><p><strong>' . Comments::count_by_url($comment->url) . '</strong></p></div><hr />');
00078 
00079     // Create the second set of action buttons
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     // Allow plugins to alter form
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       // Convenience array to output actions twice
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         // Get the $_POSTed values
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     // Get special search statuses
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     // Get special search types
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     // Make certain handler_vars local with defaults, and add them to the theme output
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     // Setting these mass_delete options prevents any other processing.  Desired?
00254     if ( isset( $mass_spam_delete ) && $status == 'spam' ) {
00255       // Delete all comments that have the spam status.
00256       Comments::delete_by_status( 'spam' );
00257       // let's optimize the table
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       // Delete all comments that are unapproved.
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     // if we're updating posts, let's do so:
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.']'} ) ) { // Skip unmoderated submitted comment_ids
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             // This comment was marked for deletion
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             // This comment was marked as spam
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             // Comments marked for approval
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' )] . ' &middot; ' : '' ) . '<a href="' . $comment->post->permalink . '">' . $comment->post->title . '</a> ';
00333             }
00334             break;
00335 
00336           case 'unapprove':
00337           case 'unapproved':
00338             // This comment was marked for unapproval
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               // This comment was edited
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     // we load the WSSE tokens
00382     // for use in the delete button
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     // only get comments the user is allowed to manage
00394     if ( !User::identify()->can( 'manage_all_comments' ) ) {
00395       $arguments['post_author'] = User::identify()->id;
00396     }
00397 
00398     // there is no explicit 'all' type/status for comments, so we need to unset these arguments
00399     // if that's what we want. At the same time we can set up the search field
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     /* Standard actions */
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     /* Allow plugins to apply actions */
00443     $actions = Plugins::filter( 'comments_actions', $baseactions, $this->theme->comments );
00444 
00445     foreach ( $this->theme->comments as $comment ) {
00446       // filter the actions based on the user's permissions
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       // remove the current status from the dropmenu
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     // check WSSE authentication
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       // skip POST elements which are not comment ids
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         // Comments marked for deletion
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         // Comments marked as spam
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         // Comments marked for approval
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         // Comments marked for unapproval
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         // Specific plugin-supplied action
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 ?>

Generated on Sun Aug 4 2013 12:51:43 for Habari by  doxygen 1.7.1