Back-End

6 ago, 2010

Personalizando MediaWiki: criando e instalando extensões

Publicidade

O aplicativo MediaWiki é provavelmente mais conhecido por ser o mecanismo que está por trás da Wikipédia. Muitas pessoas estão descobrindo que o MediaWiki oferece um ambiente de utilização para compartilhamento de informações entre grupos de trabalho e até mesmo entre organizações, bem como comunidades on-line.

O MediaWiki permite que os usuários compartilhem informações via blogs, wikis e arquivos. Ele também permite proteger arquivos transferidos por upload protegidos, marcar arquivos com tag para fácil localização e localizar especialistas usando uma nuvem de tag.

E se o usuário quiser introduzir informações personalizadas que não deseja atualizar manualmente e inserir em suas páginas de wiki? E se ele quiser fornecer formatação de saída personalizada para um determinado tipo de informação? São em situações como essas que o MediaWiki faz sentido, visto que é possível adicionar com facilidade esses recursos específicos de site por meio do uso de extensões.

Vamos ver como é possível criar extensões de MediaWiki que cooperam com diferentes fontes de informações, enquanto os dados são fornecidos por meio de interface do usuário familiar da página do wiki.

Extensões de MediaWiki

As extensões podem adicionar novas tags à marcação usada para escrever artigos, adicionar novos recursos administrativos e de relatório por meio da criação de páginas especiais, alterar a aparência do wiki por meio de aparências de formatação e até mesmo realizar integração com métodos de autenticação externos (embora a autenticação não seja abordada neste artigo).

As extensões são escritas em PHP e fazem uso de vários hooks, classes e métodos internos do MediaWiki para desempenhar suas tarefas eficientemente. Embora seja possível desenvolver e implementar o MediaWiki usando qualquer servidor da Web e seu ambiente de desenvolvimento PHP favorito, você usará o seguinte:

  • Eclipse V3.5.2 – Suporte para uma ampla gama de ambientes e linguagens de programação
  • PHP Development Tools (PDT) V2.2.0 – Um plug-in PHP para Eclipse
  • MAMP Pro V1.9 – Um pacote prático para Mac OS X, que fornece Apache, MySQL e PHP em um ambiente isolado com um front-end de GUI útil. Embora o OS X venha com Apache e PHP instalados, optei por usar esse porque a versão de PHP no OS X V10.6 Snow Leopard (V5.3.1) aparentemente tem um erro que impede o MediaWiki de operar corretamente.
  • MediaWiki V1.15.3 – A versão estável atual do MediaWiki

Ao final do artigo é possível encontrar todos esses itens citados na seção Recursos.

Antes de observar os diferentes tipos de extensões, vamos dar uma olhada rápida no layout da pasta e do arquivo usado pela maioria deles. Após isso, haverá uma visão geral de alto nível de extensões de aparência para alterar a aparência do site MediaWiki. Em seguida, você criará uma extensão de página especial que produz algumas estatísticas administrativas. Você ainda vai conferir como adicionar suporte de marcação de tag XML personalizado para aproveitar as suas vantagens enquanto escreve páginas de wiki.

Anatomia de extensão

As extensões de MediaWiki são instaladas no diretório de extensões no caminho principal de MediaWiki. A maioria das extensões modernas é instalada em seu próprio diretório e é composta por três arquivos (extension é o nome da extensão):

  • extension/extension.php
  • extension/extension.body.php
  • extension/extension.i18n.php

O primeiro arquivo é responsável pela inicialização e por todas as tarefas
de configuração. O segundo arquivo é o corpo da extensão, é o código de
trabalho que implementa a extensão. Por fim, o último arquivo contém
cadeias de caracteres de internacionalização (i18n é um formulário
curto comum).

Ao enviar as cadeias de caracteres de mensagem da
extensão para o arquivo i18n, você poderá fornecer versões localizadas
de sua extensão para qualquer um dos códigos do idioma do MediaWiki.

Como exemplo, criei um tipo de extensão Hello World denominado CHTimeStamp. Faça o download do recurso para acessar o código de origem deste exemplo e os outros exemplos abordados. CHTimeStamp inserirá o registro de data e hora atual sempre que alguém inserir {{CHSTAMP}} em uma página wiki. Ele é composto pelos seguintes arquivos:

  • CHTimeStamp/CHTimeStamp.php
  • CHTimeStamp/CHTimeStamp.body.php
  • CHTimeStamp/CHTimeStamp.i18n.php

Figura 1. Layout de CHTimeStamp no Eclipse

