wiki:WF/ExtendendoaSmartycomPlugins

A Versão 2.0 introduziu a arquitetura de plugin que é usada para quase todas as funcionalidades customizáveis da Smarty. Isto inclui:

  • funções
  • modificadores
  • funções de bloco
  • funções de compilador
  • prefiltros
  • posfiltros
  • filtros de saída
  • recursos
  • inserir

Com a exceção de recursos, a compatibilidade com a forma antiga de funções de manipulador de registro via register_* API é preservada. Se você não usou o API mas no lugar disso modificou as variáveis de classe $custom_funcs, $custom_mods, e outras diretamente, então você vai precisar ajustar seus scripts para ou usar API ou converter suas funcionalidade customizadas em plugins.

Como os Plugins Funcionam


Plugins são sempre lidos quando requisitados. Apenas os modificadores específicos, funções, recursos, etc convocados em scripts de template serão lidos. Além disso, cada plugin é lido apenas uma vez, mesmo se você tem várias instâncias diferentes da Smarty rodando na mesma requisição.

Pre/posfiltros e filtros de saída são uma parte de um caso especial. Visto que eles não são mencionados nos templates, eles devem ser registrados ou lidos explicitamente via funções de API antes do template ser processado. A ordem em que multiplos filtros do mesmo tipo são executados dependem da ordem em que eles são registrados ou lidos.

O diretório de plugins pode ser uma string contendo um caminho ou um array contendo multiplos caminhos. Para instalar um plugin, simplesmente coloque-o em um dos diretórios e a Smarty irá usá-lo automaticamente.

Convenções de Aparência


Arquivos e funções de Plugin devem seguir uma convenção de aparência muito específica a fim de ser localizada pela Smarty.

Os arquivos de plugin devem ser nomeados da sequinte forma:

tipo.nome.php

Onde tipo é um dos seguintes tipos de plugin:

  • function
  • modifier
  • block
  • compiler
  • prefilter
  • postfilter
  • outputfilter
  • resource
  • insert

E nome seria um identificador válido (letras, números, e underscores apenas).

Alguns exemplos: function.html_select_date.php, resource.db.php, modifier.spacify.php.

As funções de plugin dentro dos arquivos do plugin devem ser nomeadas da seguinte forma:

smarty_tipo_nome()

O significado de tipo e nome são os mesmos de antes.

A Smarty mostrará mensagens de erro apropriadas se o arquivo de plugins que é necessário não é encontrado, ou se o arquivo ou a função de plugin estão nomeadas inadequadamente.

Escrevendo Plugins


Os Plugins podem ser ou lidos pela Smarty automaticamente do sistema de arquivos ou eles podem ser registrados no tempo de execução via uma das funções de API register_* . Eles podem também ser com o uso da função API unregister_* .

Para os plugins que são registrados no tempo de execução, o nome da(s) função(ões) de plugin não têm que seguir a convenção de aparência.

Se um plugin depende de alguma funcionalidade fornecida por um outro plugin (como é o caso com alguns plugins embutidos com a Smarty), então a forma apropriada para ler o plugin necessário é esta:

require_once $smarty->_get_plugin_filepath('function', 'html_options');

Como uma regra geral, o objeto da Smarty é sempre passado para os plugins como o último parâmetro (com duas exceções: modificadores não passam o objeto da Smarty em tudo e blocks passam &$repeat depois do objeto da Smarty para manter compatibilidade a antigas versões da Smarty).

Funções de Template


void smarty_function_name (array $params, object &$smarty)

Todos os atributos passados para as funções de template a partir do template estão contidas em $params como um array associativo. Ou acessa esses valores diretamente i.e $paramsstart? ou usa extract($params) para importá-los para dentro da tabela símbolo.

A saída (valor de retorno) da função será substituída no lugar da tag da função no template (a função fetch(), por exemplo). Alternativamente, a função pode simplesmente executar alguma outra tarefa sem ter alguma saída (a função assign()).

Se a função precisa passar valores a algumas variáveis para o template ou utilizar alguma outra funcionalidade fornecida com a Smarty, ela pode usar o objeto $smarty fornecido para fazer isso.

Veja também: register_function(), unregister_function().

Exemplo 16-1. função de plugin com saída



<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     function.eightball.php

 * Type:     function

 * Name:     eightball

 * Purpose:  outputs a random magic answer

 * -------------------------------------------------------------

 */

function smarty_function_eightball($params, &$smarty)

