Published:
Plugins Moodle Permalink
O sucesso de um software depende muito do quão podemos modificá-lo para atender nossas necessidades particulares. Do ponto de vista de desenvolvimento, eu sempre olho para um framework através da sua estrutura de API e hooks. As classes do moodle, na sua versão atual, 3.x, me lembra muito o Drupal 5.x ou 6.x e portanto não segue muito a estrutura de frameworks modernos como symfony, laravel ou o próprio Drupal 9.x. De qualquer modo, segue-se uma série de anotações referente ao desenvolvimento de plugins para o moodle.
Exemplo: Plugin de Administração
Estrutura mínima de um plugin
Tipos de plugins: lib/components.json
frankenstyle: nome do tipo _ nome do plugin
Verificação de styles: https://moodle.org/plugins/local_codechecker https://moodle.org/plugins/local_moodlecheck
Tipo de arquivos php no plugin:
- request handlers: acessados pelo browser: devem ter require(DIR. ‘/../../config.php’);
Libraries: não acessíveis pelo browser: devem iniciar assim defined(‘MOODLE_INTERNAL’) die(); - garabte que esse qrauivo será chamado por outro e não via request - podemos colocar bibliotecas em na pasta classes: assim não precisamos usar require_once() para chama-lás em outros arquivos \mod_forum\some_class is stored in file mod/forum/classes/some_class.php nas classes NÂO precisa ter MOODLE_INTERNAL!
csrf: sesskey()
$action = new moodle_url(‘/admin/tool/do/something.php’, [‘delete’ => $id, ‘sesskey’ => sesskey()]); echo html_writer::link($action, get_string(‘delete’));
Onde processarmos o form: require_sesskey();
required_param(‘courseid’, PARAM_INT);
Dependências mínimas para instalação moodle em debian 10:
sudo apt install php php-gd php-curl php-xml php-mbstring php-intl php-mysql curl mariabdb-server
Baixando o moodle com composer:
composer create-project moodle/moodle moodle-for-plugin-dev
Instalação rápida:
cd moodle-for-plugin-dev
php admin/cli/install.php \
--lang=pt_br \
--wwwroot='http://0.0.0.0:8000' \
--dataroot='/home/thiago/moodledata' \
--dbtype=mariadb \
--dbhost='localhost' \
--dbname=moodle \
--dbuser=master \
--dbpass=master \
--fullname=moodledev \
--shortname=moodledev \
--adminpass='Admin123*' \
--non-interactive \
--agree-license
O que eu ativo no config.php:
@error_reporting(E_ALL | E_STRICT);
@ini_set('display_errors', '1');
$CFG->debug = E_ALL;
$CFG->debugdisplay = 1;
$CFG->langstringcache = 0;
$CFG->cachetemplates = 0;
$CFG->cachejs = 0;
$CFG->perfdebug = 15;
$CFG->debugpageinfo = 1;
Subindo server local:
php -S 0.0.0.0:8000
O moodle trabalha com tipos de plugins. Cada tipo de plugin deve ser colocado no diretório correspondente. Existe um tipo genérico chamado local
onde criarei meu primeiro plugin. Chamo de genérico, pois quero fazer uma mudança que não está relacionada a estrutura de um curso, mas sim relacionada a parte administrativa da instância. Nosso plugin interceptará a renderização de strings na camada de template deixando tudo em maiúscula, o chamaremos de tudoupper
. Crie o diretório do plugin:
mkdir -p local/tudoupper
Importante: todos arquivos do plugin devem conter: defined('MOODLE_INTERNAL') || die();
.
Os arquivos mínimos para o moodle reconhecer nosso plugin são:
version.php com metadados do plugin:
<?php
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'local_tudoupper'; // Nome do plugin
$plugin->version = 2021010300; // YYYYMMDDXX
O outro arquivo obrigatório é o do idioma, no qual devemos ao menos especificar o pluginname
. Neste momento não vou me preocupar com o idioma, então escreverei em português mesmo estando na pasta en
. No mundo real, você criaria local/tudoupper/lang/pt_br/local_tudoupper.php
e local/tudoupper/lang/en/local_tudoupper.php
e colocaria as strings correspondentes de cada língua.
mkdir -p local/tudoupper/lang/en
touch local/tudoupper/lang/en/local_tudoupper.php
<?php
defined('MOODLE_INTERNAL') || die();
$string['pluginname'] = 'Plugin que deixa tudo maiúsculo';
Neste momento, ao acessar o moodle como site administrator
o sistema reconhecerá e habilitará nosso plugin.
String API
Grande parte das classes que no geral vamos querer alterar em um plugin do tipo local
estão em lib/classes
. Queremos interceptar a classe que renderiza string para o template, assim vamos na busca de uma interface que trare de string:
find ./lib/classes -iname "*string*"
Identificamos a interface ./lib/classes/string_manager.php
que é implementada pela classe ./lib/classes/string_manager_standard.php
. Há um método chamado get_string
com a descrição: Get String returns a requested string.
No nosso plugin criaremos um diretórios chamado classes
:
mkdir -p local/tudoupper/classes
touch local/tudoupper/classes/tudoupper_string_manager.php
Em tudoupper_string_manager.php vamos extender core_string_manager_standard e sobrescrever o método get_string() copiando sua assinatura assim como definida na interface:
<?php
namespace local_tudoupper;
defined('MOODLE_INTERNAL') || die();
class tudoupper_string_manager extends \core_string_manager_standard {
public function get_string($identifier, $component = '', $a = null, $lang = null) {
$string = parent::get_string($identifier, $component, $a , $lang );
return strtoupper($string);
}
}
Conforme a documentação informamos ao moodle no config.php
para usar nossa classe ao invés da core_string_manager_standard
:
$CFG->customstringmanager = '\local_tudoupper\tudoupper_string_manager';
No version.php
podemos subir a versão do nosso plugin:
$plugin->version = 2021010301;
Composer
Posso estar enganado, mas não encontrei até o momento uma maneira de definir globalmente em um projeto moodle que usarei composer e que portanto as dependências dos meus plugins devem ser baixadas. Não é a melhor prática, mas vamos inicializar nosso plugin como um projeto composer distribuindo o diretório vendor
junto se necessário. Vou instalar uma biblioteca chamada jawira/case-converter
:
cd local/tudoupper/
composer init
composer require jawira/case-converter
Agora vamos modificar tudoupper_string_manager para usar essa biblioteca:
<?php
namespace local_tudoupper;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/local/tudoupper/vendor/autoload.php');
use Jawira\CaseConverter\Convert;
class tudoupper_string_manager extends \core_string_manager_standard {
public function get_string($identifier, $component = '', $a = null, $lang = null) {
$string = parent::get_string($identifier, $component, $a , $lang );
$obj = new Convert($string);
return $obj->toCamel();
}
}
Api de configuração
A página contém bastante informações sobre a API de configuração.
Vamos criar uma nova entrada em lang/en/local_tudoupper.php
:
<?php
defined('MOODLE_INTERNAL') || die();
$string['pluginname'] = 'Plugin que deixa tudo maiúsculo';
$string['title'] = 'Configurações do plugin super massa tudoupper';
Adicionemos um novo arquivo chamado settings.php
no nosso plugin tendo uma condição com $hassiteconfig
que restringe esse acesso apenas para administradores da plataforma. Manipularemos um objetos do tipo admin_settingpage
que cuidará da camada de formulário e persistência no banco de dados das configurações do plugin. Depois adicionamos esse objeto na variável global $ADMIN
que se encarregará de disponibilizar as opções do nosso plugin na área de configurações da plataforma.
<?php
defined('MOODLE_INTERNAL') || die();
if ($hassiteconfig) {
$title = new lang_string('title', 'local_tudoupper');
$settings = new admin_settingpage('local_tudoupper', $title);
$ADMIN->add('localplugins', $settings);
}
Suba a versão em version.php
e agora em Site Administration
-> Plugins
-> Local Plugins
temos uma entrada para configuração do nosso plugin, ainda sem campo algum.
Vamos adicionar os seguintes campos, em parentese estão as classes moodle da api de formulário que fornece o markup necessário para cada tipo:
- checkbox: ativar ou desativa o recurso desse plugin (admin_setting_configcheckbox)
- select: para usar tudo em uppercase ou camelCase (admin_setting_configselect)
- input text: prefixo (admin_setting_configtext)
- input text: suffixo (admin_setting_configtext)
Começamos complementando nossas strings em lang/en/local_tudoupper.php
:
<?php
defined('MOODLE_INTERNAL') || die();
$string['pluginname'] = 'Plugin que deixa tudo maiúsculo';
$string['title'] = 'Configurações do plugin super massa tudoupper';
$string['enabled'] = 'Habilitar tudoupper?';
$string['enabled_description'] = 'Habilitar esse recurso na plataforma moodle';
$string['type'] = 'Configura tipo';
$string['type_description'] = 'Tipo que deseja para o plugin tudoupper';
$string['type_upper'] = 'Tudo em Maiúscula';
$string['type_camelcase'] = 'Tudo em CamelCase';
$string['prefix'] = 'Configura prefixo';
$string['prefix_description'] = 'Colocar um prefixo em todas strings';
$string['suffix'] = 'Configura sufixo';
$string['suffix_description'] = 'Colocar um sufixo em todas strings';
Inicialmente vamos adicionar somente o campo $enabled
:
<?php
defined('MOODLE_INTERNAL') || die();
if ($hassiteconfig) {
# Inicializando objeto admin_settingpage
$title = new lang_string('title', 'local_tudoupper');
$settings = new admin_settingpage('local_tudoupper', $title);
# Campo para habilitar ou desabilitar recurso
$enabled = new lang_string('enabled', 'local_tudoupper');
$enabled_description = new lang_string('enabled_description', 'local_tudoupper');
$field_enabled = new admin_setting_configcheckbox('local_tudoupper/enabled',$enabled,$enabled_description,1);
# Adicionado campos na área de configuração
$settings->add($field_enabled);
$ADMIN->add('localplugins', $settings);
}
Antes de adicionarmos os demais campos, vamos ler essa opção na nossa classe tudoupper_string_manager
e habilitar ou não o recurso:
<?php
namespace local_tudoupper;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/local/tudoupper/vendor/autoload.php');
use Jawira\CaseConverter\Convert;
class tudoupper_string_manager extends \core_string_manager_standard {
public function get_string($identifier, $component = '', $a = null, $lang = null) {
$string = parent::get_string($identifier, $component, $a , $lang );
# só prosseguimos se o recurso estiver habilitado
$enabled = get_config('local_tudoupper','enabled');
if(!$enabled) return $string;
$obj = new Convert($string);
return $obj->toCamel();
}
}
Agora pela interface de configuração podemos desativar ou ativar esse recurso.
Adicionemos os demais campos:
<?php
defined('MOODLE_INTERNAL') || die();
if ($hassiteconfig) {
# Inicializando objeto admin_settingpage
$title = new lang_string('title', 'local_tudoupper');
$settings = new admin_settingpage('local_tudoupper', $title);
# Campo para habilitar ou desabilitar recurso
$enabled = new lang_string('enabled', 'local_tudoupper');
$enabled_description = new lang_string('enabled_description', 'local_tudoupper');
$field_enabled = new admin_setting_configcheckbox('local_tudoupper/enabled',$enabled,$enabled_description,1);
# Campos tipo
$type = new lang_string('type', 'local_tudoupper');
$type_description = new lang_string('type_description', 'local_tudoupper');
$type_upper = new lang_string('type_upper', 'local_tudoupper');
$type_camelcase = new lang_string('type_camelcase', 'local_tudoupper');
$default = 'upper';
$options = ['upper' => $type_upper, 'camelcase' => $type_camelcase];
$field_type = new admin_setting_configselect('local_tudoupper/type',$type, $type_description, $default, $options);
# Campo prefixo
$prefix = new lang_string('prefix', 'local_tudoupper');
$prefix_description = new lang_string('prefix_description', 'local_tudoupper');
$default = '';
$field_prefix = new admin_setting_configtext('local_tudoupper/prefix',$prefix,$prefix_description,$default);
# Campo prefixo
$suffix = new lang_string('suffix', 'local_tudoupper');
$suffix_description = new lang_string('suffix_description', 'local_tudoupper');
$default = '';
$field_suffix = new admin_setting_configtext('local_tudoupper/suffix',$suffix,$suffix_description,$default);
# Adicionado campos na área de configuração
$settings->add($field_enabled);
$settings->add($field_type);
$settings->add($field_prefix);
$settings->add($field_suffix);
$ADMIN->add('localplugins', $settings);
}
Por fim modificaremos a classe tudoupper_string_manager
para usar esses novos campos:
<?php
namespace local_tudoupper;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/local/tudoupper/vendor/autoload.php');
use Jawira\CaseConverter\Convert;
class tudoupper_string_manager extends \core_string_manager_standard {
public function get_string($identifier, $component = '', $a = null, $lang = null) {
$string = parent::get_string($identifier, $component, $a , $lang );
# só prosseguimos se o recurso estiver habilitado
$enabled = get_config('local_tudoupper','enabled');
if(!$enabled) return $string;
# prefixo e sufixo das strings
$prefix = get_config('local_tudoupper','prefix');
$suffix = get_config('local_tudoupper','suffix');
$string = $prefix . $string . $suffix;
# tipo
$type = get_config('local_tudoupper','type');
if($type == 'upper') return strtoupper($string);
if($type == 'camelcase') {
$obj = new Convert($string);
return $obj->toCamel();
}
return $string;
}
}