A extensão CHTimeStamp adiciona uma variável {{CHSTAMP}} à marcação do MediaWiki. Sempre que você colocar {{CHSTAMP}}
em uma página, ele será substituído por um registro de data e hora.
Trivial e fácil de seguir, certo? Se estiver curioso, dê uma olhada no
código para download. Vamos apenas descrever isso bem detalhadamente aqui para apresentá-lo
ao layout geral e às convenções das extensões de MediaWiki.

Meu CHTimeStamp.php registra o arquivo de mensagens de
internacionalização, informa ao mecanismo do wiki que ele pode
encontrar a classe CHTimeStamp em CHTimeStamp.body.php e adiciona o método CHTimeStamp::registerHooks ao array das funções de extensão.

No CHTimeStamp.body.php, defina a classe CHTimeStamp.
Se você observar o código, verá que ele é composto totalmente por
métodos estáticos, portanto, ele poderia também ter sido escrito como
uma série de funções sem a alteração do comportamento da extensão. CHTimeStamp: o seu método registerHooks registra métodos estáticos para criar a variável {{CHSTAMP}} e manipular as páginas que a utilizam.

Por fim, em CHTimeStamp.i18n.php, criei traduções para a única
cadeia de caracteres estática na extensão: sua descrição. Com a ajuda
do Google Translate, CHTimeStamp é compatível com os códigos do idioma
francês, alemão e espanhol. Mas espero que as traduções automatizadas
não transformem meu inglês em sinopses inadequadas (ou inapropriadas)!

Após ter criado uma extensão ou feito sua transferência por download, você precisará instalá-la no MediaWiki e ativá-la.

Instalando uma extensão

Quando tiver uma extensão interessante ou útil pronta para o seu site MediaWiki, você a instalará e a ativará:

  1. Copie ou descompacte a extensão no diretório de extensões do MediaWiki.
  2. Edite LocalSettings.php no diretório-raiz do MediaWiki. Usando seu
    editor de texto favorito, adicione linhas para configurar a nova
    extensão e ative-a usando a instrução require_once() do PHP.

Por exemplo, para instalar CHTimeStamp, copiei seu diretório CHTimeStamp para o diretório de extensões e adicionei o seguinte a LocalSettings.php: require_once( “$IP/extensions/CHTimeStamp/CHTimeStamp.php” );.

Verifique se a extensão foi carregada visitando a página
Special:Version do wiki. Além das informações sobre a versão do
MediaWiki que você está executando, a página Special:Version lista as
extensões que foram carregadas com êxito.

Figura 2. Página Special:Version mostrando CHTimeStamp

Personalizando a aparência

MediaWiki aproveita a vantagem da capacidade do PHP de misturar
código e marcação HTML para lhe oferecer controle sobre a aparência do
seu wiki por meio do uso de aparências. Além do código PHP principal,
uma aparência pode conter vários arquivos CSS e imagens de suporte ou
JavaScript.

Uma aparência geralmente é composta por dois arquivos PHP e um
diretório para arquivos de suporte adicionais. Por exemplo, a aparência
padrão famosa, MonoBook, é composta por:

  • MonoBook.php – Código de aparência MonoBook principal
  • MonoBook.deps.php – Uma correção de um erro no cache do código de operação APC de PHP V5
  • monobook/ – Suporte a CSS e a gráficos

A convenção de nomenclatura de aparências é muito estrita, solicitando SkinName.php, SkinName.deps.php e skinname (letra minúscula) como o nome da pasta de suporte.

Dentro da pasta skinname, estará main.css para o estilo
da aparência. As correções de folha de estilo específicas de navegador
estão aqui também, portanto, você também encontrará, em geral,
FF2Fixes.css, IE6Fixes.css, Opera6Fixes.css etc.

SkinName.php começará com alguns metadados úteis.

Listagem 1. Metadados de aparência MediaWiki

/**
* [SkinName] skin
*
* @file
* @ingroup Skins
* @version [#].[#].[#]
* @author [name] ([URL] / [E-Mail])
* @license [URL] [name]
*/

Substitua tudo entre colchetes por algo adequado para a aparência.

Em seguida, será preciso criar uma subclasse de SkinTemplate e substituir o método initPage para indicar o nome, o estilo e o modelo da aparência. Lembre-se de substituir SkinName e skinname pelo nome da sua aparência.

Listagem 2. Estendendo SkinTemplate para fornecer uma nova aparência

// inherit main code from SkinTemplate, set the CSS and template filter
class SkinSkinName extends SkinTemplate {
function initPage( OutputPage $out ) {
parent::initPage( $out );
$this->skinname = 'skinname';
$this->stylename = 'skinname';
$this->template = 'SkinNameTemplate';
}
}

