5.4 Hook

Dans ce chapitre, vous allez utiliser la notion de hook (hameçons).

5.4.1 Objectifs

  • Calcul automatique d'un tableau de référentiel,
  • Contrôle à la création d'un document,
  • Ajout de JS/CSS dans les formulaires.

5.4.2 Théorie

Les hooks sont des méthodes de la classe Doc qui sont appelées à différents moments clefs de la vie du document.

Dynacase propose deux types de hooks :

  • pre : les hooks de pre sont exécutés avant une action et peuvent annuler cette action,
  • post : les hooks de post sont exécutés après une action.

La liste des hooks standards est dans la documentation.

5.4.3 Cadre

Lors de la phase de spécification, les éléments suivants ont été identifiés. L'application nécessite :

  • pour les Audits :
    • le tableau des Fiches de non conformité doit être calculé automatiquement et non modifiable,
    • la duplication d'un audit peut-être effectuée mais la date d'audit doit être vidée automatiquement,
    • lorsque la fin de l'audit est dépassée un message doit être affiché pour avertir les utilisateurs,
  • pour les Référentiels de qualité :
    • un référentiel de qualité ne peut pas être supprimé tant que qu'il existe des chapitres associés à ce référentiel.

5.4.4 Automatisation du calcul d'un tableau

Vous allez mettre en place la logique permettant de calculer automatiquement le tableau des Fiches de non conformité.

Ouvrez le fichier ./COGIP_AUDIT/COGIP_AUDIT_AUDIT__CLASS.php et ajoutez la fonction suivante :

/**
 * Compute the FNC attributes content
 * 
 * @return string
 */
public function computeFNC() {
    $err = "";
    $fncs = array();
    $search = new \SearchDoc('', 'COGIP_AUDIT_FNC');
    $search->setObjectReturn();
    $search->addFilter("%s = '%d'",
        \Dcp\AttributeIdentifiers\COGIP_AUDIT_FNC::caf_audit,
        $this->getPropertyValue("initid")
    );
    foreach($search->getDocumentList() as $currentFNC) {
        /* @var \Dcp\Family\COGIP_AUDIT_FNC $currentFNC */
        $fncs[] = $currentFNC->getPropertyValue("initid");
     }
    $err .= $this->setValue(MyAttributes::caa_fnc_fnc, $fncs);
    if ($err) {
        $err = __FILE__.":".__LINE__.":".__METHOD__." ".$err."\n";
    }
    return $err;
 }

Cette méthode est assez proche de celles écrites dans le chapitre de paramétrage pour les aides à la saisie.

Les point suivants sont intéressants :

  • le filtre de la recherche est fait sur l'initid du document en cours,
  • le setValue est fait avec un array car l'attribut caa_fnc_fnc est multiple,
  • la gestion des erreurs dans Dynacase est faite principalement par le retour de la fonction : celle-ci renvoie une chaîne de caractères décrivant l'erreur en cours et une chaîne vide lorsque la fonction n'a pas échoué.

Surchargez ensuite la fonction postStore, cette fonction est appelée automatiquement après chaque enregistrement du document :

public function postStore() {
    $err = parent::postStore();
    $err .= $this->computeFNC();
    if ($err) {
        error_log(__FILE__ . ":" . __LINE__ . ":" . __METHOD__ . " " . $err . "\n");
    }
}

Il est conseillé de ne pas mettre le code métier directement dans la fonction postStore. Il est ainsi possible de surcharger dans les familles filles les fonctions appelées dans les hooks plus facilement.

Vous remarquerez que la méthode computeFNC ne sauvegarde pas les modifications qu'elle effectue (elle n'appelle pas store). En effet, les hooks font automatiquement cette sauvegarde lorsque nécessaire. De plus, cela permet d'appeler les méthodes concernées en dehors des hooks, sans surcoût particulier.

Vous pouvez retrouver le fichier PHP complété dans les sources.

5.4.4.1 Problèmes

A ce stade si vous déployez les sources modifiées, le formulaire calcule automatiquement la valeur de l'attribut caa_fnc_fnc, il reste deux points à résoudre :

  • lors de la modification de l'audit, les utilisateurs peuvent toujours modifier la valeur de l'attribut dans le formulaire,
  • le calcul est effectué seulement lors de la sauvegarde du document audit. Si des fiches de non-conformités sont ajoutées, alors que l'audit n'est pas modifié, l'attribut caa_fnc_fnc n'est pas à mis à jour.

