<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 15156 -->
<sect1 id="zend.form.standardDecorators">
    <title>Zend Framework に同梱されている標準のデコレータ</title>

    <para>
        <classname>Zend_Form</classname> には、標準でいくつかのデコレータが組み込まれています。
        デコレータの一般的な使用法については <link
            linkend="zend.form.decorators">デコレータの説明</link>
        を参照ください。
    </para>

    <sect2 id="zend.form.standardDecorators.callback">
        <title>Zend_Form_Decorator_Callback</title>

        <para>
            Callback デコレータは、コンテンツをレンダリングする際に任意のコールバックを実行します。
            コールバックは、デコレータのオプション 'callback' で指定します。
            PHP のコールバック型の値を指定することができます。
            指定するコールバックは、3 つの引数
            <code>$content</code> (デコレータに渡されたコンテンツ)、
            <code>$element</code> (処理する項目)、
            <code>$options</code> (オプションの配列)
            を受け取るものでなければなりません。
            コールバックの例は、次のようになります。
        </para>

        <programlisting role="php"><![CDATA[
class Util
{
    public static function label($content, $element, array $options)
    {
        return '<span class="label">' . $element->getLabel() . "</span>";
    }
}
]]></programlisting>

        <para>
            このコールバックは <code>array('Util',
                'label')</code> のように指定します。
            そして、ラベル用の (間違った) HTML マークアップを生成します。
            Callback デコレータはコンテンツの内容を書き換えることもできますし、
            コンテンツの前後に文字列を追加することもできます。
        </para>

        <para>
            Callback デコレータの placement オプションに null 値を指定すると、
            元のコンテンツをコールバックの返り値で上書きします。
            'prepend' や 'append' を指定した場合も正しく動作します。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.captcha">
        <title>Zend_Form_Decorator_Captcha</title>

        <para>
            Captcha デコレータは <link
                linkend="zend.form.standardElements.captcha">CAPTCHA
                フォーム要素</link> と組み合わせて使用します。
            これは、CAPTCHA アダプタの
            <code>render()</code> メソッドを使用して出力を生成します。
        </para>

        <para>
            Captcha デコレータの別版である 'Captcha_Word' もよく用いられます。
            これは id と input のふたつの要素を作成します。
            id は比較対象のセッション識別子、そして input は
            CAPTCHA のユーザ入力を表します。
            これらは単一の要素として検証されます。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.description">
        <title>Zend_Form_Decorator_Description</title>

        <para>
            Description デコレータは
            <classname>Zend_Form</classname>、<classname>Zend_Form_Element</classname>
            あるいは <classname>Zend_Form_DisplayGroup</classname> の説明を表示します。
            説明は、各オブジェクトの <code>getDescription()</code>
            メソッドで取得します。
            各要素の操作説明を提供するためなどに使用します。
        </para>

        <para>
            デフォルトでは、説明が存在しない場合は何も出力を生成しません。
            説明が存在する場合は、デフォルトではそれを HTML の
            <code>p</code> タグで囲んで表示します。このタグを変更するには、
            デコレータを作成する際にオプション <code>tag</code>
            を渡すか、あるいは <code>setTag()</code> をコールします。
            さらに、そのタグにクラスを指定することもできます。これは、オプション
            <code>class</code> あるいはメソッド
            <code>setClass()</code> で指定します。
            デフォルトで使用するクラスは 'hint' です。
        </para>

        <para>
            説明は、デフォルトでビューオブジェクトのエスケープ機構を使って
            エスケープされます。これを無効にするには、デコレータのオプション
            'escape' に <code>false</code> を渡すか、あるいは
            <code>setEscape()</code> メソッドをコールします。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.dtDdWrapper">
        <title>Zend_Form_Decorator_DtDdWrapper</title>

        <para>
            デフォルトのデコレータで、フォームの要素を定義リスト
            (<code>&lt;dl&gt;</code>) を用いて装飾します。
            フォームの項目は任意の順序であらわれるので、
            表示グループやサブフォームがその他のフォーム項目の中に点在することがあり得ます。
            表示グループやサブフォームなどの特定の項目を定義リスト内でも保持するために、
            DtDdWrapper は新しい空の用語定義 (<code>&lt;dt&gt;</code>)
            を作成し、コンテンツを新しい定義データ (<code>&lt;dd&gt;</code>)
            としてラップします。出力は、次のようになります。
        </para>

        <programlisting role="html"><![CDATA[
<dt></dt>
<dd><fieldset id="subform">
    <legend>User Information</legend>
    ...
</fieldset></dd>
]]></programlisting>

        <para>
            このデコレータは、元のコンテンツを上書きし、
            <code>&lt;dd&gt;</code> 要素でラップしたもので置き換えます。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.errors">
        <title>Zend_Form_Decorator_Errors</title>

        <para>
            要素のエラーを処理するのが Errors デコレータです。
            このデコレータは FormErrors ビューヘルパーへのプロキシとなり、
            エラーメッセージを順序なしリスト
            (<code>&lt;ul&gt;</code>) にレンダリングします。
            <code>&lt;ul&gt;</code> 要素のクラスは "errors" となります。
        </para>

        <para>
            Errors デコレータは、元のコンテンツの先頭あるいは末尾に文字列を追加します。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.fieldset">
        <title>Zend_Form_Decorator_Fieldset</title>

        <para>
            グループやサブフォームの内容を、デフォルトで fieldset
            の中にレンダリングします。
            Fieldset デコレータは、オプション 'legend'
            の内容あるいは要素の <code>getLegend()</code> メソッドの内容を確認し、
            何かが指定されていればそれを legend として使用します。
            渡されたコンテンツは HTML の fieldset でラップされ、
            その内容で元のコンテンツを上書きします。
            元の項目に設定されていた属性は、すべて fieldset
            の HTML 属性として設定されます。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.file">
        <title>Zend_Form_Decorator_File</title>

        <para>
            File 要素には特殊な記法があり、
            複数の file 要素やサブフォームを利用する際にそれを使用します。
            File デコレータは <classname>Zend_Form_Element_File</classname>
            が使用するもので、複数の file 要素を一度のメソッドコールで設定することができます。
            自動的に使用され、要素名を自動的に修正します。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.form">
        <title>Zend_Form_Decorator_Form</title>

        <para>
            <classname>Zend_Form</classname> オブジェクトは HTML の form タグをレンダリングするものです。
            Form デコレータは Form ビューヘルパーへのプロキシとなります。
            これは、渡されたコンテンツを HTML の form 要素でラップします。
            その際に <classname>Zend_Form</classname> オブジェクトの action や method、
            そして属性を使用します。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.formElements">
        <title>Zend_Form_Decorator_FormElements</title>

        <para>
            フォームや表示グループ、サブフォームはいくつかの要素のコレクションです。
            これらの要素をレンダリングする際には FormElements デコレータを使用します。
            これは、各構成要素を順次処理して個別に <code>render()</code>
            をコールし、登録されている区切り文字で結果を連結します。
            このデコレータは、元のコンテンツの先頭あるいは末尾に文字列を追加します。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.formErrors">
        <title>Zend_Form_Decorator_FormErrors</title>

        <para>
            開発者やデザイナの中には、
            すべてのエラーメッセージをフォームの最上部にまとめて表示させることを好む人もいます。
            FormErrors デコレータは、そのためのものです。
        </para>

        <para>
            デフォルトでは、生成されるエラー一覧は次のようなマークアップになります。
        </para>

        <programlisting role="html"><![CDATA[
<ul class="form-errors>
    <li><b>[要素の label あるいは name]</b><ul>
            <li>[エラーメッセージ]</li>
            <li>[エラーメッセージ]</li>
        </ul>
    </li>
    <li><ul>
        <li><b>[サブフォーム要素の label あるいは name</b><ul>
                <li>[エラーメッセージ]</li>
                <li>[エラーメッセージ]</li>
            </ul>
        </li>
    </ul></li>
</ul>
]]></programlisting>

        <para>
            さまざまなオプションを渡すことで、生成される出力を変更することができます。
        </para>

        <itemizedlist>
            <listitem><para>
                <code>ignoreSubForms</code>: サブフォームの再帰を無効にするかどうか。
                デフォルト値: false (再帰を許可する)
            </para></listitem>

            <listitem><para>
                <code>markupElementLabelEnd</code>: 要素のラベルの後につけるマークアップ。
                デフォルト値: '&lt;/b&gt;'
            </para></listitem>

            <listitem><para>
                <code>markupElementLabelStart</code>: 要素のラベルの前につけるマークアップ。
                デフォルト値: '&lt;b&gt;'
            </para></listitem>

            <listitem><para>
                <code>markupListEnd</code>: エラーメッセージ一覧の後につけるマークアップ。
                デフォルト値: '&lt;/ul&gt;'
            </para></listitem>

            <listitem><para>
                <code>markupListItemEnd</code>: 個々のエラーメッセージの後につけるマークアップ。
                デフォルト値: '&lt;/li&gt;'
            </para></listitem>

            <listitem><para>
                <code>markupListItemStart</code>: 個々のエラーメッセージの前につけるマークアップ。
                デフォルト値: '&lt;li&gt;'
            </para></listitem>

            <listitem><para>
                <code>markupListStart</code>: エラーメッセージ一覧の前につけるマークアップ。
                デフォルト値: '&lt;ul class="form-errors"&gt;'
            </para></listitem>
        </itemizedlist>

        <para>
            FormErrors デコレータは、コンテンツの前と後の両方に追加することができます。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.htmlTag">
        <title>Zend_Form_Decorator_HtmlTag</title>

        <para>
            HtmlTag デコレータは、HTML タグを使ってコンテンツを装飾します。
            使用するタグを 'tag' オプションで指定します。
            それ以外に指定したオプションは、そのタグの属性として用いられます。
            デフォルトのタグはブロックレベルのものであり、
            指定したタグでコンテンツをラップして元のコンテンツを上書きします。
            しかし、placement に append あるいは prepend を指定することもできます。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.image">
        <title>Zend_Form_Decorator_Image</title>

        <para>
            Image デコレータは、HTML の image input
            (<code>&lt;input type="image" ... /&gt;</code>)
            を作成し、オプションでそれを他の HTML タグの中にレンダリングします。
        </para>

        <para>
            デフォルトでは、このデコレータは要素の src プロパティを使用します。
            これは、<code>setImage()</code> で画像ソースとして指定することができます。
            さらに、要素のラベルは alt タグとして使用します。また
            <code>imageValue</code> (Image 要素のアクセサ
            <code>setImageValue()</code> および
            <code>getImageValue()</code> で操作します)
            を値として使用します。
        </para>

        <para>
            この要素をラップする HTML タグを指定するには、デコレータのオプション
            'tag' を指定するか、あるいは <code>setTag()</code> をコールします。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.label">
        <title>Zend_Form_Decorator_Label</title>

        <para>
            フォーム要素には通常ラベルがあります。Label
            デコレータは、このラベルをレンダリングするものです。
            FormLabel ビューヘルパーへのプロキシとして働き、
            要素の <code>getLabel()</code> メソッドを使用してラベルを取得します。
            ラベルが存在しない場合は、何もレンダリングしません。
            デフォルトでは、翻訳アダプタが存在して
            ラベルの翻訳が存在する場合には、ラベルの翻訳を行います。
        </para>

        <para>
            オプション 'tag' を指定することもできます。
            指定した場合は、そのブロックレベルタグでラベルをラップします。
            'tag' が指定されているがラベルが存在しないという場合は、
            指定したタグを中身なしでレンダリングします。
            このタグにクラスを指定するには、オプション 'class'
            を指定するか、あるいは <code>setClass()</code> をコールします。
        </para>

        <para>
            さらに、要素の表示の際に使用するプレフィックスおよびサフィックスを指定することもできます。
            これは、任意要素のラベルか必須要素のラベルかを表す際などに使用します。
            一般的な使用法は、ラベルの最後に ':' を追加したり
            必須項目に '*' を追加したりといったものです。
            次のようなオプションやメソッドを使用します。
        </para>

        <itemizedlist>
            <listitem><para>
                    <code>optionalPrefix</code>:
                    その要素がオプション要素である場合にラベルの先頭に付加するテキストを設定します。
                    <code>setOptionalPrefix()</code> および
                    <code>getOptionalPrefix()</code> で操作します。
            </para></listitem>

            <listitem><para>
                    <code>optionalSuffix</code>:
                    その要素がオプション要素である場合にラベルの末尾に付加するテキストを設定します。
                    <code>setOptionalSuffix()</code> および
                    <code>getOptionalSuffix()</code> で操作します。
            </para></listitem>

            <listitem><para>
                    <code>requiredPrefix</code>:
                    その要素が必須要素である場合にラベルの先頭に付加するテキストを設定します。
                    <code>setRequiredPrefix()</code> および
                    <code>getRequiredPrefix()</code> で操作します。
            </para></listitem>

            <listitem><para>
                    <code>requiredSuffix</code>:
                    その要素が必須要素である場合にラベルの末尾に付加するテキストを設定します。
                    <code>setRequiredSuffix()</code> および
                    <code>getRequiredSuffix()</code> で操作します。
            </para></listitem>
        </itemizedlist>

        <para>
            デフォルトでは、Label デコレータは元のコンテンツの先頭に結果を追加します。
            'placement' オプションを 'append' にすると、
            コンテンツの末尾に追加することができます。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.prepareElements">
        <title>Zend_Form_Decorator_PrepareElements</title>

        <para>
            フォーム、表示グループそしてサブフォームは、要素のコレクションです。
            <link
                linkend="zend.form.standardDecorators.viewScript">ViewScript</link>
            デコレータをフォームやサブフォームで使用する際に、
            ビューオブジェクトやトランスレータ、完全修飾名
            (サブフォームの配列記法で定義されるもの) を再帰的に設定できたら便利です。
            'PrepareElements' デコレータはそのためのものです。
            一般的には、これをリスト内の最初のデコレータとして設定します。
        </para>

        <programlisting role="php"><![CDATA[
$form->setDecorators(array(
    'PrepareElements',
    array('ViewScript', array('viewScript' => 'form.phtml')),
));
]]></programlisting>
    </sect2>

    <sect2 id="zend.form.standardDecorators.viewHelper">
        <title>Zend_Form_Decorator_ViewHelper</title>

        <para>
            大半の要素のレンダリングには <classname>Zend_View</classname>
            ヘルパーを使用します。これを行うのが ViewHelper デコレータです。
            このデコレータでは、'helper' タグで明示的にビューヘルパーを指定することができます。
            指定しなかった場合は、要素のクラス名の最後の部分をもとに使用するヘルパーを決定します。
            この最後の部分の先頭に 'form' をつけたものを使います。
            たとえば 'Zend_Form_Element_Text' の場合は 'formText'
            というビューヘルパーを探すことになります。
        </para>

        <para>
            渡された要素のすべての属性は、要素の属性としてビューヘルパーに渡されます。
        </para>

        <para>
            デフォルトでは、このデコレータはコンテンツの末尾に結果を追加します。
            'placement' オプションを指定すれば、先頭に追加させることもできます。
        </para>
    </sect2>

    <sect2 id="zend.form.standardDecorators.viewScript">
        <title>Zend_Form_Decorator_ViewScript</title>

        <para>
            ビュースクリプトを使用して要素を作成したくなることもあるでしょう。
            これにより、作成する要素をよりきめ細やかに設定できるようになります。
            またビュースクリプトでデザインを行ったり
            使用するモジュールにあわせて設定を簡単にオーバーライドしたりできるようになります
            (各モジュールで、要素のビュースクリプトを必要に応じてオーバーライドすることができます)。
            ViewScript デコレータが、この問題を解決します。
        </para>

        <para>
            ViewScript デコレータには 'viewScript' オプションが必須です。
            これは、デコレータ側で指定するか、あるいは要素の属性で指定します。
            そのビュースクリプトをパーシャルスクリプトとしてレンダリングします。
            各コールごとに独自の変数スコープを保持するので、
            その要素の変数以外にビューからの変数が注入されることはありません。
            いくつかの変数が設定されます。
        </para>

        <itemizedlist>
            <listitem><para>
                    <code>element</code>: デコレートする要素の名前
            </para></listitem>

            <listitem><para>
                    <code>content</code>: デコレータに渡されたコンテンツ
            </para></listitem>

            <listitem><para>
                    <code>decorator</code>: デコレータオブジェクト自身
            </para></listitem>

            <listitem><para>
                    さらに、デコレータに <code>setOptions()</code>
                    で渡されたすべてのオプションのうち内部的に使用しないもの
                    (placement や　separator など) は、
                    ビュースクリプトにビュー変数として渡されます。
            </para></listitem>
        </itemizedlist>

        <para>
            例として、次のような要素を考えてみましょう。
        </para>

        <programlisting role="php"><![CDATA[
// 要素のデコレータとして、ViewScript デコレータを指定し、
// ビュースクリプトとその他のオプションを設定します
$element->setDecorators(array(array('ViewScript', array(
    'viewScript' => '_element.phtml',
    'class'      => 'form element'
))));

// あるいはビュースクリプトを要素の属性として指定します
$element->viewScript = '_element.phtml';
$element->setDecorators(array(array('ViewScript',
                                    array('class' => 'form element'))));
]]></programlisting>

        <para>
            そして、次のようなビュースクリプトを作成します
        </para>

        <programlisting role="php"><![CDATA[
<div class="<?php echo $this->class ?>">
    <?php echo $this->formLabel($this->element->getName(),
                         $this->element->getLabel()) ?>
    <?php echo $this->{$this->element->helper}(
        $this->element->getName(),
        $this->element->getValue(),
        $this->element->getAttribs()
    ) ?>
    <?php echo $this->formErrors($this->element->getMessages()) ?>
    <div class="hint"><?php echo $this->element->getDescription() ?></div>
</div>
]]></programlisting>

        <note>
            <title>ビュースクリプトによるコンテンツの置換</title>

            <para>
                デコレータに渡されたコンテンツをビュースクリプトで置換したいこともあるでしょう。
                たとえばコンテンツをラップしたい場合などです。
                その場合は、デコレータのオプション 'placement'
                に false を設定します。
            </para>

            <programlisting role="php"><![CDATA[
// デコレータの作成時
$element->addDecorator('ViewScript', array('placement' => false));

// 既存のデコレータインスタンスへの適用
$decorator->setOption('placement', false);

// 既に要素にアタッチされているデコレータへの適用
$element->getDecorator('ViewScript')->setOption('placement', false);

// デコレータが使用するビュースクリプト内
$this->decorator->setOption('placement', false);
]]></programlisting>
        </note>

        <para>
            ViewScript デコレータは、
            要素のレンダリングをよりきめ細やかに設定したい場合に使用することをおすすめします。
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 tw=80 et:
-->
