PowerCMS™
2025年1月1日購入分よりライセンスの価格を改定いたします。
[ブログ] PowerCMS 6 でのアップデートまとめ を追加しました。
[よくあるご質問] スマートフォンでは使えない機能がありますか? を追加しました。
[事例紹介] 株式会社BOTAO様 / 公益社団法人 地域医療振興協会 を追加しました。

PowerCMS ブログ

ホーム > PowerCMS ブログ > プラグイン > 細かすぎて伝わらない FieldIsNotEmpty プラグインの実装

2015年02月19日

細かすぎて伝わらない FieldIsNotEmpty プラグインの実装

先日の記事で、

<MTEntries field:entryenglishtitle="IS NOT EMPTY">

を実現するプラグインを紹介しました。

通常、field:foo モディファイアはカスタムフィールドの値でフィルタするのに使われるので「IS NOT EMPTY」のような条件を指定することはできません。プラグインによってこれが可能になっているのは、field:foo モディファイアに「IS NOT EMPTY」が指定されたらこういう処理をする、ということが定義されているからです。

MTEntries は MT 本体のタグなので、当然その処理は MT によって定義されています。もちろん MT のソースコードを書き換えればできますが、それではサポートを受けられなくなってしまいます。また、モディファイア field:foo の動作だけをカスタマイズできればよいので、大筋の処理を変更する必要はありません。


こういった状況で MTEntries タグの動作をカスタマイズする場合、config.yaml に以下のように既述します。

tags:
    block:
        Entries: >
            sub {
                # テンプレートタグの処理
            }

MT タグを定義するプラグインを作成した経験がある場合「これだと MT 本体の MTEntries をまるごと上書きすることになる」と考えるかもしれません。

しかし、MT タグを処理する MT::Template::Context には、super_handler というメソッドがあります。config.yaml に定義した MTEntries の処理の中でこのメソッドを実行することで MT 本体の MTEntries の処理が呼ばれる仕組みです。ある程度プログラミングの経験があれば、super と聞いたときにサイヤ人よりも継承が思い浮かぶでしょう。サイヤ人が思い浮かんだとしても、それはそれでかまいません。

tags:
    block:
        Entries: >
            sub {
                my ( $ctx, $args, $cond ) = @_;
                # field:foo をごにょごにょする処理
                defined( my $result = $ctx->super_handler( $args, $cond ) )
                    or return $ctx->error( $ctx->errstr );
                return $result;
            }

この方法は MultiBlog プラグインが IncludeBlogs などのモディファイアを定義する用途にも利用されています。もちろんこの方法を新たなプラグインで定義しても、MultiBlog の処理も反映されます。


残すは field.foo をごにょごにょする処理です。

テンプレートタグの記述でモディファイアに指定した値はそのまま MTEntires の処理内で load 条件に渡されます。以下の処理内の $val が該当です。

        if (%fields) {

            # specifies we need a join with entry_meta;
            # for now, we support one join
            my ( $col, $val ) = %fields;
            my $type = MT::Meta->metadata_by_name( $class, 'field.' . $col );
            $args{join} = [
                $class->meta_pkg,
                undef,
                {   type          => 'field.' . $col,
                    $type->{type} => $val,
                    'entry_id'    => \'= entry_id'
                }
            ];
        }

$val にハッシュリファレンスで { not => '' } を渡せばカスタムフィールドの値が「空でない」を実現できます。しかしハッシュリファレンスというのはあくまでも Perl 処理内でのデータの形ですし、当然ですが MT タグの記述としてはモディファイアにはテキストしか記述できません。 そこで、値がテキスト「IS NOT EMPTY」の場合はハッシュリファレンス { not => '' } に変換してやればよいわけです。

できあがったものはこんな感じです。

tags:
    block:
        Entries: >
            sub {
                my ( $ctx, $args, $cond ) = @_;
                foreach my $arg ( keys %$args ) {
                    # field:foo をごにょごにょしている処理
                    if ( $arg =~ m/^field:./ ) {
                        if ( $args->{ $arg } eq 'IS NOT EMPTY' ) {
                            $args->{ $arg } = { not => '' };
                        }
                    }
                }
                defined( my $result = $ctx->super_handler( $args, $cond ) )
                    or return $ctx->error( $ctx->errstr );
                return $result;
            }

ダイナミックパブリッシングでも類似の処理を行うことができます。これについては後日紹介します。


カテゴリー
プラグイン
技術情報

Recent Entries