{

    $answers = array('Yes',

                     'No',

                     'No way',

                     'Outlook not so good',

                     'Ask again soon',

                     'Maybe in your reality');



    $result = array_rand($answers);

    return $answers[$result];

}

?>



que pode ser usada no template da seguinte forma:



Pergunta: Nós sempre teremos tempo para viajar?

Resposta: {eightball}.



Exemplo 16-2. função de plugin sem saída



<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     function.assign.php

 * Type:     function

 * Name:     assign

 * Purpose:  assign a value to a template variable

 * -------------------------------------------------------------

 */

function smarty_function_assign($params, &$smarty)

{

    extract($params);



    if (empty($var)) {

        $smarty->trigger_error("assign: missing 'var' parameter");

        return;

    }



    if (!in_array('value', array_keys($params))) {

        $smarty->trigger_error("assign: missing 'value' parameter");

        return;

    }



    $smarty->assign($var, $value);

}

?>

Modificadores


Modificadores são funções que são aplicadas a uma variável no template antes dela ser mostrada ou usada em algum outro contexto. Modificadores podem ser encadeados juntos.

mixed smarty_modifier_name (mixed $value, [mixed $param1, ...])

O primeiro parâmetro para o plugin midificador é o valor em que o modificador é suposto operar. O resto dos parâmetros podem ser opcionais, dependendo de qual tipo de operação é para ser executada.

O modificador deve retornar o resultado de seu processamento.

Veja também: register_modifier(), unregister_modifier().

Exemplo 16-3. Plugin modificador simples

Este plugin basiamente é um alias de uma função do PHP. Ele não tem nenhum parâmetro adicional.

<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     modifier.capitalize.php

 * Type:     modifier

 * Name:     capitalize

 * Purpose:  capitalize words in the string

 * -------------------------------------------------------------

 */

function smarty_modifier_capitalize($string)

{

    return ucwords($string);

}

?>

Exemplo 16-4. Plugin modificador mais complexo

<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     modifier.truncate.php

 * Type:     modifier

 * Name:     truncate

 * Purpose:  Truncate a string to a certain length if necessary,

 *           optionally splitting in the middle of a word, and 

 *           appending the $etc string.

 * -------------------------------------------------------------

 */

function smarty_modifier_truncate($string, $length = 80, $etc = '...',

                                  $break_words = false)

{

    if ($length == 0)

        return '';



    if (strlen($string) > $length) {

        $length -= strlen($etc);

        $fragment = substr($string, 0, $length+1);

        if ($break_words)

            $fragment = substr($fragment, 0, -1);

        else

            $fragment = preg_replace('/s+(S+)?$/', '', $fragment);

        return $fragment.$etc;

    } else

        return $string;

}

?>

Block Functions


void smarty_block_name (array $params, mixed $content, object &$smarty)

Funções de Block são funções da forma: {func} .. {/func}. Em outras palavras, ele enclausura um bloco de template e opera no conteúdo deste bloco. Funções de Block tem precedência sobre funções customizadas com mesmo nome, assim, você não pode ter ambas, função customizável {func} e função de Bloco {func} .. {/func}.

Por definição a implementação de sua função é chamada duas vezes pela Smarty: uma vez pela tag de abertura, e outra pela tag de fechamento (veja &$repeat abaixo para como mudar isto).

Apenas a tag de abertura da função de bloco pode ter atributos. Todos os atributos passados para as funções de template estão contidos em $params como um array associativo. Você pode ou acessar esses valores diretamente, i.e. $paramsstart? ou usar extract($params) para importá-los para dentro da tabela símbolo. Os atributos da tag de abertura são também acessíveis a sua função quando processando a tag de fechamento.

O valor da variável $content depende de que se sua função é chamada pela tag de fechamento ou de abertura. Caso seja a de abertura, ele será null, se for a de fechamento o valor será do conteúdo do bloco de template. Note que o bloco de template já terá sido processado pela Smarty, então tudo que você receberá é saída do template, não o template original.

O parâmetro &$repeat é passado por referência para a função de implementação e fornece uma possibilidade para ele controlar quantas vezes o bloco é mostrado. Por definição $repeat é true na primeira chamada da block-function (a tag de abertura do bloco) e false em todas as chamadas subsequentes à função de bloco (a tag de fechamento do bloco). Cada vez que a implementação da função retorna com o &$repeat sendo true, o conteúdo entre {func} .. {/func} é avaliado e a implementação da função é chamada novamente com o novo conteúdo do bloco no parâmetro $content.

