元フリーエンジニアライフ

Ruby on Rails とか MovableType とかAWSやってるフリーランスウェブエンジニアの記録でした。現在は法人成りしてIT社長。

MTのデータベース中の文字列を一括置換するスクリプト

SQLだとこんなかんじで・・・

UPDATE mt_entry SET entry_text=REPLACE(entry_text, "http://takeyu-web.com/", "/") WHERE entry_text IS NOT NULL;

カスタムフィールド(複数行テキスト)だったらこんな感じで・・・

UPDATE mt_entry_meta SET entry_meta_vclob=REPLACE(entry_meta_vclob, "http://takeyu-web.com/", "/") WHERE entry_meta_vclob IS NOT NULL;

カスタムフィールドのデータがどのカラムに入っているのかは藤本さんのこの記事あたりをどうぞ。→カスタムフィールドの型を変える(その1)

素人でもただ実行するだけで置換できる状態で渡すのであれば、MTのデータベースで任意のSQLを実行する方法と、SQLでの置換のやり方をしっていれば簡単。こんなかんじ。

MT_DIR/tools/path_replace.pl

#!/usr/bin/env perl

# データベース中に含まれる http://takeyu-web.com/ を / に置換

use strict;
use utf8;

use strict;
use warnings;

use lib $ENV{MT_HOME} ? "$ENV{MT_HOME}/lib" : 'lib';

use Data::Dumper;

use MT;
use MT::Util;

use Getopt::Long;
use Pod::Usage;
GetOptions(
    "config=s" => \my ( $cfg )
);

$cfg = 'mt-config.cgi' unless defined $cfg;
my $app = new MT(($cfg ? ('Config' => $cfg) : ())) or die MT->errstr;
$app->run_callbacks( 'init_app', $app );

require MT::Object;

sub find_by_sql {
    my ( $sql, $bind_values ) = @_;
    die unless $sql;
    $bind_values ||= [];

    my @result_set;

    require MT::Object;
    my $driver = MT::Object->driver;
    my $dbh = $driver->rw_handle;
    my $sth = $dbh->prepare( $sql );
    die $dbh->errstr if $dbh->errstr;
    $sth->execute( @$bind_values );
    die $sth->errstr if $sth->errstr;

    my @row;
    my $column_names = $sth->{ NAME_hash };
    my @next_row;
    @next_row = $sth->fetchrow_array();
    while ( @next_row ) {
        @row = @next_row;
        my $result = {};
        foreach my $column_name ( keys %$column_names ) {
            my $idx = $column_names->{ $column_name };
            $result->{ $column_name } = $row[ $idx ];
        }
        push @result_set, $result;

        @next_row = $sth->fetchrow_array();
    }
    $sth->finish();

    return wantarray ? @result_set : scalar \@result_set;
}

sub replace {
    my ( $tbl, $col, $target, $replace ) = @_;
    find_by_sql( "UPDATE @{[ $tbl ]} SET @{[ $col ]}=REPLACE (@{[ $col ]}, ?, ?) WHERE @{[ $col ]} IS NOT NULL;", [ $target, $replace ] )
}

MT::Object->begin_work;
eval {
    # ブログ記事・ウェブページ本文
    replace( 'mt_entry', 'entry_text', 'http://takeyu-web.com/', '/' );
    # ブログ記事・ウェブページ続き
    replace( 'mt_entry', 'entry_text_more', 'http://takeyu-web.com/', '/' );
    # ブログ記事・ウェブページカスタムフィールド(1行など)
    replace( 'mt_entry_meta', 'entry_meta_vchar_idx', 'http://takeyu-web.com/', '/' );
    # ブログ記事・ウェブページカスタムフィールド(テキスト複数行など)
    replace( 'mt_entry_meta', 'entry_meta_vclob', 'http://takeyu-web.com/', '/' );
};
if ( my $errstr = $@ ) {
    MT::Object->rollback;
    die $errstr;
} else {
    MT::Object->commit;
}


1;

replace( 'mt_entry', 'entry_text', 'http://takeyu-web.com/', '/' );のあたりを便宜変更すれば良いと思います。コマンドラインオプションにしてもいいけど・・・実行が怖いです。

dumpをとってからやりましょう。