Nesse tutorial iremos criar um módulo para o Drupal, o foco aqui será entendermos a estrutura do módulo em si, e não em criarmos algo super complexo.

O que é Drupal?

Drupal é um CMS (Content management system) de código aberto fantástico através do qual você pode construir sites modernos. Sejam eles blogs pessoais ou um e-commerce.

O que são módulos?

Um módulo é um código que altera ou adiciona uma funcionalidade ao Drupal. Você pode usar módulos criados pela comunidade ou criar os seus próprios.

Drupal Vs. WordPress

É impossível citar um CMS sem mencionar também o WordPress, o processo de escolha do CMS certo é um passo extremamente importante. Escolher a plataforma errada e você terá uma batalha difícil logo no início do seu projeto. No geral, o Drupal é um CMS bastante sólido, possui muitos recursos e é otimizado para desempenho e segurança de alto nível desde o primeiro dia. é muito flexível, mas tem uma curva de aprendizado maior. Se você não tem tempo para aprender a programar e quer construir um site o mais rápido possível, considere usar o WordPress.

Iniciando o projeto

Para esse Projeto iremos utilizar vamos precisar do Lando e do Composer.

Vamos Iniciar um novo projeto Drupal com o composer:

composer create-project drupal/recommended-project drupal_project

Abrimos o diretório do projeto:

cd drupal_project

E criamos a configuração do Lando:

lando init

Nas telas a seguir selecionamos as opções:

# From where should we get your app's codebase?
❯ current working directory
# From where should we get your app's codebase? current working directory
# What recipe do you want to use?
❯ drupal9
# Where is your webroot relative to the init destination?
web
# What do you want to call this app?
drupal_project

E podemos iniciar o projeto com:

lando start

Tenha calma, esse processo pode demorar um pouco dependo das imagens docker que serão baixadas e sua conexão com a internet.

Assim que finalizado você verá as informações do projeto na tela, mas pode ver à qualquer momento com:

lando info

Para agilizar o processo de instalação iremos utilizar o drush, que é uma ferramenta de linha de comando para o Drupal.

Primeiro, instalamos o drush:

lando composer require drush/drush

E com ele instalamos o Drupal:

lando drush site:install --db-url=mysql://drupal9:drupal9@database/drupal9 -y

A senha do administrador aparacerá na tela, não se esqueça de anotar.

Com isso, como mágica temos o Drupal instalado, você pode acessá-lo em https://drupal_project.lndo.site.

Captura de tela inicial do Drupal

E com isso temos um ambiente de desenvolvimento para o Drupal configurado.

Criando o módulo

Antes de tudo

Antes de começar aqui fica uma dica importante, o Drupal cria caches das páginas e com isso as vezes nossas alterações parecem não terem efeito, é muito importante limpar-mos esse cache para ter certeza, basta utilizarmos o comando:

lando drush cr

A ideia do módulo

Lembrando que o foco aqui é você ter uma noção de como a estrutura de um módulo funciona, não iremos criar nada complexo por enquanto, mas será um ótimo começo.

Com isso vamos criar um módulo para adicionar uma política de uso no formulário cadastro de usuário.

A estrutura do módulo

Essa será a estrutura do nosso módulo:

Estrutura do módulo

Vamos passar por cada um destes arquivos.

Iniciando o módulo

module.info.yml

Para o Drupal entender um diretório como módulo precisamos criar o .info.yml.

Vamos criar a pasta do modulo em web/modules/custom/policy e, importante saber, o nome do diretório e arquivos .yml deverão seguir o mesmo padrão, no nosso caso a pasta policy conterá o arquivo policy.info.yml.

Com essa informação vamos criar o arquivo web/modules/custom/policy/policy.info.yml com o seguinte conteúdo:

name: Policy
description: "Custom module to manage the Policy terms"
package: Custom
core_version_requirement: ^8 || ^9
type: module

Só com isso se formos em https://drupal_project.lndo.site/admin/modules já veremos o módulo Policy aparecendo.

Salvando as configurações de nossa politica no banco de dados

module.schema.yml

Vamos criar um local onde iremos utilizar para armazenar nossos termos, onde fique mais fácil alterarmos no futuro, para isso vamos criar um schema de configuração, onde será possível alterar sempre que necessário.

Vamos criar o arquivo web/modules/custom/policy/config/schema/policy.schema.yml com o seguinte conteúdo:

policy.settings:
  type: config_object
  label: "Policy Content Type Settings"
  mapping:
    title:
      type: text
      label: "Title"
    message:
      type: text
      label: "Policy terms"

module.settings.yml

O arquivo .settings.yml será o valor padrão dessas configurações, criado no momento que o módulo é instalado, então criamos o arquivo web/modules/custom/policy/config/install/policy.settings.yml com o seguinte conteúdo:

