<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="learning.plugins.usage">
    <title>Utilizando Plugins</title>

    <para>
        Componentes que fazem uso de plugins normalmente utilizam
        <classname>Zend_Loader_PluginLoader</classname>. Essa classe permite que você registre
        plugins especificando um ou mais "caminhos prefixados". O componente irá chamar ao método
        de PluginLoader <methodname>load()</methodname>, passando o nome abreviado do plugin.
        O PluginLoader irá consultar cada caminho prefixado para saber se existe uma classe
        correspondente. Os caminhos prefixados são procurados na ordem LIFO (last in, first
        out - último a entrar, primeiro a sair), e com isso, as correspondências ocorrerão
        primeiramente com os últimos caminhos registrados - o que possibilita a você substituir
        plugins já existentes.
    </para>

    <para>
        Os exemplos seguintes deixarão isso mais claro.
    </para>

    <example id="learning.plugins.usage.basic">
        <title>Exemplo básico de Plugin: Adicionando um caminho prefixado</title>

        <para>
            Neste exemplo, vamos supor que alguns validadores foram escritos e colocados no
            diretório <filename>foo/plugins/validators/</filename>, e que todas essas classes
            possuem o prefixo "Foo_Validate_"; essas duas partes de informação formam o
            "caminho prefixado".
            Além disso, vamos supor que temos dois validadores, um chamado "Par" (garantindo que
            um número seja par), e outro chamado "Dúzias" (garantindo que o número é um múltiplo
            de 12). A árvore terá esta aparência:
        </para>

        <programlisting language="text"><![CDATA[
foo/
|-- plugins/
|   |-- validators/
|   |   |-- Par.php
|   |   |-- Duzias.php
]]></programlisting>

        <para>
            Agora, vamos informar uma instância de <classname>Zend_Form_Element</classname>
            deste caminho prefixado. O método <methodname>addPrefixPath()</methodname> da classe
            <classname>Zend_Form_Element</classname> espera um terceiro argumento que indica
            o tipo de plugin para o qual o caminho está sendo registrado, neste caso, é um
            plugin "validador".
        </para>

        <programlisting language="php"><![CDATA[
$element->addPrefixPath('Foo_Validate', 'foo/plugins/validators/', 'validate');
]]></programlisting>

        <para>
            Agora podemos simplesmente informar ao elemento o nome abreviado dos validadores que
            queremos usar. No exemplo seguinte, usaremos uma mistura de validadores padrão
            ("NotEmpty", "Int") e validadores customizados ("Par", "Duzias"):
        </para>

        <programlisting language="php"><![CDATA[
$element->addValidator('NotEmpty')
        ->addValidator('Int')
        ->addValidator('Par')
        ->addValidator('Duzias');
]]></programlisting>

        <para>
            Quando o elemento demanda validação, requisitará a classe de plugin através do
            PluginLoader. Os dois primeiros validadores serão
            <classname>Zend_Validate_NotEmpty</classname> e
            <classname>Zend_Validate_Int</classname>, respectivamente; os dois seguintes serão
            <classname>Foo_Validate_Par</classname> e <classname>Foo_Validate_Duzias</classname>,
            respectivamente.
        </para>
    </example>

    <note>
        <title>O que acontece caso um plugin não seja encontrado?</title>

        <para>
            O que acontece se um plugin é solicitado, mas o PluginLoader é incapaz de encontrar
            uma classe correspondente? Por exemplo, no exemplo acima, se registrássemos o plugin
            "Bar", com o elemento, o que aconteceria?
        </para>

        <para>
            O carregador de plugin irá procurar em cada caminho prefixado, verificando se há um
            arquivo correspondente ao nome do plugin. Se o arquivo não for encontrado, ele passa
            ao próximo caminho prefixado.
        </para>

        <para>
            Uma vez que a pilha de caminhos prefixados tenha se esgotado, caso nenhum arquivo
            tenha sido encontrado, será gerada uma exceção
            <exceptionname>Zend_Loader_PluginLoader_Exception</exceptionname>.
        </para>
    </note>

    <example id="learning.plugins.usage.override">
        <title>Uso Intermediário do Plugin: Sobrescrevendo plugins existentes</title>

        <para>
            Uma característica do PluginLoader é que seu uso da pilha LIFO permite sobrescrever
            plugins existentes, criando sua própria versão localmente com um caminho prefixado
            diferente e registrá-lo mais tarde na pilha.
        </para>

        <para>
            Por exemplo, vamos considerar <classname>Zend_View_Helper_FormButton</classname>
            (auxiliares de visualização - view helpers - são um tipo de plugin). Esse auxiliar de
            visualização aceita três argumentos, um nome de elemento (também usado como seu
            identificador DOM), um valor (usado como o rótulo do botão) e um vetor opcional de
            atributos. O auxiliar gera marcação <acronym>HTML</acronym> para um elemento de
            inserção em formulário.
        </para>

        <para>
            Digamos que você deseja que o auxiliar, ao invés de gerar um elemento
            <constant>button</constant> em <acronym>HTML</acronym>; não quer que o auxiliar
            gere um identificador DOM, mas sim utilizar o valor para um seletor de classe em CSS;
            sem interesse em manipular atributos arbitrários.
            Você pode fazer isso de algumas maneiras. Em todos os casos, você criaria sua própria
            classe "auxiliar de visualização" que implementa o comportamento desejado;
            a diferença está em como você iria nomeá-los e chamá-los.
        </para>

        <para>
            Nosso primeiro exemplo será o de nomear o elemento com um nome único:
            <classname>Foo_View_Helper_CssButton</classname>, o que implica no nome do plugin
            "CssButton". Embora isso seja uma abordagem viável, apresenta várias questões: caso
            você já tenha utilizado o auxiliar de visualização Button, você terá que refatorar;
            em outro caso, se outro desenvolvedor começar a escrever código para a sua aplicação,
            pode inadvertidamente usar o auxiliar de visualização Button em vez de seu novo
            auxiliar.
        </para>

        <para>
            Então, o melhor exemplo é usar o plugin de nome "Button", ficando o nome da classe
            como <classname>Foo_View_Helper_Button</classname>. Em seguida, registrar o caminho
            prefixado com a visualização (view):
        </para>

        <programlisting language="php"><![CDATA[
// Zend_View::addHelperPath() utiliza o PluginLoader; entretanto, inverte
// os argumentos e fornece o valor padrão de "Zend_View_Helper" para o
// prefixo de plugin.
//
// O código abaixo assume que sua classe está no diretório 'foo/view/helpers/'.
$view->addHelperPath('foo/view/helpers', 'Foo_View_Helper');
]]></programlisting>

        <para>
            Uma vez feito, em qualquer lugar que utilizar o auxiliar "Button" irá direcionar para
            a sua classe <classname>Foo_View_Helper_Button</classname> customizada!
        </para>
    </example>
</sect1>
