Migration depuis PrototypePhp

Installer CodeIgniter et Ppci

Créez un dossier différent de celui qui contient le code initial de l’application à migrer, par exemple app2, puis, depuis le répertoire de niveau inférieur :

composer create-project codeigniter4/appstarter app2
cd app2
composer require equinton/ppci
vendor/equinton/ppci/install/install.sh

Éditez ensuite le fichier .env, et mettez à jour les paramètres nécessaires (CI_ENVIRONMENT, app.baseURL et les paramètres de connexion à la base de données).

Créer un nouveau vhost dans Apache

Voici un exemple de configuration :

<VirtualHost *:80>
    ServerName app2.local
    ServerPath /app2.local
    RewriteEngine On
    RewriteRule ^ https://app2.local%{REQUEST_URI} [R]
</VirtualHost>
<VirtualHost *:443>
    ServerName app2.local
    ServerPath /app2.local
    SSLEngine on
    SSLCertificateFile  /etc/ssl/certs/server.crt
    SSLCertificateKeyFile /etc/ssl/private/server.key
    SSLCACertificateFile /etc/ssl/certs/cacert.crt
    DocumentRoot /var/www/app2/public 
</VirtualHost>
<Directory /var/www/app2/public>
    <LimitExcept GET POST>
        Deny from all
    </LimitExcept>
    Options -Indexes FollowSymLinks MultiViews
    Header unset ETag
    Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate, private"
    Header set Pragma "no-cache"
    Header set X-Frame-Options "DENY"
    Header set X-XSS-Protection "1; mode=block"
    Header set X-Content-Type-Options "nosniff"
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
    Header always set Content-Security-Policy "default-src 'self' ; script-src blob: * 'self' 'unsafe-inline' 'unsafe-eval'; connect-src data: blob: filesystem: *.tile.openstreetmap.org 'self' ; img-src 'self' data: blob: *.openstreetmap.org ; style-src 'self' 'unsafe-inline' ;"
    <FilesMatch "\.(ico|flv|jpg|jpeg|png|gif|js|css|svg)$">
        Header set Cache-Control "max-age=604800, private"
    </FilesMatch>
<FilesMatch ".*openstreetmap.*\.png$">
    Header set Cache-Control "max-age=2592000, public"
</FilesMatch>
    Require all granted
    AllowOverride all
    RewriteEngine On
    RewriteBase /
    RewriteCond "/%{REQUEST_FILENAME}" !-f
    RewriteCond "/%{REQUEST_FILENAME}" !-d
    RewriteRule "(.*)" "/index.php?$1" [PT,QSA]
</Directory>

Mettre à jour la base de données

Éditez le fichier vendor/equinton/ppci/migration/updatedb.sql, et vérifiez la première ligne (set search_path), en remplaçant app par le nom du schéma contenant les données.

Exécutez ensuite le fichier sql.

Mettre à niveau le menu

Éditez le fichier app/Config/menu.xml, et rajoutez les entrées nécessaires.

Ajouter les modèles Smarty

Recopiez les modèles Smarty depuis display/templates dans app/Views/templates en conservant l’organisation en sous-dossiers, à l’exception des fichiers à la racine et du sous-dossier framework.

Modifications globales

Dans ce dossier, remplacez tous les libellés (filtre sur *tpl) :

  • </form> par {$csrf}</form> pour ajouter le jeton CSRF dans les formulaires
  • droits par rights
  • .gestion par .manage
  • datatable" par datatable display"
  • datatable-nopaging-nosearching" par datatable-nopaging-nosearching display"
  • datatable-searching" par datatable-searching display"
  • datatable-nopaging" par datatable-nopaging display"
  • datatable-nopaging-nosort" par datatable-nopaging-nosort display"
  • datatable-nosort" par datatable-nosort display"
  • datatable-export" par datatable-export display"
  • datatable-export-paging" par datatable-export-paging display"

Supprimez

  • index.php?module=

Modifications dans chaque formulaire

Reprenez tous les liens (recherchez les balises a href) et remplacez le premier & par ?

Modifiez toutes les actions des formulaires, pour qu’ils aient cette forme :

<form class="form-horizontal" id="formName" method="post" action="moduleWrite">
<input type="hidden" name="moduleBase" value="module">

Le champ action peut être supprimé. Par contre, le champ moduleBase doit être conservé : il est utilisé pour créer l’action moduleDelete par l’intermédiaire du script javascript dans main_js.tpl.

Réécriture des modèles

Recopier les fichiers depuis modules/classes vers app/Models.

Transformations globales

Elles peuvent être effectuées par rechercher/remplacer.

  • remplacer :
    • <?php par <?php namespace App\Models;use Ppci\Models\PpciModel;, avec sauts de ligne ;
    • extends ObjetBDD par extends PpciModel ;
    • (public function __construct().*) par public function __construct(), en cochant expression régulière ;
    • $this->colonnes par $this->fields ;
    • function ecrire par function write
    • function lire par function read
    • parent::ecrire par parent::write
    • (parent::__construct().*) par parent::__construct(), en cochant expression régulière ;
    • $this->id_auto = 0 par $this->useAutoIncrement = false
    • auto_date = 0 par autoFormatDate = false
  • supprimer :
    • $this->id_auto = 1;
    • $param["fullDescription"] = 1;
    • $this->param = $param;

