Desenvolupament corporatiu amb Drupal

1. Bones pràctiques

Com a bones pràctiques i de forma general per qualsevol propjecte web: 

  • Intentarem seguir les best practices del producte i els seus estàndards de codificació: https://www.drupal.org/docs/develop/standards
  • Per al javascript i els estils utilitzarem fitxers .css i .js, mai styles o scripts inline.
  • Per al HTML intentarem que el codi estigui principalment en fitxers .twig o es generi a través d'un editor WYSIWYG amb filtratge i correcció d'HTML activat.
  • Les actualitzacions i els partches es gestionen sempre via composer, i el fitxer composer.json ha d'estar al dia i reflexar els mòduls i versións que necesita el projecte.
  • Per raons de seguretat no pot haver-hi javascript en base de dades i els usuaris drupal no han de poder escrire codi javascript, tampoc l'usuari administrador.
  • El projecte s'ha d'entregar amb tots els mòduls i core a la última versió estable o a la última versió dev si fos imprescindible.
  • La web ha de complir els estàndard d'accessibilitat

2. Instal·lació del Drupal

Per desenvolupar amb Drupal 9 s'utilitzarà composer per fer la instal·lació i gestionar els patches i les depenències.

$ composer create-project drupal/recommended-project DIRECTORY-PROJECTE 9.5.*

Per evitar problemes de versions definirem la versió PHP de l'entorn en el composer.json per instal·lar les versions compatibles dels paquets i evitar incompatibilitats. Les versións PHP són: LAMP 2 = 5.3, LAMP 3 = 7.4 i LAMP3 HA = 7.4.

$ composer config platform.php 7.4.24
"prefer-stable": true,
"config": {
    "sort-packages": true,
    "process-timeout": 0,
    "platform": {
        "php": "7.4.24"
    }
}

Per seguretat el projecte disposarà d'un sobdomini que apuntarà a la carpeta /web on hi haurà el core de drupal i els mòduls, themes i fitxers de la web.

Els directori de /vendors i els fixters privats /private i les configuracions del site /config/sync aniran a l'arrel del projecte i no seràn accessibles per URL directe.

3. Afegir un nou mòdul

$ composer require 'drupal/responsivewrappers:^2.0' --prefer-dist

4. Parchejar amb un hotfix

Per afegir un patch editarem el fitxer composer.json i afegirem el fitxers de diferències el-fix-a-aplicat.patch a la secció "patches" d'aquest. Indicarem sempre una petita descripció del que fa aquell hotfix i una referència al fitxer que cal aplicar.

Exemple composer.json:

"extra": { 
  "patches": { 
    "drupal/address": { "Drupal Addess fix default syncing": "patches/address_syncing.patch" } 
  }
}

Un cop editat el composer.json un simple: $ composer update serà suficient perquè s'apliqui el hotfix.

Això garantirà que el fix es segueix aplicant automàticament al llarg de les actualitzacions i no caldrà re-aplicar els hotfixes cada cop que s'actualitza el codi.

Si enlloc de parchejar el mòdul general de tots els sites volem aplicar el hotfix només al nostre projecte farem el seguent:

  1. Copiarem el mòdul a la carpeta /web/sites/elmeuprojecte.diba.cat/modules/contrib/elmeumodul
  2. Copiarem el patch a /web/sites/elmeuprojecte.diba.cat/modules/contrib/elmeumodul/patches
  3. Editarem el composer.json del mòdul en qüestió afegint el patch
  4. Executarem un composer update des de dins de la carpeta del mòdul.

5. Actualització del codi a les últimes versions estables

$ composer update --with-dependencies --prefer-dist

6. Altres considerancions sobre les versions dels mòduls al composer

Les versions dels mòdul s'han de definit de la seguent manera:

  • Sempre que es pugui definirem només la versió mínim requerida amb ^, per exemple: "^2.0"
  • Si cal fixar una subversió, prioritàriamnet deixarem oberta les actualitzacions de bugfixing: "9.5.*"
  • Si cal finar una versió concreta ho justificarem.
  • Eliminarem el forçat de versions @RC, @beta o @alfa sempre que sigui possible, per exemple: "^2.0@beta" és una especificació a evitar perquè quan surti una versió estable ens quedarem sempre a la beta. Milllor eliminarem el @beta i actualizem el "minimum-stability":"dev" per acceptar versions beta.