Pour corriger le premier point, ouvrez le fichier ./COGIP_AUDIT/COGIP_AUDIT_AUDIT__STRUCT.csv et modifiez la visibilité du tableau des Fiches de non-conformité pour le rendre statique. Modifiez la colonne I :

  • pour l'attribut caa_a_fnc, passez la valeur de W à U,
  • pour l'attribut caac_fnc_fnc, passez la valeur de W à S.

La liste des fiches de non conformité n'est plus modifiable dans les audits en modification.

Vous pouvez retrouver le fichier CSV complété dans les sources.

Pour corriger le second point, vous devez modifier la fiche de non conformité pour que, lors de sa sauvegarde, elle mette à jour l'audit associé. Ouvrez le fichier ./COGIP_AUDIT/COGIP_AUDIT_FNC__CLASS.php et ajoutez la fonction suivante :

/**
 -   Refresh the list of the audit
 * 
 * @return string
 */
public function refreshAudit() {
    $err = "";
    $audit = $this->getAttributeValue(MyAttributes::caf_audit);
    $audit = new_Doc("", $audit, true);
    /* @var \Dcp\Family\COGIP_AUDIT_AUDIT $audit */
    $err .= $audit->computeFNC();
    $err .= $audit->store();
    if ($err) {
        $err = __FILE__ . ":" . __LINE__ . ":" . __METHOD__ . " " . $err . "\n";
    }
    return $err;
 }

Ensuite surchargez la fonction postStore :

/**
 * Hook executed after the store
 *
 * @return string|void
 */
public function postStore() {
    $err = parent::postStore();
    $err .= $this->refreshAudit();
    if ($err) {
        error_log(__FILE__ . ":" . __LINE__ . ":" . __METHOD__ . " " . $err . "\n");
    }
}

Attention à bien appeler le parent lors de la surcharge de la fonction de hook, sinon le code des classes parentes ne serait pas appelé.

Vous pouvez retrouver le fichier PHP complété dans les sources.

5.4.5 Duplication

Vous allez mettre en place un traitement après la duplication d'un audit pour supprimer les dates de l'audit dans le nouveau document créé par duplication.

Les liens vers les fiches de non-conformité sont re-calculé automatiquement après la duplication de la page (car ils sont enregistrés au postStore), il est donc inutile de les supprimer après la duplication.

Ouvrez ./COGIP_AUDIT/COGIP_AUDIT_AUDIT__CLASS.php et ajoutez la fonction suivante :

/**
 * Clean constat date
 *
 * @return string
 */
public function cleanDate() {
    $err = "";
    $err .= $this->clearValue(MyAttributes::caa_date_debut);
    $err .= $this->clearValue(MyAttributes::caa_date_fin);
    $err .= $this->clearValue(MyAttributes::caa_duree);
    if ($err) {
        $err = __FILE__ . ":" . __LINE__ . ":" . __METHOD__ . " " . $err . "\n";
    }
    return $err;
}

Cette fonction utilise clearValue qui permet de vider la valeur d'un attribut.

Ajoutez ensuite la fonction suivante :

public function postDuplicate($copyFrom) {
    $err = parent::postDuplicate($copyFrom);
    $err .= $this->cleanDate();
    if ($err) {
        error_log(__FILE__ . ":" . __LINE__ . ":" . __METHOD__ . " " . $err . "\n");
    }
}

Attention à penser à transmettre le paramètre $copyFrom au parent.

Si vous souhaitez tester, vous pouvez générer le paquet <devtool> generateWebinst -s . et le déployer. Vous pouvez ensuite dupliquer le document en utilisant le menu du document Autres > Dupliquer.

Vous pouvez retrouver le fichier PHP complété dans les sources.

5.4.6 Affichage d'un message aux utilisateurs

Vous allez maintenant mettre en place l'affichage conditionnel d'un message aux utilisateurs lorsque la date de fin d'audit est dépassée.

Ouvrez ./COGIP_AUDIT/COGIP_AUDIT_AUDIT__CLASS.php et ajoutez la fonction suivante :

/**
 * Check if the end date is in the past
 *
 * @return string
 */
public function checkEndDate()
{
    $err = "";
    $date = $this->getAttributeValue(MyAttributes::caa_date_fin);
    if (!empty($date) && $this->getAttributeValue(MyAttributes::caa_date_fin) < new \DateTime()) {
        $err = ___("The end date of the audit is in the past", "COGIP_AUDIT:AUDIT");
    }
    return $err;
}