Transformations individuelles

  • renommer le nom du fichier, par exemple espece.class.php en Espece.php ;
  • dans les requêtes SQL, modifier les variables en rajoutant : à la fin : :id doit devenir :id: ;
  • pour les tables portant des données géographiques (champs avec type=4), modifier les requêtes ou créer les fonctions lire() pour ajouter st_astext() pour les champs concernés ;
  • les transformations de dates pour les champs non présents dans la table doivent être réécrites selon ce schéma :
$this->dateFields[] = "peche_date";
$this->datetimeFields[] = "peche_datetime";
  • si la fonction utf8_encode est utilisée, elle doit être remplacée par :
$data = mb_convert_encoding($data, 'UTF-8', 'ISO-8859-15, ISO-8859-1, Windows-1252');

La fonction traite indistinctement les chaînes ou les tableaux.

Réécriture des librairies

Recopier l’ensemble des modules dans app/Libraries. Il faut les transformer en classes.

Transformations globales

Remplacer :

  • <?php par :
<?php 
namespace App\Libraries;

use Ppci\Libraries\PpciException;
use Ppci\Libraries\PpciLibrary;
use Ppci\Models\PpciModel;

class Xx extends PpciLibrary { 
    /**
     * @var xx
     */
    protected PpciModel $dataclass;
    private $keyName;

    function __construct()
    {
        parent::__construct();
        $this->dataclass = new XXX();
        $keyName = "xxx_id";
        if (isset($_REQUEST[$this->keyName])) {
            $this->id = $_REQUEST[$this->keyName];
        }
    }
  • dataRead($dataclass, par $this->dataRead(
  • dataDelete($dataclass, par $this->dataDelete(
  • case "list": par function list(){$vue=service('Smarty'); (saut de ligne)
  • case "display": par function display(){$vue=service('Smarty'); (saut de ligne)
  • case "change": par function change(){$vue=service('Smarty'); (saut de ligne)
  • case "write": par
    function write() {
    try {
            $this->id = $this->dataWrite($_REQUEST);
            if ($this->id > 0) {
                $_REQUEST[$this->keyName] = $this->id;
                return $this->display();
            } else {
                return $this->change();
            }
        } catch (PpciException) {
            return $this->change();
        }
    }
  • case "delete": par function delete(){
  • case " par function
  • ": par () {
  • break; par } : fermeture des fonctions
  • $dataclass par $this->dataclass
  • $id par $this->id
  • $vue par $this->vue
  • $this->dataDelete($this->id); par
        try {
            $this->dataDelete($this->id);
            return $this->list();
        } catch (PpciException $e) {
            return $this->change();
        }
  • $this->dataWrite( $_REQUEST ); par
        try {
            $this->id = $this->dataWrite($_REQUEST);
            $_REQUEST["xx_id"] = $this->id;
            return $this->list();
        } catch (PpciException $e) {
            return $this->change();
        }
  • $message-> par $this->message->

et suppression de :

  • switch ($t_module["param"]) {
  • $bdd, $ObjetBDDParam

Modifications individuelles

  • renommer le fichier en le commençant par une majuscule
  • Modifier la fonction __construct() pour charger la bonne classe et le bon identifiant
  • définir les vues autres que Smarty dans les fonctions
  • définir le retour attendu de chaque fonction :
    • soit ajouter la commande return $this->vue->send(); pour déclencher l’affichage
    • soit renvoyer vers une des fonctions de la classe : return $this->display();
    • soit renvoyer vers la page d’accueil : defaultPage();

Traitement des transactions

Remplacer :

  • $bdd->beginTransaction(); par :
$db = $this->dataclass->db;
$db->transBegin();
  • supprimer $bdd->commit(); by $db->transCommit();
  • remplacer $bdd->rollback(); par :
if ($db->transEnabled) {
    $db->transRollback();
}

Générer les routes et les droits nécessaires pour exécuter les modules

Exécutez la commande suivante :

php vendor/equinton/ppci/migration/actionsParse.php ../app/param/actions.xml

Le script va lire l’ancien fichier actions.xml, et va préparer deux contenus :

  • le premier est destiné à être inséré dans la classe app\Config\Rights, et contient la liste des droits nécessaires pour exécuter un module
  • le second contient un prototype des routes pour exécuter les modules. Le contenu doit être inséré dans app/Config/Routes.php.

Renommer le droit “gestion” en “manage”

Utilisez une fonction de recherche automatique pour remplacer “gestion” par “manage”.

Ajouter les contrôleurs

Lancez le script :

php vendor/equinton/ppci/migration/generateController.php app/Config/Routes.php app/Controllers/

Le programme va lire les routes définies, puis créer les contrôleurs correspondants, en regroupant les routes par module. Les contrôleurs intègrent lles appels aux fonctions de la librairie correspondante (même nom).

Ajouter un filtre pour les opérations génériques au démarrage

  • Ajouter un filtre pour réaliser les opérations décrites dans modules/common.php ;
  • renseigner le cas échéant la classe App\Libraries\Postlogin, pour réaliser les opérations spécifiques après connexion.

Récupérer les traductions

Les traductions de Ppci sont fournies par défaut. Pour éviter de tout perdre, il faut les fusionner avec les anciennes traductions :

msgmerge app/Language/locales/lang.po ../oldapp/locales/en.po -o app/Language/locales/lang.po
cd app/Language/locales
./generate_po.sh
./compile.sh

Mettre à niveau le readme et le À propos

Éditez les fichiers suivants :

  • app/Config/news.txt pour les nouveautés en français
  • app/Config/newsen.txt pour les nouveautés en anglais

Éditez également les templates suivants :

  • app/Views/templates/about_fr.tpl
  • app/Views/templates/about_en.tpl