title: "Policy terms"
message:
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam a facilisis dolor, aliquam ullamcorper odio. Ut sollicitudin imperdiet ante, quis placerat sapien. Fusce sed vestibulum nisi. Morbi vel rhoncus dui, eu semper dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed pulvinar lorem eros, et fringilla arcu blandit nec. Praesent sem nunc, hendrerit vitae arcu at, rhoncus sagittis est. Fusce ultrices venenatis rhoncus.
  Duis euismod, elit semper ultrices molestie, eros elit cursus diam, eu cursus justo urna vel lacus. Donec ornare efficitur pulvinar. Suspendisse pulvinar ipsum ipsum. Vestibulum eu fermentum felis, ut accumsan nibh. Proin blandit urna arcu, at posuere nunc hendrerit at. Sed finibus diam vel vulputate mollis. Quisque feugiat iaculis aliquet. Duis auctor enim a risus tincidunt bibendum. Proin augue tellus, finibus quis lorem interdum, mattis condimentum nunc. Nam et condimentum nibh. Sed eleifend sapien a massa sollicitudin vestibulum. Donec fringilla elit nisi, et pretium dolor dapibus in.
  Aliquam ac est vestibulum, tempus odio quis, tempor leo. Quisque dui eros, laoreet id diam ac, consectetur ultrices lorem. Duis augue ante, venenatis ac mollis sed, posuere in purus. Vivamus magna tortor, fringilla eget felis sed, mattis finibus magna. Proin mauris dui, tempor ut ante id, aliquam ultrices nisi. Aenean pulvinar sapien at enim sagittis vehicula. Donec tristique sapien eget felis tincidunt, ut commodo magna pulvinar. Quisque vel tempor dui.
  Phasellus luctus dolor sed odio pharetra, et interdum libero sollicitudin. Proin facilisis justo ac felis bibendum, ut commodo tellus lacinia. Fusce viverra eget augue nec aliquam. Quisque leo tortor, volutpat a facilisis tincidunt, molestie ut ante. Maecenas ornare commodo lacus, nec lobortis eros finibus eget. Nulla at nulla nec orci vehicula egestas semper viverra tellus. In scelerisque neque ac urna vulputate aliquet. Maecenas ultrices imperdiet ligula, eu commodo nisi. Praesent sodales felis metus, sed ultrices ipsum sodales ut. Pellentesque faucibus ligula risus, at ornare metus varius sit amet. Donec mollis non urna ut auctor. In imperdiet arcu ex, non vulputate tortor bibendum rutrum. Phasellus convallis metus in imperdiet finibus. Aenean maximus eget nibh quis interdum.
  Fusce dictum, metus at tempus tincidunt, tortor tortor porta leo, non aliquam metus arcu in sem. Pellentesque vel nulla orci. Aliquam dolor elit, accumsan vel libero et, viverra auctor augue. Sed vulputate volutpat leo, nec euismod mauris congue ullamcorper. Curabitur quis diam vestibulum, aliquam nisi nec, vehicula lacus. Sed id luctus lorem. Praesent et ante vel arcu hendrerit efficitur vitae eu augue. Phasellus vulputate metus ac sapien cursus mattis. Donec nisl enim, ornare id tortor vitae, fermentum sodales sem. Nam et ligula nec purus bibendum scelerisque. Aliquam quis enim ut nibh placerat facilisis vestibulum sed arcu. Nunc eu orci eu nunc ultricies blandit eget a lorem."

Criando nossa página de Politica

Para exibir exibir esse conteúdo em uma página vamos precisar criar um controller e uma rota pra que seja exibido em /policy do nosso site.

Criando o controller

Criamos o arquivo web/modules/custom/policy/src/Controler/PolicyController.php com:

<?php

namespace Drupal\policy\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Config\ConfigFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Controller for display a Policy terms.
 */
class PolicyController extends ControllerBase {

  /**
   * Config object for PolicyController configuration.
   *
   * @var \Drupal\Core\Config\Config
   */
  protected $config;

  /**
   * PolicyController constructor.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   Configuration object factory.
   */
  public function __construct(ConfigFactoryInterface $config_factory) {
    $this->config = $config_factory->get('policy.settings');
  }

  /**
   * {@inheritdoc}
   *
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   The Drupal service container.
   *
   * @return static
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('config.factory')
    );
  }

  /**
   * {@inheritDoc}
   */
  public function content() {
    $message = $this->config->get('message');
    return [
      '#type' => 'markup',
      '#markup' => $message,
    ];
  }
}

Criando a rota

Vamos criar também um arquvio de rota onde chamará nosso controller exibindo as políticas em web/modules/custom/policy/policy.routing.yml com:

policy.content:
  path: "/policy"
  defaults:
    _controller: '\Drupal\policy\Controller\PolicyController::content'
    _title: "Policy terms"
  requirements:
    _permission: "access content"

