#!/usr/bin/perl use strict; use warnings; =head1 NAME mt_close_comments -- close old MovableType entries to comments =head1 SYNOPSIS F S> S> S> S> S> S> S> S> =head1 DESCRIPTION C closes movable type entries to comments and trackbacks with a simple SQL query. This is meant to be used from a cron job, sample cron entry: # Close movable type entries that are older than 15 days to comments once a day at 4am. # 0 4 * * * mt_close_comments =head1 ARGUMENTS =over 4 =item B<-h>, B<--help> See a synopsis. =item B<--man> Browse the manpage. =back =head1 OPTIONS =over 4 =item B<-n>, B<--just-print>, B<--dry-run> Don't actually do anything, just provide feedback on what would have been done. =item B<-t> Close trackbacks too. =item B<--days=num> Close entries older than these many days. [default: 15] =item B<--db-type> The type of the database. [default: mysql] =item B<--db-host> The database host. =item B<--db-user> The username with which to authenticate to the database. =item B<--db-pass> The password for the given database username. =back =head1 SEE ALSO FIXME =head1 BUGS FIXME =head1 AUTHORS Kasia Trapszo =head1 COPYRIGHT FIXME =cut use DBI; use Pod::Usage; use Getopt::Long 2.24, qw( :config bundling no_ignore_case no_auto_abbrev ); my $dbh; sub db_connect { my ( $db, $user, $password, $host, $type ) = @_; my $dbh = DBI->connect( "DBI:$type:database=$db;hostname=$host", $user, $password, { RaiseError => 1 } ); return defined $dbh; } sub db_disconnect { $dbh->disconnect if $dbh; } sub db_select { my ( $select, $table, $where, $other ) = @_; my $sql = join ' ', ( SELECT => $select, FROM => $table, $where ? ( WHERE => $where ) : (), $other ? $other : (), ); my @r = $dbh->selectrow_array( $sql ); return wantarray ? @r : $r[ 0 ]; } sub db_update { my ( $table, $data, $where ) = @_; my $values = join ', ', map { my $field = $_; my $value = $data->{ $_ }; $value = $dbh->quote( $value ) unless $field =~ s/^-//; join ' = ', $field, $value; } keys %$data; my $sql = join ' ', ( UPDATE => $table, SET => $values, $where ? ( WHERE => $where ) : (), ); $dbh->do( $sql ); } # These are the mt defaults, probably best left alone my $mt_entry = 'mt_entry'; my $entry_created_on = 'entry_created_on'; my $entry_allow_comments = 'entry_allow_comments'; my $entry_allow_pings = 'entry_allow_pings'; my $close_comments_val = '2'; my $close_pings_val = '0'; GetOptions( 'h|help' => sub { pod2usage( -verbose => 1 ) }, 'man' => sub { pod2usage( -verbose => 2 ) }, 'n|dry-run|just-print' => \( my $opt_dry_run ), 't|trackbacks' => \( my $opt_trackbacks ), 'd|days=i' => \( my $opt_days_back = 15 ), 'db-type=s' => \( my $opt_db_type = 'mysql' ), 'db-host=s' => \( my $opt_db_host ), 'db-user=s' => \( my $opt_db_user ), 'db-pass=s' => \( my $opt_db_pass ), 'db-name=s' => \( my $opt_db_name ), ) or pod2usage(); pod2usage( -verbose => 1 ) unless $opt_db_host and $opt_db_user and $opt_db_pass and $opt_db_name; # this works in mysql, dunno about other mt databases. my $query_time = do { my $time = time() - ( $opt_days_back * 24 * 60 * 60 ); my ( $year, $month, $day ) = ( localtime $time )[ 5, 4, 3 ]; $year += 1900; $month++; join '', $year, $month, $day; }; db_connect( $opt_db_name, $opt_db_user, $opt_db_pass, $opt_db_host, $opt_db_type) or die "Unable to connect to $opt_db_name: $DBI::errstr\n"; if ( $opt_dry_run ) { my $count; $count = db_select( "count(*)", $mt_entry, "$entry_created_on < $query_time and $entry_allow_comments != $close_comments_val", ); warn "Would have updated $count entries to disallow comments.\n"; if ( $opt_trackbacks ) { $count = db_select( "count(*)", $mt_entry, "$entry_created_on < $query_time and $entry_allow_pings != $close_pings_val", ); warn "Would have updated $count entries to disallow trackbacks.\n"; } } else { db_update( $mt_entry, { $entry_allow_comments => $close_comments_val }, "$entry_created_on < $query_time" ); if ( $opt_trackbacks ) { db_update( $mt_entry, { $entry_allow_pings => $close_pings_val }, "$entry_created_on < $query_time" ); } } db_disconnect();