Se você tem funções de bloco aninhadas, é possível descobrir qual é a função de bloco pai acessando a variável $smarty->_tag_stack. Apenas faça um var_dump() nela e a estrutura estaria visível.

See also: register_block(), unregister_block().

Exemplo 16-5. função de bloco

<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     block.translate.php

 * Type:     block

 * Name:     translate

 * Purpose:  translate a block of text

 * -------------------------------------------------------------

 */

function smarty_block_translate($params, $content, &$smarty)

{

    if (isset($content)) {

        $lang = $params['lang'];

        // do some intelligent translation thing here with $content

        return $translation;

    }

}

Funções Compiladoras


Funções compiladoras só são chamadas durante a compilação do template. Elas são úteis para injeção de código PHP ou conteúdo estático time-sensitive dentro do template. Se há ambos, uma função compiladora e uma função customizável registrada sob o mesmo nome, a função compiladora tem precedência.

mixed smarty_compiler_name (string $tag_arg, object &$smarty)

À função compiladora são passados dois parâmetros: a tag string de argumento da tag - basicamente, tudo a partir do nome da função até o delimitador de fechamento, e o objeto da Smarty. É suposto que retorna o código PHP para ser injetado dentro do template compilado.

See also register_compiler_function(), unregister_compiler_function().

Exemplo 16-6. função compiladora simples

<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     compiler.tplheader.php

 * Type:     compiler

 * Name:     tplheader

 * Purpose:  Output header containing the source file name and

 *           the time it was compiled.

 * -------------------------------------------------------------

 */

function smarty_compiler_tplheader($tag_arg, &$smarty)

{

    return "
echo '" . $smarty->_current_file . " compiled at " . date('Y-m-d H:M'). "';";

}

?>

Esta função pode ser chamada em um template da seguinte forma:

{* esta função é executada somente no tempo de compilação *}

{tplheader}

O código PHP resultante no template compilado seria algo assim:

<php

echo 'index.tpl compiled at 2002-02-20 20:02';

?>

Prefiltros/Posfiltros?


Plugins Prefilter e postfilter são muito similares em conceito; onde eles diferem é na execução -- mais precisamente no tempo de suas execuções.

string smarty_prefilter_name (string $source, object &$smarty)

Prefilters são usados para processar o fonte do template imediatamente antes da compilação. O primeiro parâmetro da função de prefilter é o fonte do template, possivelmente modificado por alguns outros prefilters. O Plugin é suposto retornar o fonte modificado. Note que este fonte não é salvo em lugar nenhum, ele só é usado para a compilação.

string smarty_postfilter_name (string $compiled, object &$smarty)

Postfilters são usados para processar a saída compilada do template (o código PHP) imediatamente após a compilação ser feita e antes do template compilado ser salvo no sistema de arquivo. O primeiro parâmetro para a função postfilter é o código do template compilado, possivelmente modificado por outros postfilters. O plugin é suposto retornar a versão modificada deste código.

Exemplo 16-7. Plugin prefilter

<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     prefilter.pre01.php

 * Type:     prefilter

 * Name:     pre01

 * Purpose:  Convert html tags to be lowercase.

 * -------------------------------------------------------------

 */

 function smarty_prefilter_pre01($source, &$smarty)

 {

     return preg_replace('!<(w+)[^>]+>!e', 'strtolower("$1")', $source);

 }

?>

Exemplo 16-8. Plugin postfilter

<?php

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     postfilter.post01.php

 * Type:     postfilter

 * Name:     post01

 * Purpose:  Output code that lists all current template vars.

 * -------------------------------------------------------------

 */

 function smarty_postfilter_post01($compiled, &$smarty)

 {

     $compiled = "<pre>
<?php print_r($this->get_template_vars()); ?>
</pre>" . $compiled;

     return $compiled;

 }

?>

Filtros de saída


Filtros de saída operam na saída do template, depois que o template é lido e executado, mas antes a saída é mostrada.

string smarty_outputfilter_name (string $template_output, object &$smarty)

O primeiro parâmetro para a função do filtro de saída é a saída do template que precisa ser processada, e o segundo parâmetro é a instância da Smarty invocando o plugin. O plugin deve fazer o precessamento e retornar os resultados.

Exemplo 16-9. output filter plugin

/*

 * Smarty plugin

 * -------------------------------------------------------------

 * File:     outputfilter.protect_email.php

 * Type:     outputfilter

 * Name:     protect_email

 * Purpose:  Converts @ sign in email addresses to %40 as 

 *           a simple protection against spambots

 * -------------------------------------------------------------

 */

 function smarty_outputfilter_protect_email($output, &$smarty)

 {

     return preg_replace('!(S+)@([a-zA-Z0-9.-]+.([a-zA-Z]{2,3}|[0-9]{1,3}))!',

                         '$1%40$2', $output);

 }

