00001 <?php
00007 namespace Habari;
00008
00035 class Comment extends QueryRecord implements IsContent
00036 {
00037 private $post_object = null;
00038
00039 private $inforecords = null;
00040
00041
00042 static $comment_status_list = array();
00043 static $comment_type_list = array();
00044 static $comment_status_actions = array();
00045
00050 public static function default_fields()
00051 {
00052 return array(
00053 'id' => 0,
00054 'post_id' => 0,
00055 'name' => '',
00056 'email' => '',
00057 'url' => '',
00058 'ip' => 0,
00059 'content' => '',
00060 'status' => self::status('unapproved'),
00061 'date' => DateTime::create(),
00062 'type' => self::type('comment')
00063 );
00064 }
00065
00070 public function __construct( $paramarray = array() )
00071 {
00072
00073 $this->fields = array_merge( self::default_fields(), $this->fields );
00074 parent::__construct( $paramarray );
00075 $this->exclude_fields( 'id' );
00076 }
00077
00082 public static function __static()
00083 {
00084 Pluggable::load_hooks(__CLASS__);
00085 }
00086
00098 static function get( $id = 0 )
00099 {
00100 if ( ! $id ) {
00101 return false;
00102 }
00103 return DB::get_row( 'SELECT * FROM {comments} WHERE id = ?', array( $id ), 'Comment' );
00104 }
00105
00112 static function create( $paramarray )
00113 {
00114 $comment = new Comment( $paramarray );
00115 $comment->insert();
00116 return $comment;
00117 }
00118
00123 public function insert()
00124 {
00125 $allow = true;
00126 $allow = Plugins::filter( 'comment_insert_allow', $allow, $this );
00127 if ( ! $allow ) {
00128 return false;
00129 }
00130 Plugins::act( 'comment_insert_before', $this );
00131
00132 foreach ( $this->fields as $fieldname => $value ) {
00133 Plugins::act( 'comment_update_' . $fieldname, $this, $this->$fieldname, $value );
00134 }
00135 $result = parent::insertRecord( DB::table( 'comments' ) );
00136 $this->newfields['id'] = DB::last_insert_id();
00137 $this->fields = array_merge( $this->fields, $this->newfields );
00138 $this->newfields = array();
00139 $this->info->commit( $this->fields['id'] );
00140 Plugins::act( 'comment_insert_after', $this );
00141 return $result;
00142 }
00143
00149 public static function add_type($type)
00150 {
00151 DB::insert(
00152 DB::table('commenttype'),
00153 array(
00154 'name' => $type,
00155 'active' => 1,
00156 )
00157 );
00158 return DB::last_insert_id();
00159 }
00160
00167 public static function add_status($status, $internal = false)
00168 {
00169 DB::insert(
00170 DB::table('commentstatus'),
00171 array(
00172 'name' => $status,
00173 'internal' => $internal ? 1 : 0,
00174 )
00175 );
00176 return DB::last_insert_id();
00177 }
00178
00184 public static function remove_type($type, $delete = false)
00185 {
00186 if($delete) {
00187
00188 $type_id = Comment::type($type);
00189 DB::delete(
00190 DB::table('comments'),
00191 array('type' => $type_id)
00192 );
00193 DB::exec('DELETE FROM {commentinfo} WHERE comment_id IN (SELECT {commentinfo}.comment_id FROM {commentinfo} LEFT JOIN {comments} ON {commentinfo}.comment_id = {comments}.id WHERE {comments}.id IS NULL)');
00194 DB::delete(
00195 DB::table('commenttype'),
00196 array('name' => Comment::type_name($type))
00197 );
00198 }
00199 else {
00200 DB::update(
00201 DB::table('commenttype'),
00202 array(
00203 'name' => Comment::type_name($type),
00204 'active' => 0,
00205 ),
00206 array('name')
00207 );
00208 }
00209 }
00210
00216 public static function remove_status($status, $newstatus = null)
00217 {
00218
00219 $status_id = Comment::status($status);
00220 if(is_null($newstatus)) {
00221 DB::delete(
00222 DB::table('comments'),
00223 array('status' => $status_id)
00224 );
00225 DB::exec('DELETE FROM {commentinfo} WHERE comment_id IN (SELECT {commentinfo}.comment_id FROM {commentinfo} LEFT JOIN {comments} ON {commentinfo}.comment_id = {comments}.id WHERE {comments}.id IS NULL)');
00226 }
00227 else {
00228 DB::update(
00229 DB::table('comments'),
00230 array('status' => Comment::status($newstatus)),
00231 array('status' => $status_id)
00232 );
00233 }
00234 DB::delete(
00235 DB::table('commentstatus'),
00236 array('name' => Comment::status_name($status))
00237 );
00238 }
00239
00244 public function update()
00245 {
00246 $allow = true;
00247 $allow = Plugins::filter( 'comment_update_allow', $allow, $this );
00248 if ( ! $allow ) {
00249 return false;
00250 }
00251 Plugins::act( 'comment_update_before', $this );
00252
00253 foreach ( $this->newfields as $fieldname => $value ) {
00254 Plugins::act( 'comment_update_' . $fieldname, $this, $this->fields[$fieldname], $value );
00255 }
00256 $result = parent::updateRecord( DB::table( 'comments' ), array( 'id'=>$this->id ) );
00257 $this->fields = array_merge( $this->fields, $this->newfields );
00258 $this->newfields = array();
00259 $this->info->commit();
00260 Plugins::act( 'comment_update_after', $this );
00261 return $result;
00262 }
00263
00268 public function delete()
00269 {
00270 $allow = true;
00271 $allow = Plugins::filter( 'comment_delete_allow', $allow, $this );
00272 if ( ! $allow ) {
00273 return false;
00274 }
00275 Plugins::act( 'comment_delete_before', $this );
00276
00277
00278 $this->info->delete_all();
00279
00280 $result = parent::deleteRecord( DB::table( 'comments' ), array( 'id'=>$this->id ) );
00281 Plugins::act( 'comment_delete_after', $this );
00282 return $result;
00283 }
00284
00290 public function __get( $name )
00291 {
00292 $fieldnames = array_merge( array_keys( $this->fields ), array('post', 'info', 'editlink' ) );
00293 $filter = false;
00294 if ( !in_array( $name, $fieldnames ) && strpos( $name, '_' ) !== false ) {
00295 $field_matches = implode('|', $fieldnames);
00296 if(preg_match( '/^(' . $field_matches . ')_(.+)$/', $name, $matches )) {
00297 list( $unused, $name, $filter ) = $matches;
00298 }
00299 }
00300
00301 switch ( $name ) {
00302 case 'name':
00303 if ( parent::__get( $name ) == '' ) {
00304 $out = _t( 'Anonymous' );
00305 }
00306 else {
00307 $out = parent::__get( $name );
00308 }
00309 break;
00310 case 'post':
00311 $out = $this->get_post();
00312 break;
00313 case 'info':
00314 $out = $this->get_info();
00315 break;
00316 case 'statusname':
00317 $out = self::status_name( $this->status );
00318 break;
00319 case 'typename':
00320 $out = self::type_name( $this->type );
00321 break;
00322 case 'editlink':
00323 $out = $this->get_editlink();
00324 break;
00325 default:
00326 if(preg_match('#^is_(.+)$#i', $name, $matches)) {
00327 $ts_field = $matches[1];
00328 if($index = array_search($ts_field, Comment::list_comment_statuses())) {
00329 $out = $this->status == $index;
00330 }
00331 if($index = array_search($ts_field, Comment::list_comment_types())) {
00332 $out = $this->type == $index;
00333 }
00334
00335 $pluralize = function($s) {
00336 return $s . 's';
00337 };
00338 if($index = array_search($ts_field, array_map($pluralize, Comment::list_comment_statuses()))) {
00339 $out = $this->status == $index;
00340 }
00341 if($index = array_search($ts_field, array_map($pluralize, Comment::list_comment_types()))) {
00342 $out = $this->type == $index;
00343 }
00344 }
00345 else {
00346 $out = parent::__get( $name );
00347 }
00348 break;
00349 }
00350
00351 $out = Plugins::filter( "comment_{$name}", $out, $this );
00352 if ( $filter ) {
00353 $out = Plugins::filter( "comment_{$name}_{$filter}", $out, $this );
00354 }
00355 return $out;
00356 }
00357
00364 public function __set( $name, $value )
00365 {
00366 switch ( $name ) {
00367 case 'status':
00368 $value = self::status($value);
00369 break;
00370 case 'date':
00371 if ( !( $value instanceOf DateTime ) ) {
00372 $value = DateTime::create( $value );
00373 }
00374 break;
00375 case 'post':
00376 if ( is_int( $value ) ) {
00377
00378 $p = Post::get( array( 'id'=>$value ) );
00379 $this->post_id = $p->id;
00380 $this->post_object = $p;
00381 }
00382 elseif ( is_string( $value ) ) {
00383
00384 $p = Post::get( array( 'slug'=>$value ) );
00385 $this->post_id = $p->id;
00386 $this->post_object = $p;
00387 }
00388 elseif ( is_object( $value ) ) {
00389
00390 $this->post_id = $value->id;
00391 $this->post_object = $value;
00392 }
00393 return $value;
00394 }
00395 return parent::__set( $name, $value );
00396 }
00397
00403 private function get_post( $use_cache = true )
00404 {
00405 if ( ! isset( $this->post_object ) || ( ! $use_cache) ) {
00406 $this->post_object = Posts::get( array('id' => $this->post_id, 'fetch_fn' => 'get_row') );
00407 }
00408 return $this->post_object;
00409 }
00410
00416 private function get_info()
00417 {
00418 if ( ! $this->inforecords ) {
00419 if ( 0 == $this->id ) {
00420 $this->inforecords = new CommentInfo();
00421 }
00422 else {
00423 $this->inforecords = new CommentInfo( $this->id );
00424 }
00425 }
00426 return $this->inforecords;
00427 }
00428
00434 public static function list_comment_types( $refresh = false )
00435 {
00436 if ( $refresh || empty( self::$comment_type_list ) ) {
00437 self::$comment_type_list = DB::get_keyvalue('SELECT id, name FROM {commenttype} WHERE active = 1;');
00438 }
00439 self::$comment_type_list = Plugins::filter( 'list_comment_types', self::$comment_type_list );
00440 return self::$comment_type_list;
00441 }
00442
00448 public static function list_comment_statuses( $refresh = false )
00449 {
00450 if ( $refresh || empty( self::$comment_status_list ) ) {
00451 self::$comment_status_list = DB::get_keyvalue('SELECT id, name FROM {commentstatus};');
00452 }
00453 self::$comment_status_list = Plugins::filter( 'list_comment_statuses', self::$comment_status_list );
00454 return self::$comment_status_list;
00455 }
00456
00462 public static function status_action( $status )
00463 {
00464 if ( empty( self::$comment_status_actions ) ) {
00465 self::$comment_status_actions = array(
00466 'unapproved' => _t( 'Unapprove' ),
00467 'approved' => _t( 'Approve' ),
00468 'spam' => _t( 'Spam' ),
00469 );
00470 self::$comment_status_actions = Plugins::filter( 'list_comment_actions', self::$comment_status_actions );
00471 }
00472 if ( isset( self::$comment_status_actions[$status] ) ) {
00473 return self::$comment_status_actions[$status];
00474 }
00475 if ( isset(self::$comment_status_actions[Comment::status_name($status)]) ) {
00476 return self::$comment_status_actions[Comment::status_name($status)];
00477 }
00478
00479 return '';
00480 }
00481
00482
00488 public static function status( $name )
00489 {
00490 $statuses = Comment::list_comment_statuses();
00491 if ( is_numeric( $name ) && ( isset( $statuses[$name] ) ) ) {
00492 return $name;
00493 }
00494 $statuses = array_flip( $statuses );
00495 if ( isset( $statuses[$name] ) ) {
00496 return $statuses[$name];
00497 }
00498 return false;
00499 }
00500
00506 public static function status_name( $status )
00507 {
00508 $statuses = Comment::list_comment_statuses();
00509 if ( is_numeric( $status ) && isset( $statuses[$status] ) ) {
00510 return $statuses[$status];
00511 }
00512 $statuses = array_flip( $statuses );
00513 if ( isset( $statuses[$status] ) ) {
00514 return $status;
00515 }
00516 return '';
00517 }
00518
00524 public static function type( $name )
00525 {
00526 $types = Comment::list_comment_types();
00527 if ( is_numeric( $name ) && ( isset( $types[$name] ) ) ) {
00528 return $name;
00529 }
00530 $types = array_flip( $types );
00531 if ( isset( $types[$name] ) ) {
00532 return $types[$name];
00533 }
00534 return false;
00535 }
00536
00542 public static function type_name( $type )
00543 {
00544 $types = Comment::list_comment_types();
00545 if ( is_numeric( $type ) && isset( $types[$type] ) ) {
00546 return $types[$type];
00547 }
00548 $types = array_flip( $types );
00549 if ( isset( $types[$type] ) ) {
00550 return $type;
00551 }
00552 return '';
00553 }
00554
00561 public function content_type()
00562 {
00563 return Comment::type_name( $this->type );
00564 }
00565
00572 public function get_access( $user = null )
00573 {
00574 if ( ! $user instanceof User ) {
00575 $user = User::identify();
00576 }
00577
00578
00579 if ( $user->can( 'super_user' ) || $user->can( 'manage_all_comments' ) ||
00580 ( $user->id == $this->post->user_id && $user->can( 'manage_own_post_comments' ) ) ) {
00581 return ACL::get_bitmask( 'full' );
00582 }
00583
00584
00585
00586
00587 $tokens = array(
00588 'post_any',
00589 'post_' . Post::type_name( $this->post->content_type ),
00590 );
00591
00592 if ( $user->id == $this->post->user_id ) {
00593 $tokens[] = 'own_posts';
00594 }
00595
00596 $tokens = array_merge( $tokens, $this->post->get_tokens() );
00597
00598 $token_accesses = array();
00599
00600
00601 foreach ( $tokens as $token ) {
00602 $access = ACL::get_user_token_access( $user, $token );
00603 if ( $access instanceof Bitmask ) {
00604 $token_accesses[] = ACL::get_user_token_access( $user, $token )->value;
00605 }
00606 }
00607
00608
00609 if ( in_array( 0, $token_accesses ) ) {
00610 return ACL::get_bitmask( 0 );
00611 }
00612
00613 if ( ACL::get_bitmask( Utils::array_or( $token_accesses ) )->read ) {
00614 return ACL::get_bitmask( 'read' );
00615 }
00616
00617
00618 return ACL::get_bitmask( 0 );
00619 }
00620
00625 private function get_editlink()
00626 {
00627 return URL::get( 'edit_comment', $this, false );
00628 }
00629
00636 public function css_class ( $append = array() ) {
00637
00638 $classes = $append;
00639
00640 $classes[] = 'comment';
00641 $classes[] = 'comment-' . $this->id;
00642 $classes[] = 'type-' . $this->typename;
00643 $classes[] = 'status-' . $this->statusname;
00644
00645 $classes[] = 'comment-post-' . $this->post->id;
00646
00647 return implode( ' ', $classes );
00648
00649 }
00650
00659 public static function filter_comment_type_display_4( $type, $foruse )
00660 {
00661 $names = array(
00662 'comment' => array(
00663 'singular' => _t( 'comment' ),
00664 'plural' => _t( 'comments' ),
00665 ),
00666 'pingback' => array(
00667 'singular' => _t( 'pingback' ),
00668 'plural' => _t( 'pingbacks' ),
00669 ),
00670 'trackback' => array(
00671 'singular' => _t( 'trackback' ),
00672 'plural' => _t( 'trackbacks' ),
00673 ),
00674 );
00675 return isset( $names[$type][$foruse] ) ? $names[$type][$foruse] : $type;
00676 }
00677
00685 public static function filter_comment_status_display_4( $status )
00686 {
00687 $names = array(
00688 'unapproved' => _t( 'unapproved' ),
00689 'approved' => _t( 'approved' ),
00690 'spam' => _t( 'spam' ),
00691 );
00692 return isset( $names[$status] ) ? $names[$status] : $status;
00693 }
00694 }
00695
00696 ?>