<sect1 id="zend.loader.pluginloader">
    <title>Caricamento di plugin</title>

    <para>
        Diversi componenti del Framework Zend sono estendibili e permettono il caricamento dinamico di funzionalità specificando un prefisso di classe ed un percorso ai file contenenti le classi che non necessariamente rientra nei percorsi specificati in <code>include_path</code> o segue le convenzioni tradizionali sui nomi di classe.
        <code>Zend_Loader_PluginLoader</code> fornisce funzionalità comuni per quest'attività.
    </para>

    <para>
        L'utilizzo base di <code>PluginLoader</code> segue le convenzioni sui nomi di Zend Framework che prevedono una classe per file, utilizzando l'underscore "_" come carattere separatore delle cartelle nell'indicazione del percorso completo.
        Permette di specificare un prefisso opzionale per il nome delle classi da prependere nel controllo sul caricamento di una classe.
        In aggiunta, i percorsi sono cercati nell'ordine LIFO.
        La ricerca di tipo LIFO ed i prefissi di classe consentono di aggiungere namespace ai propri plugin e sovrascrivere plugin da percorsi registrati precedentemente.
    </para>

    <sect2 id="zend.loader.pluginloader.usage">
        <title>Esempio di utilizzo base</title>

        <para>
            Innanzi tutto, si assuma la seguente struttura di cartelle e file contenenti classi e che le cartelle application e library siano incluse in <code>include_path</code>:
        </para>

        <programlisting role="txt"><![CDATA[
application/
    modules/
        foo/
            views/
                helpers/
                    FormLabel.php
                    FormSubmit.php
        bar/
            views/
                helpers/
                    FormSubmit.php
library/
    Zend/
        View/
            Helper/
                FormLabel.php
                FormSubmit.php
                FormText.php
]]></programlisting>

        <para>
            Si crei ora un plugin loader per caricare tutti i metodi a supporto (helper) per le viste (view) disponibili:
        </para>

        <programlisting role="php"><![CDATA[<?php
$loader = new Zend_Loader_PluginLoader();
$loader->addPrefixPath('Zend_View_Helper', 'Zend/View/Helper/')
       ->addPrefixPath('Foo_View_Helper', 'application/modules/foo/views/helpers')
       ->addPrefixPath('Bar_View_Helper', 'application/modules/bar/views/helpers');
?>]]></programlisting>

        <para>
            Ora è possibile caricare un helper specifico utilizzando esclusivamente la porzione corrispondente al nome della classe dopo al prefisso così come specificato nell'aggiunta dei percorsi:
        </para>

        <programlisting role="php"><![CDATA[<?php
// load 'FormText' helper:
$formTextClass = $loader->load('FormText'); // 'Zend_View_Helper_FormText';

// load 'FormLabel' helper:
$formLabelClass = $loader->load('FormLabel'); // 'Foo_View_Helper_FormLabel'

// load 'FormSubmit' helper:
$formSubmitClass = $loader->load('FormSubmit'); // 'Bar_View_Helper_FormSubmit'
?>]]></programlisting>

        <para>
            Una volta che la classe è caricata, è possibile crearne una nuova istanza.
        </para>

        <note>
            <title>Registrazione di più percorsi per un prefisso</title>

            <para>
                In alcuni casi, è necessario utilizzare lo stesso prefisso per percorsi differenti.
                Attualmente <code>Zend_Loader_PluginLoader</code> registra un array di percorsi per ogni prefisso specificato; l'ultimo registrato è il primo ad essere controllato.
                Questa soluzione è particolarmente utile se si utilizzano componenti in incubator
                (NdT. la cartella contenente i moduli dello Zend Framework ancora in fase di sviluppo).
            </para>
        </note>

        <note>
            <title>E' possibile definire i percorsi in fase di creazione di un'istanza</title>

            <para>
                Opzionalmente è possibile fornire un array di coppie prefisso / percorso
                (o prefisso / percorsi -- sono ammessi più percorsi) come parametro del costruttore:
            </para>

            <programlisting role="php"><![CDATA[<?php
$loader = new Zend_Loader_PluginLoader(array(
    'Zend_View_Helper' => 'Zend/View/Helper/',
    'Foo_View_Helper'  => 'application/modules/foo/views/helpers',
    'Bar_View_Helper'  => 'application/modules/bar/views/helpers'
));
?>]]></programlisting>
        </note>

        <para>
            <code>Zend_Loader_PluginLoader</code> consente anche, opzionalmente, di condividere plugin tra diversi oggetti compatibili senza la necessità di utilizzare un'istanza singleton.
            Questo è possibile grazie ad un registro statico. Indicare il nome del registro in fase di creazione di una nuova istanza, come secondo parametro del costruttore:
        </para>

        <programlisting role="php"><![CDATA[<?php
// Store plugins in static registry 'foobar':
$loader = new Zend_Loader_PluginLoader(array(), 'foobar');
?>]]></programlisting>

        <para>
            Altri componenti che istanziano <code>PluginLoader</code> utilizzando lo stesso nome di registro avranno accesso a tutti i plugin e percorsi già caricati.
        </para>
    </sect2>

    <sect2 id="zend.loader.pluginloader.paths">
        <title>Manipolazione dei percorsi dei plugin</title>

        <para>
            L'esempio nella sezione precedente mostra come aggiungere percorsi al plugin loader.
            Come fare per determinare i percorsi già caricati, per rimuoverne uno o più?
        </para>

        <itemizedlist>
            <listitem><para>
                    <code>getPaths($prefix = null)</code> restituisce tutti i percorsi come coppie prefisso / percorso se non è fornito alcun <code>$prefix</code> oppure solo i percorsi registrati per un determinato prefisso se <code>$prefix</code> è presente.
            </para></listitem>

            <listitem><para>
                    <code>clearPaths($prefix = null)</code> rimuove tutti i percorsi predefiniti registrati oppure solo quelli associati ad un determinato prefisso se <code>$prefix</code> è disponibile e presente nella pila.
            </para></listitem>

            <listitem><para>
                    <code>removePrefixPath($prefix, $path = null)</code> permette di rimuovere selettivamente un percorso specifico associato ad un dato prefisso.
                    Se viene indicato <code>$path</code> ed il valore esiste per il dato prefisso, allora verrà rimosso solo quel percorso.
            </para></listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.loader.pluginloader.checks">
        <title>Verifica di plugin ed estrazione dei nomi delle classi</title>

        <para>
            Qualche volta è necessario determinare semplicemente se la classe di un plugin è stata caricata prima di eseguire un'azione.
            <code>isLoaded()</code> accetta il nome di un plugin e restituisce lo status.
        </para>

        <para>
            Un altro uso comune per <code>PluginLoader</code> è determinare i nomi completi delle classi dei plugin corrispondenti alle classi caricate; questa funzionalità è offerta da <code>getClassName()</code>.
            Tipicamente, la si utilizza insieme a <code>isLoaded()</code>:
        </para>

        <programlisting role="php"><![CDATA[<?php
if ($loader->isLoaded('Adapter')) {
    $class   = $loader->getClassName('Adapter');
    $adapter = call_user_func(array($class, 'getInstance'));
}
?>]]></programlisting>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