E acessando o /policy já podemos ver nossa página de politicas.

Conheça as Hooks

Hooks, ou ganchos, em uma tradução livre, são métodos que conseguem alterar um comportamento padrão do Drupal, assim como os nomes dos arquivos eles devem seguir um padrão de nome para funcionarem corretamente.

No nosso caso criaremos uma hook para alterar o funcionamento da página de registro de novo usuário, localizado em /user/register para adicionarmos um checkbox contendo um link para as políticas do site.

module.module

O arquivo .module é onde criaremos nossos hooks, ele é tratado como um arquivo .php mas devemos manter o padrão do nome, para isso vamos criar o aquivoweb/modules/custom/policy/policy.module com:

<?php

use Drupal\Core\Url;
use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_user_register_form_alter().
 */
function policy_form_user_register_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['policy_terms'] = [
    '#type' => 'checkbox',
    '#default_value' => FALSE,
    '#title' => t('I have read and accept <a href="@policy_terms"  target="_blank" }" >the policy terms</a>.', ['@policy_terms' => Url::fromRoute('policy.content')->toString()]),
    '#required' => TRUE,
  ];
}

Reparem que não estamos exatamente utilizando um HTML puro, estamos usando a API do Drupal para adicionarmos um elemento e ele se encarrega de gerar um o código na página, se formos em nossa página de cadastro veremos a checkbox já está aparecendo.

Abrindo a política em um modal

Por mais que nosso checkbox já esteja funcionando não vejo necessidade de abrir uma nova página ao clicar no link the policy terms, mas ainda assim acho importante termos a página /policy para usarmos em outro local, e é aqui que a o Drupal brilha mais uma vez, vamos modificar nosso arquivo policy.module para que a página seja aberta em um modal, e bastar fazermos a seguinte alteração:

-   '#title' => t('I have read and accept <a href="@policy_terms"  target="_blank" }" >the policy terms</a>.', ['@policy_terms' => Url::fromRoute('policy.content')->toString()]),
+   '#title' => t('I have read and accept <a href="@policy_terms"  target="_blank" class="use-ajax" data-dialog-options="{&quot;width&quot;:&quot;60vw&quot; }"  data-toggle="modal" data-dialog-type="modal">the policy terms</a>.', ['@policy_terms' => Url::fromRoute('policy.content')->toString()]),

Lembre-se de limpar o cache antes de testar.

E assim, como mágica, o Drupal abre a página em um modal, e ainda mantém a nossa rota, demais né?

Alterando nossas configurações

Com tudo criado e funcionando ainda nos resta criarmos uma forma de alteramos nossas políticas quando necessário, para isso criamos um arquivo web/modules/custom/policy/src/Form/PolicySettingsForm.php com:

<?php

namespace Drupal\policy\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Defines a form to update the Policy message config.
 */
class PolicySettingsForm extends ConfigFormBase {

  /**
   * {@inheritDoc}
   */
  public function getFormId() {
    return 'policy_form_update';
  }

  /**
   * {@inheritDoc}
   */
  protected function getEditableConfigNames() {
    return [
      'policy.settings',
    ];
  }

  /**
   * {@inheritDoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    // Form Constructor.
    $form = parent::buildForm($form, $form_state);
    $config = $this->config('policy.settings');
    $form['message'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Update Policy Terms'),
      '#default_value' => $config->get('message'),
      '#description' => $this->t('Write policy terms'),
    ];
    return $form;
  }

  /**
   * {@inheritDoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $config = $this->config('policy.settings');
    $config->set('message', $form_state->getValue('message'));
    $config->save();
    return parent::submitForm($form, $form_state);
  }
}

E voltamos no aqrquivo web/modules/custom/policy/policy.routing.yml e no final dele adicionamos:

...

policy.form_update:
  path: "/admin/config/content/policy"
  defaults:
    _form: '\Drupal\policy\Form\PolicySettingsForm'
    _title: "Update Policy Terms"
  requirements:
    _role: "administrator"

Então ao acessarmos o endereço /admin/config/content/policy com um usuário adminsitrador veremos a seguinte página:

Editando políticas do site

Para facilitar mais um pouco vamos criar um link dentro do painel de administrativo para podermos acessar essas configuraçoões, assim não precisamos lembra sempre desse endereço quando formos alterar.

E como tudo até o momento basta criarmos o arquivo web/modules/custom/policy/policy.link.menu.yml com:

policy.form_update:
  title: "Policy Terms Settings"
  description: "Update policy terms"
  route_name: policy.form_update
  parent: system.admin_config_content
  weight: 10

Então se clicarmos em Configuration no menu administrativo veremos o link Policy Terms Settings.

Com isso temos nosso módulo finalizado.

O código deste tutorial está neste repositório do GitHub .