"dompdf/dompdf": "2.0.3" == millor ==> "^2.0"
"drupal/address": "^1.10@beta" == millor ==> "^1.10"
"drupal/core-recomended": "9.5.2" == millor ==> "9.5.*"

7. Settings

Tots els projectes utilitzaran el settings.local.php con configuració general de la web estarà en el settings.php però els configruació específiques de l'entorn (com per exdemple l'usuari/password de la base de dades) estaran al settings.local.php.

8. Base de dades

La LAMP3HA utilitza una plataforma en alta disponibilitat amb tres nodes MariaDB. Dos nodes poden fer de master i un de slave, pel que poden configurar el sistema com a master/master/slave o master/slave/slave.

Desenvolupament:

  • su0247 (master1)

  • su0248(master2)

  • su0249(slave)

Producció:

  • su0255 (master1)

  • su0256 (master2)

  • su0257 (slave)

Tots els projectes drupal sempre definiran un prefix a les seves taules (unes poques lletres identificatives del projecte seguides d'un guió baix, per exemple: $prefix = 'db_'). Si és un projecte donat d'alta al GVUS es pot utilitzar el codi del projecte per prefixar les taules.

9. Integració amb el VUS i mòduls corporatius

La Diputació de Barcelona utilitza el proejcte VUS com a sistema de Validació d'USuaris corporatius. Actualemnt hi ha un mòdul d'integració del Drupal 8/9 amb el VUS que pots incorporar al teu projecte utilitzant el composer.

Per afegir el mòdul VUS o la sincronitzación de l'organigrama, municipis o comarques al teu projecte et cal demanar accés al repositori privat del GitLab on es manté aquest mòdul. Un cop tens un usuari amb accés simplement has d'afegir el repositori al fitxer composer.json de l'arrel del teu project, quedant de la següent forma:

"repositories": [
    {
        "type": "vcs",
        "url": "https://gitlab.com/diputacioBCN/drupal8/vus"
    },
    {
        "type": "vcs", 
        "url": "https://gitlab.com/diputacioBCN/drupal8/taxonomy_dibasync" 
    },
    {
        "type": "vcs",
        "url": "https://gitlab.com/diputacioBCN/drupal8/tag-manager-cookie-warn"
    }
]

I requerir el mòdul en el teu projecte amb la instrucció:

composer require 'drupal/vus'
composer require 'drupal/taxonomy_dibasync'
composer require 'drupal/tag_manager_cookie_warn'

Aquesta comanda afegirà automàticament la darerra versió del mòdul al teu projecte i l'actualitzarà cada cop que surti una nova versió i llencis un: composer udpate del teu projecte.

Un cop hagis incorporat el mòdul del VUS al teu projecte simplement has de desplegar el codi i activar el mòdul a la teva instal·lació del Drupal.

10. Mòduls no recomanats

No usarem moduls de Drupal que hagin tingut molt poc us, és a dir, que a la informació del projecte digui que el mòdul l'estan usant molt pocs sites.

El mòdul reCAPTCHA no és gratuït per la nostra organtizació, per tant, no l'usarem. Mireu el mòdul Diba starterkit per altres substituts.

11. Esborrat de fitxers no utilitzats

Per tal de no acumular fitxer innecesàris cal marcat al fitxer settings.php o settings.local.php la variable:

$config['file.settings']['make_unused_managed_files_temporary'] = TRUE;

Sinó els fitxers o imatges que algún cop s'han pujat al servidor no s'esborren MAI.

Aquesta configuració NO es retroactiva, pel que si cal fer neteja i revisar els fitxers i imatges no utilitzats al servidor es poden utilitzar mòduls com Audit FilesFancy file delete o File Delete.

12. Disseny corporatiu

Per fer webs amb disseny corporatiu hi ha un tema que ja aplica el disseny corporatiu. Es recomana que creis un sub-tema pel teu proejcte per tal de poder sobre-escriure tot allò que encesitis del tema original.

Diba Core, és el tema corporatiu mantingut que alhora és un subtema del tema Boostrap Barrio basat en Bootstrap 4: https://www.drupal.org/project/diba_core

Instal·lació:

composer require 'drupal/diba_core:^2.0'

Per crear el teu sub-tema del projecte el fitxer el-meu-tema.info.yml hauria de tenir un format silimar a això:

name: El meu tema
type: theme
description: 'Tema del meu projecte desenvolupat per XYZ.'
base theme: diba_core

Nota: Això només aplica en el cas de fer una web amb disseny corporatiu complet.

13. Llibreries JS

Si el teu projecte utilitza llibreries, cal vincular la seva actualització via composer.

Per fer això farem el següent:

  • Executar: composer require --prefer-dist composer/installers. Aquest paquet facilit la instal·lació amb el composer de paquets en directoris diferents al "/vendors" (per  exemple "/libraries").
  • Ala secció: "installer-paths" del "composer.json" assegurat que existeix la ruta: "web/libraries/{$name}": ["type:drupal-library"],
  • Afegieix les llibreries JS a la secció "repositories" del composer.json que vols utilitzar. Per exemple, si volem afegir la llibreria del Google Charts simplement afegim el seu repositori com un repositori més:
"repositories": [
        {
            "type": "package",
            "package": {
                "name": "google/charts",
                "version": "45",
                "type": "drupal-library",
                "extra": {
                    "installer-name": "google_charts"
                },
                "dist": {
                    "url": "https://www.gstatic.com/charts/loader.js",
                    "type": "file"
                },
                "require": {
                    "composer/installers": "~1.0"
                }
            }
        }
]
  • I per últim podem llençar la següent comanda per afegir la dependencia de la nova llibreria pel nostre projecte i es descarregarà i actualitzarà la llibreria a la carpeta /libraries del nostre projecte amb totes les seves dependències: composer require --prefer-dist google/charts:45

Exemple referenciant una llibreria externa compactada en un zip (Chosen):

        {
            "type": "package",
            "package": {
                "name": "harvesthq/chosen",
                "version": "1.8.7",
                "type": "drupal-library",
                "extra": {
                    "installer-name": "chosen"
                },
                "dist": {
                    "url": "https://github.com/harvesthq/chosen/releases/download/v1.8.7/chosen_v1.8.7.zip",
                    "type": "zip"
                },
                "require": {
                    "composer/installers": "~1.0"
                }
            }
        }

Per efegir-la:

 composer require harvesthq/chosen:1.8.7

Exemple d'un fitxer d'un projecte corporatiu: composer.json

14. Composer Merge Plugin

Si un mòdul utilitza vàries llibreries externes, per exemple múltiples llibreries JS es una bona pràctica que el mateix mòdul defineixi les seves dependències en el seu propi ftxer de configuració i utilitzar el Composer Merge Plugin per afegir descarregar totes les llibreris externes.

Un exemple concret són les llibreries que utiltza el mòdul Webform, i que és la via recomanada per instal·lar-les:

https://www.drupal.org/node/3003140

15. Altres mòduls corporatius per a Drupal

Per tal de donar resposta a altres necesitats la Diputació de Barcelona s'han desenvolupat altres mòduls que poden ser d'utilitat pels projectes de la corporació:

16. Usuaris i rols d'usuari

Per defecte sempre ha d'existir un usuari amb rol superadministrador amb nom: admindiba, que correspondrà a l'usuari amb identificador 1 i serà l'utilitzat per l'Oficina Tècnica d'Internet per administrar la web i tindrà tots els permisos.

A més, també caldrà crear un rol editor SEMPRE, amb els permissos d'edició de continguts i que és el que utilitzaran els editors de la web. Aquest rol no ha de tenir capacitats per activar nous mòduls o fer tasques d'administració.

Segons les necessitats del projecte es crearan tants rols adicionals com perfils existeixin.

17. Reverse Proxy

L'entorn de producció utilitza un reverse proxy pel que cal configurar-lo als settings:

$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = [@$_SERVER['REMOTE_ADDR']];
$settings['reverse_proxy_trusted_headers'] = \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_HOST | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO | \Symfony\Component\HttpFoundation\Request::HEADER_FORWARDED;

18. Settings

Definirem el directori de fitxers privats, de configuració i de temporals fora de la part accesible per url i dins de la carpeta del projecte:

$settings["config_sync_directory"] = '../config/sync';
​$settings['file_private_path'] = '../private';
$settings['file_temp_path'] = '../private/tmp';

19. Diba starterkit

Per facilitar la gestió de dependències i que els projectes Drupal de la Diputació de Barcelona comparteixin solucions comunes s'ha creat el mòdul "diba_starterkit" que instal·la i configura una sèrie de mòduls i configuracions de forma comuna. Aquest mòdul te varis "kits" que inclou més o menys funcionalitats en funció del projecte.

Es pot utilitzar el starterkit que més s'ajusti al vostre projecte i després ampliar amb altres mòduls i dependencies.

En els servidors de la diba és necessari tenir instal.lat com a mínim el bàsic, ja que el mòdul neteja carpeta tmp, que a vegades és desborda per temporals creats per timeout, en aplicacions com backup&migrate.

19.1. Bàsic: estadístiques + anti spam + urls amigables + backups

$ composer require 'drupal/diba_starterkit:^2.0'

19.2. Core: bàsic + estadístiques amb gràfics + field groups + file paths

$ composer require 'drupal/diba_starterkit_core:^2.0'
$ composer require 'drupal/diba_starterkit_standard:^2.0'

20. Continguts paginats, exportació de continguts, generació de pdfs, Excel, csv, etc..

Els recursos del servidor son limitats, per tant, a l'igual que les cerques de contingut no poden mostrar infinits resultats ja que això relentiria molt la web i s'han de paginar, s’ha de preveure que si és genera un fitxer, d’un o varis continguts que poden anar creixent amb el temps, la descarregar del fitxer s'ha de fer en diversos fitxers. Una solució és fer que el fitxer a descarregar sigui el resultat d'una cerca paginada, així que cada pàgina permet descarregar un fitxer nou. Tingueu en conta que afegir imatges, consumeix molts recursos, així que intenteu afegir el mínim d'imatges i el més optimitzades possibles.

21. Composer i timeout

Si a l'executar composer, aquest dona problemes de timeout, és poden afegir les següents instruccions:

    "config": {
        "process-timeout": 0,
    },

22. Pasos mínims en el desenvolupament d'un nou producte

  1. Abans d'iniciar el projecte:
    • L'empresa que fa el desenvolupament ha de realitzar una reunió amb els tècnics d'informàtica per pactar tecnologies, versions i solucions. NO ÉS POT INICIAR EL DESENVOLUPAMENT SENSE UNA REUNIÓ TÈCNICA PRÈVIA AMB EL SERVEI D'INFORMÀTICA.
    • Es llegiran i seguiran les pràctiques descrites en aquest docuemnt.
  2. Abans d'entregar el projecte:
    • El servei client de la Diputació ha d'haver validat i revisat el projecte a nivell funcional previament abans de l'entrega del projecte al servei d'informàtica amb contingut realista i de prova.
    • S'ha de facilitar un url d'accés o un projecte dockeritzat amb continguts realistes i un usuari d'administrador al servei d'informàtica per poder fer una revisó inicial abans de cap entrega o instal·lació als servidors corporatius.
    • S'ha de facilitar en tot moment abans de cap entrega o instal·lació fitxers clau com el: composer.json per a una revisió inicial.
  3. Entrega del projecte:
    • S'entregarà el projecte sense vendors ni libraries, amb un composer.json funcional i capaç de generar tots els vendors i libraries executant la comanda: composer install. Si el composer install no funciona correctament no s'acceptarà l'entrega.
    • Les versions del core i mòduls entregats no poden tenir pendent cap actualització de seguretat, i cal tenir la resta de mòduls i llibreries el més actualitzats possible. Si hi ha actualitzacions de seguretat pendents o actualitzacions de bugfixing pendents des de fa més de 3 mesos no s'acceptarà l'entrega.
    • El servei d'informàtica revisarà el codi del projecte i envirà feedback de coses a solucionar abans de cap instal·lació.

23. Revisions finals

  • El composer.json només ha de tenir els mòduls necessaris i utilitzats, feu neteja de mòduls si no s'utilitzen.
  • En el composer.json, els pegats de seguretat de Drupal han de tenir el codi de referencia de Drupal, per trobar-los amb facilitat.
  • El mòdul devel no ha d'estar actiu.
  • Per seguretat, només han d'estar actives les vistes o formularis utilitzats, deshabiliteu els que no s'utilitzin com la vista search o el formulari de contacte, si no s'utilitza.
  • El cercador per defecte de drupal (search), si no s'utilitza, treieu-li els permisos d'accés als usuaris anònim o als usuaris que no hagin de tenir accés: /admin/people/permissions
  • No permeteu que els usuaris anònims puguin crear nous usuaris si no és estrictament necessari, i sempre requeriu la confirmació del correu i a ser possible l'aprovació d'un administrador.
  • Oculteu els misatges d'error: /admin/config/development/logging
  • Reviseu el log d'error de Drupal (/admin/reports/dblog), aquest no pot generar avisos de themes, blocks, hooks, etc.. no trobats , ni errors de cap tipus.