PowerCMS™
[ブログ] PowerCMS 6 でのアップデートまとめ を追加しました。
[新着情報] PHP 8.2 に対応した PowerCMS 6.5 の提供を開始 を追加しました。
[新着情報] PowerCMSクラウド の月額費用を、2024年7月1日より価格改定します を追加しました。
[新着情報] アルファサードのゴールデンウィーク休業について を追加しました。

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