PowerCMS ブログ

2016年01月22日

もしもテンプレートの検索・置換でテンプレートを壊してしまった時は

MT、PowerCMSでテンプレートの検索・置換使っていますか? このような機能を使うときはデータベースのバックアップ必須ですよね? でもついつい安易に実行してしまうようなケースはないでしょうか。同じように逆パターンに再検索・置換できるケースならまだ良いのですが、できない場合頭を抱えてしまうことになります。

テンプレートの検索・置換画面

そんな時は以下のようなスクリプトを書いて MTの toolsディレクトリに設置して実行することで更新履歴から直前のものに戻すことができます。以下の例は検索・置換対象かどうかを考慮していませんので、実際は必要なテンプレートをもう少し指定してやる必要があります。


#!/usr/bin/perl
package MT::Tool::RevertToThePrevious;
use strict;
use warnings;
use File::Spec;
use FindBin;
use lib map File::Spec->catdir( $FindBin::Bin, File::Spec->updir, $_ ),
                                qw/lib extlib/;
use base qw( MT::Tool );

sub usage { '--debug 1' }

sub help {
    return q {
        --debug 1
    };
}

my ( $debug );

sub options {
    return (
        'debug=s'   => \$debug,
    );
}

sub main {
    my $class = shift;
    my ( $verbose ) = $class->SUPER::main( @_ );
    my $iter = MT->model( 'template' )->load_iter( { blog_id => { not => 0 },
                                                     type => { not => 'backup' } } );
    while (my $template = $iter->()) {
        my $current_revision = $template->current_revision;
        next unless $current_revision;
        $current_revision--;
        my $rev_new = _load_revision( $template,
                    { rev_number => $current_revision } );
        next unless $rev_new;
        my $obj_new = $rev_new->[ 0 ];
        my $text = $obj_new->text;
        if ( $text ) {
            $template->text( $text );
            $template->save or die $template->errstr;
        }
    }
    1;
}

sub _load_revision {
    my ( $obj, $terms, $args ) = @_;
    my $datasource = $obj->datasource;
    my $rev_class  = MT->model( $datasource . ':revision' );
    # Only specified a rev_number
    if ( defined $terms && ref $terms ne 'HASH' ) {
        $terms = { rev_number => $terms };
    }
    $terms->{ $datasource . '_id' } ||= $obj->id;
    if ( wantarray ) {
        my @rev = map { _object_from_revision( $obj, $_ ); }
            $rev_class->load( $terms, $args );
        unless ( @rev ) {
            return $obj->error( $rev_class->errstr );
        }
        return @rev;
    } else {
        my $rev = $rev_class->load( $terms, $args )
            or return $obj->error( $rev_class->errstr );
        my $array = _object_from_revision( $obj, $rev );
        return $array;
    }
}

sub _object_from_revision {
    my ( $obj, $rev ) = @_;
    my $datasource = $obj->datasource;
    my $rev_obj = $obj->clone;
    my $serialized_obj = $rev->$datasource;
    require MT::Serialize;
    my $packed_obj = MT::Serialize->unserialize($serialized_obj);
    $rev_obj->unpack_revision($$packed_obj);
    $rev_obj->modified_by( $rev->created_by );
    $rev_obj->modified_on( $rev->modified_on );
    my @changed = split ',', $rev->changed;
    return [ $rev_obj, \@changed, $rev->rev_number, $rev ];
}

__PACKAGE__->main() unless caller;

検索・置換ログ

どのテンプレートが検索・置換されたかどうかはログを見ればわかります。特定のテンプレートを id指定で処理する場合、コードを下記のようにカスタマイズします。


    my @ids = qw/ 1 2 3 4 /;
    my $iter = MT->model( 'template' )->load_iter( { id => \@ids } );

あ、このようなスクリプトを実行するときは必ずバックアップを取ってから、且つ自己責任でお願いします。バックアップ重要ですね。

カテゴリー
サイト制作全般サポートトラブルシューティング技術情報

ページの先頭へ