A grande força da sua aparência será a subclasse QuickTemplate.

Listagem 3. A maior parte do trabalho é feita no modelo

class SkinNameTemplate extends QuickTemplate {
...
/**
* Template filter callback for this skin.
* Takes an associative array of data set from a SkinTemplate-based
* class, and a wrapper for MediaWiki's localization database, and
* outputs a formatted page.
*/
public function execute() {
global $wgUser, $wgSitename;
$skin = $wgUser->getSkin();

// retrieve site name
$this->set( 'sitename', $wgSitename );

// suppress warnings to prevent notices about missing indexes
// in $this->data
wfSuppressWarnings();

/* compose XHTML output */

?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
...

Dentro da subclasse QuickTemplate, substitua métodos
para formatar e definir o estilo de coisas como listagens de categoria
e referências cruzadas da forma que quiser. O método execute
da classe forma o layout de toda a página como um documento XHTML,
proporcionando-lhe controle completo sobre o estilo e a organização da
página.

Não é possível acessar o layout e o estilo de página XHTML e CSS
aqui, portanto, dê uma olhada na pasta de aparências do MediaWiki para
ter acesso a exemplos que podem ser experimentados imediatamente.

Adicionando páginas especiais

Páginas especiais no MediaWiki são geradas sob demanda para se fazer
algo específico e possivelmente útil para o wiki, como permitir a
edição de texto de mensagens de todo o sistema, a listagem das
extensões instaladas ou a obtenção de uma lista de links externos.

A menos que especificado de outra forma, sua página especial estará disponível a qualquer pessoa e será exibida na lista Special:SpecialPages
de páginas especiais. É possível também configurar a página especial
para que ela possa ser incluída de maneira sequencial em uma página com
o uso da sintaxe {{Special:YourPageName}}.

Assim como outras extensões, páginas especiais são instaladas como
um diretório na pasta de extensões. Elas geralmente são compostas por
quatro arquivos:

  • specialpage/specialpage.php – O arquivo de configuração da extensão
  • specialpage/specialpage.aliases.php – Aliases do nome da página especial
  • specialpage/specialpage.body.php – O código principal da página especial
  • specialpage/specialpage.i18n.php – Cadeias de caracteres de internacionalização para a página especial

Por exemplo, se estiver criando uma página especial denominada CHStats, seu layout ficará como na Figura 3.

Figura 3. CHStats no Eclipse

O código CHStats.php adiciona crédito para a extensão, registra os
aliases, os arquivos de corpo e i18n e informa ao mecanismo do wiki
para carregar automaticamente a classe CHStats quando necessário.

Listagem 4. Configurando a página especial CHStats

<?php
# This is not a valid entry point to MediaWiki.
if( !defined( 'MEDIAWIKI' ) ) {
echo <<<EOT
To install CHStats, put the following line in LocalSettings.php:
require_once( "\$IP/extensions/CHStats/CHStats.php" );
EOT;
exit( 1 );
}

# Take credit for this extension.
$wgExtensionCredits['specialpage'][] = array(
'name' => 'CHStats',
'author' => 'Chris Herborth (chrish@pobox.com)',
'url' => 'http://www.pobox.com/~chrish/CHStats/',
'description' => 'A simple special page demonstration, showing some DB stats.',
'descriptionmsg' => 'chstats-desc',
'version' => '1.0.0',
);

$dir = dirname( __FILE__ ) . '/';

# Register the extension's main code/class.
$wgAutoloadClasses['CHStats'] = $dir . 'CHStats.body.php';

# Register our internationalization files.
$wgExtensionMessagesFiles['CHStats'] = $dir . 'CHStats.i18n.php';
$wgExtensionAliasesFiles['CHStats'] = $dir . 'CHStats.aliases.php';

# Let MediaWiki know about the new special page.
$wgSpecialPages['CHStats'] = 'CHStats';

?>

Em CHStats.body.php, crie uma nova classe, CHStats, que estende a classe SpecialPage. No construtor, inicialize a classe pai e carregue as mensagens de internacionalização chamando wfLoadExtensionMessages. Verifique a página do guia do desenvolvedor Special Pages através de Recursos para mais informações sobre o construtor da classe SpecialPage, que permitirá restringir o acesso, ocultar a página etc.

A substituição do método execute realiza o trabalho de gerar a página.

Listagem 5. Gerando a página especial CHStats

# This is where the special page's output is created.
function execute( $par ) {
global $wgOut;

# Initialize the output page.
$this->setHeaders();

# Do stuff.
$wgOut->addWikiText( "Some stats about this '''Wiki''':" );

$db = wfGetDB( DB_SLAVE );
// SELECT ... FROM site_stats
$result = $db->select( 'site_stats',
array( 'ss_total_views', 'ss_total_edits',
'ss_total_pages', 'ss_users' ) );
$statList = array();
foreach( $result as $row ) {
$statList[] = '* Total page views: ' . $row->ss_total_views;
$statList[] = '* Total page edits: ' . $row->ss_total_edits;
$statList[] = '* Total # of users: ' . $row->ss_users;
}

$wgOut->addWikiText( implode( "\n", $statList ) );

$wgOut->addWikiText( "That's it." );
}

No método execute, o argumento $par é a subpágina. Por exemplo, caso Special:CHStats/foo tenha sido carregado, $par será definido como foo (seu nome é aparentemente uma excentricidade de histórico).

Primeiro, use o método setHeaders para configurar o cabeçalho da página e, em seguida, chame $wgOut->addWikiText para escrever alguma marcação no fluxo de saída. É possível também usar $wgOut->addHTML
para escrever HTML formatado diretamente, mas estou usando a marcação
de wiki na saída. Consulte em Recursos o guia do desenvolvedor Special Pages para
obter mais informações sobre isso
e como adicionar marcação de wiki corretamente e/ou HTML a páginas
especiais que podem ser incluídas sequencialmente em outras páginas.

A página CHStats usa a função wfGetDB para obter uma
referência para o banco de dados (use DB_SLAVE para operações somente
leitura e DB_MASTER para operações de gravação). Em seguida, selecione
vários campos no banco de dados site_stats e formate os resultados como
uma lista com marcadores usando a marcação wiki.

É possível ver como fica a saída dessa página especial na Figura 4.

Figura 4. CHStats em ação

As cadeias de caracteres de internacionalização encontradas em
CHStats.i18n.php são compostas por um array, com uma entrada por idioma
suportado (inglês, francês, alemão e espanhol, nesse caso). Em cada
entrada, está um array que mapeia cadeias de caracteres de IDs para o
que é provavelmente o seu texto localizado. O Google Translate foi
usado para as partes em francês, alemão e espanhol.

CHStats.aliases.php tem um array similar contendo as versões
localizadas do próprio nome da página CHStats. Isso permite que os
usuários de francês (por exemplo) acessem a página como Spécial:StatsCH.

Adicionando tags

Outra forma conhecida de estender MediaWiki é adicionando suporte
para novas tags XML à marcação. Essas tags podem produzir saída
diferente com base nos atributos de tag ou no conteúdo e são úteis para
inserir HTML sequencial ou até mesmo blocos grandes de saída formatada.

As extensões de tag são instaladas em seu próprio diretório sob a
pasta de extensões e usam a convenção de três arquivos descrita no
início deste artigo. Vamos observar uma que criei, denominada CHUser:

  • CHUser/CHUser.php – Configuração de extensão
  • CHUser/CHUser.body.php – Código de extensão principal
  • CHUser/CHUser.i18n.php – Dados de internacionalização

A configuração de extensão em CHUser.php é igual ao que você já viu, embora utilize o array $wgHooks para adicionar o método init da extensão à lista ParserFirstCallInit. CHUser::init será chamado na primeira vez em que for usado.

Listagem 6. Configurando a extensão de tag

# Let MediaWiki know about the new tag.
$wgHooks['ParserFirstCallInit'][] = 'CHUser::init';

Dentro de CHUser.body.php, o método init registra duas tags: <chuser> e <bz> (consulte a Listagem 7). Essa extensão fornece duas tags diferentes em apenas uma extensão. Você poderá facilmente combinar todas as extensões discutidas neste artigo se quiser, não existe nenhum requisito para separar as coisas.

Listagem 7. Registrando as tags <chuser> e <bz>

public static function init( &$parser ) {
# Add our <chuser> tag handler, the continue.
$parser->setHook( 'chuser', 'CHUser::render' );
$parser->setHook( 'bz', 'CHUser::renderBugzilla' );
return true;
}

Sempre que o mecanismo de marcação do wiki encontrar uma tag <chuser>, ele chamará o método CHUser::render, e as tags <bz> chamarão CHUser::renderBugzilla.

O método de renderização <chuser> seleciona o nome completo e o endereço de e-mail do usuário especificado e o formata como um link mailto: em torno do nome completo do usuário (se houver um). É possível ver na Listagem 8 que a maior parte da lógica é simplesmente cuidar dos casos em que o nome completo ou o endereço de e-mail não está presente no banco de dados (como a conta Admin no meu wiki).

Listagem 8. Manipulação <chuser>UserName</chuser>

public static function render( $input, $args, $parser, $frame ) {
$user = mysql_escape_string( $input );

$db = wfGetDB( DB_SLAVE );
// SELECT ... FROM user
$result = $db->select( 'user',
array( 'user_real_name', 'user_email' ),
'user_name = \'' . $user . '\'' );
$mailtos = array();
foreach( $result as $row ) {
$thisUser = '<span class="user">';

if( $row->user_email ) {
$thisUser = $thisUser . '<a href="mailto:'
. htmlspecialchars( $row->user_email ) . '">';
}

if( $row->user_real_name ) {
$thisUser = $thisUser . htmlspecialchars( $row->user_real_name );
} else {
$thisUser = $thisUser . htmlspecialchars( $input );
}

if( $row->user_email ) {
$thisUser = $thisUser . '</a>';
}

$thisUser = $thisUser . '</span>';

$mailtos[] = $thisUser;
}

return implode( ", ", $mailtos );
}

A Listagem 9 mostra como a tag <bz> usa seu atributo de ID para estabelecer um vínculo com um relatório de erros especificado no banco de dados MediaWiki Bugzilla. Aqui, é possível ver quão fácil é trabalhar com origens de dados externas. Se quiser ser caprichoso, use Ajax para carregar o relatório de erros em vez de estabelecer um vínculo com ele e exiba alguns de seus dados em vez do link.

Listagem 9. <bz id=”number” /> estabelece vínculo com o MediaWiki Bugzilla

public static function renderBugzilla( $input, $args, $parser, $frame ) {
$retval = '';
if( $args['id'] ) {
$bzId = htmlspecialchars( $args['id'] );

$retval = '<a href="https://bugzilla.wikimedia.org/show_bug.cgi?id='
. $bzId . '">MediaWiki Bug #' . $bzId . '</a>';
} else {
$retval = '<span class="error">No bug ID specified</span>';
}

return $retval;
}

É possível ver essas duas tags em ação na Figura 5.

Figura 5. Suas extensões em ação

A Listagem 10 mostra como a marcação do wiki fica para essa seção da página.

Listagem 10. A marcação do wiki mostrando as extensões

== Extension testing ==

If this is working, we should see a timestamp: {{CHSTAMP}}

CHUser info:

* '''Admin''': <chuser>Admin</chuser>
* '''Chrish''': <chuser>Chrish</chuser>

<bz id="1024" />

Como é possível ver na extensão CHUser, a adição de suporte para as XML personalizadas é fácil e lhe permite fazer praticamente tudo. Todos os recursos PHP e serviços MediaWiki estão disponíveis, portanto, é possível extrair dados de (ou envia dados a) sistemas externos, alterar o comportamento com base nas credenciais e permissões do usuário atual ou inserir JavaScript para executar tarefas diretamente no navegador do visualizador. As possibilidades são ilimitadas e estão limitadas apenas às suas necessidades e aos seus requisitos específicos.

Conclusão

Neste artigo, apresentamos várias técnicas de extensão suportadas pelo MediaWiki, um sistema de wiki de software livre similar a software wiki comercial, como Lotus Connections.

Mostramos as convenções de extensão do MediaWiki e como criar uma extensão de variável de wiki simples como uma introdução à escrita de extensões MediaWiki. Uma visão geral dos recursos de aparência do MediaWiki o ajuda a começar a criar seu próprio layout de site personalizado.

Páginas especiais são geralmente usadas para gerar informações, recuperadas de um banco de dados ou de outra origem, portanto, você criou uma que exibe algumas das estatísticas do sistema. Em seguida, você criou várias tags XML personalizadas que poderão ser incluídas na marcação de wiki de qualquer página.

Confira agora nossa sessão recursos e coloque os aprendizados sobre a personalização de MediaWiki em prática.

Recursos

Aprender:

  • Obtenha informações gerais sobre a escrita de extensões para MediaWiki no Manual de extensões.

Obter produtos e tecnologias:

  • Obtenha o Eclipse IDE usado para criar o código deste artigo
  • Obtenha o MAMP Pro (pacote Apache, MySQL, PHP para Mac OS X).

artigo publicado originalmente em developerWorks Brasil, por Chris Herborth

Chris Herborth é um escritor técnico senior vencedor de prêmios, com
mais de 10 anos de experiência na escrita de materiais sobre sistemas
operacionais e programação.