Recursos (Resources)


Os plugins de Recursos são como uma forma genérica de fornecer códigos fontes de template ou componentes de script PHP para a Smarty. Alguns exemplos de recursos: banco de dados, LDAP, memória compartilhada, sockets, e assim por diante.

Há um total de 4 funções que precisam estar registradas para cada tipo de recurso. Cada função receberá o recurso requisitado como o primeiro parâmetro e o objeto da Smarty como o último parâmetro. O resto dos parâmetros dependem da função.

bool smarty_resource_name_source (string $rsrc_name, string &$source, object &$smarty)



bool smarty_resource_name_timestamp (string $rsrc_name, int &$timestamp, object &$smarty)



bool smarty_resource_name_secure (string $rsrc_name, object &$smarty)



bool smarty_resource_name_trusted (string $rsrc_name, object &$smarty)

A primeira função deve devolver o recurso. Seu segundo parâmetro é uma variável passada por referência onde o resultado seria armazenado. A função deve retornar true se ela está apta a devolver com sucesso o recurso e caso contrário retorna false.

A segunda função deve devolver a última modificação do recurso requisitado (como um timestamp Unix). O segundo parâmetro é uma variável passada por referência onde o timestamp seria armazenado. A função deve retornar true se o timestamp poderia ser determinado com sucesso, e caso contrário retornaria false.

A terceira função deve retornar true ou false, dependendo do recurso requisitado está seguro ou não. Esta função é usada apenas para recursos de template mas ainda assim seria definida.

A quarta função deve retornar true ou false, dependendo do recurso requisitado ser confiável ou não. Esta função é usada apenas para componentes de script PHP requisitados pelas tags include_php ou insert com o atributo src. Entretanto, ela ainda assim mesmo seria definida para os recursos de template.

Veja também: register_resource(), unregister_resource().

Exemplo 16-10. Plugin resource (recurso)

<?php

/*

 * Smarty plugin

 * ------------------------------------------------------------- 

 * File:     resource.db.php

 * Type:     resource

 * Name:     db

 * Purpose:  Fetches templates from a database

 * -------------------------------------------------------------

 */

function smarty_resource_db_source($tpl_name, &$tpl_source, &$smarty)

{

    // do database call here to fetch your template,

    // populating $tpl_source

    $sql = new SQL;

    $sql->query("select tpl_source

                   from my_table

                  where tpl_name='$tpl_name'");

    if ($sql->num_rows) {

        $tpl_source = $sql->record['tpl_source'];

        return true;

    } else {

        return false;

    }

}



function smarty_resource_db_timestamp($tpl_name, &$tpl_timestamp, &$smarty)

{

    // faz o banco de dados chamar aqui para preencher $tpl_timestamp.

    $sql = new SQL;

    $sql->query("select tpl_timestamp

                   from my_table

                  where tpl_name='$tpl_name'");

    if ($sql->num_rows) {

        $tpl_timestamp = $sql->record['tpl_timestamp'];

        return true;

    } else {

        return false;

    }

}



function smarty_resource_db_secure($tpl_name, &$smarty)

{

    // assume que todos os templates são seguros

    return true;

}



function smarty_resource_db_trusted($tpl_name, &$smarty)

{

    // não usado para templates

}

?>

Inserts


Plugins Insert são usados para implementar funções que são invocadas por tags insert no template.

string smarty_insert_name (array $params, object &$smarty)

O primeiro parâmetro para a função é um array associativo de atributos passados para o insert. Ou acessa esses valores diretamente, i.e. $paramsstart? ou usa extract($params) para importá-los para dentro da tabela símbolo.

A função insert deve retornar o resultado que será substituído no lugar da tag insert no template.

Exemplo 16-11. Plugin insert

<?php

/*

 * Smarty plugin

 * ------------------------------------------------------------- 

 * File:     insert.time.php

 * Type:     time

 * Name:     time

 * Purpose:  Inserts current date/time according to format

 * -------------------------------------------------------------

 */

function smarty_insert_time($params, &$smarty)

{

    if (empty($params['format'])) {

        $smarty->trigger_error("insert time: missing 'format' parameter");

        return;

    }



    $datetime = strftime($params['format']);

    return $datetime;

}

?>