Ajoutez ensuite la fonction suivante :

/**
 * Hook executed after the refresh
 * 
 * @return string
 */
public function postRefresh() {
    $err = parent::postRefresh();
    $err .= $this->checkEndDate();
    return $err;
}

Si vous souhaitez tester, vous pouvez générer le paquet <devtool> generateWebinst -s . et le déployer.

Une fois le code déployé si la date de fin d'audit est dans le passé vous avez le message suivant qui s'affiche :

Message utilisateur

Figure 56. Message utilisateur

Vous pouvez retrouver le fichier PHP complété dans les sources.

5.4.7 Contrôle à la suppression

Vous allez mettre en place un contrôle à la suppression.

Ouvrez ./COGIP_AUDIT/COGIP_AUDIT_REFERENTIEL__CLASS.php et ajoutez la fonction suivante :

/**
 * Check if exist chapter associated to the current referentiel
 * 
 * @return string
 */
public function checkIfAssociatedChapterExist() {
    $return = "";
    $search = new \SearchDoc("", "COGIP_AUDIT_CHAPITRE");
    $search->addFilter("%s = '%d'",
        \Dcp\AttributeIdentifiers\COGIP_AUDIT_CHAPITRE::cac_ref,
        $this->getPropertyValue("initid")
    );
    $search->setSlice(1);
    $nb = $search->onlyCount();
    if ($nb > 0) {
        $return = ___("You have to delete all associated chapter before delete the ref", "COGIP_AUDIT:REFERENTIEL");
    }
    return $return;
}

Cette fonction effectue une recherche et possède les spécificités suivantes :

  • setSlice : cette fonction indique le nombre maximum de retour de la recherche. Dans votre cas, la présence d'un seul élément suffit pour enclencher le rejet de la suppression et limiter la recherche à un élément permet de l'accélérer,
  • onlyCount : cette fonction indique que l'on ne souhaite pas lancer la recherche mais juste compter le nombre de résultats de celle-ci.

Ajoutez ensuite la fonction suivante :

public function preDelete() {
    $msg = parent::preDelete();
    $msg .= $this->checkIfAssociatedChapterExist();
    return $msg;
}

Vous pouvez retrouver le fichier PHP complété dans les sources.

5.4.8 Injection de JS ou CSS

Pour finir ce chapitre, le service qualité a jeté un coup d'œil sur vos ajouts et aimerait que le message envoyé aux utilisateurs soit moins anxiogène et donc moins rouge.

Vous allez donc ajouter une CSS pour obtenir ce comportement.

Ajoutez le fichier ./COGIP_AUDIT/Layout/specRefresh.css :

.COREErrorBg {
    color: rgb(255, 173, 0);
}

Ce fichier définit la couleur de background des erreurs en orange.

Ouvrez le fichier ./COGIP_AUDIT/COGIP_AUDIT_BASE__CLASS.php et ajoutez la fonction suivante :

/**
 * Inject a CSS
 */
public function addCSS() {
    global $action;
    $action->parent->addCssRef("COGIP_AUDIT:specRefresh.css");
}

Cette méthode fait appel à la fonction addCssRef, elle permet d'ajouter une CSS à un document.

Vous allez maintenant ajouter les fonctions suivantes :

public function preEdition() {
    $err = parent::preEdition();
    $this->addCSS();
    return $err;
}
 
public function preConsultation() {
    $err = parent::preConsultation();
    $this->addCSS();
    return $err;
}

Les deux fonctions ajoutées s’exécutent respectivement avant l'édition et avant la consultation. La CSS définie ci-dessus est ajoutée dans le formulaire.

Vous pouvez retrouver les sources complétées dans les sources.

5.4.9 Mise en place des modifications

Vous allez maintenant déployer vos modifications :

<devtool> deploy -s . --url http://admin:anakeen@<nomDeDomaine>/dynacase-control/ --port <port> --context dynacase

Vous pouvez ensuite consulter les modifications apportées via l'application http://<nomDeDomaine>/dynacase/.

5.4.10 Conclusion

Vous avez abordé les hooks et leurs fonctionnalités. Ils permettent de surcharger le fonctionnement par défaut des documents de Dynacase pour implémenter la logique métier de votre projet.

5.4.11 Voir aussi

×