Comment créer et utiliser des Invokable Datasets

Edit me

Les Invokable Datasets

Description

Il s’agit d’un système qui permet de transformer un dataset après sa création par le model manager.

La transformation peut consister en un remplissage du dataset, en un filtrage des enregistrements, voir en sa création complète.

Plusieurs invokables sont disponibles dans le noyau Voozanoo4, et il sera également bientôt possible de créer des invokables spécifiques.

Utilisation

Invokable datasets simples

<!-- Groups list -->
<dataset id="groups" invoke_from="IndentedGroups"/>

<!-- Roles list -->
<dataset id="roles" invoke_from="Roles"/>

Invokable datasets avec paramètres

<dataset id="groups" invoke_from="InvokableDatasetName">
    <params>
        <value alias="param_1_name">value</value>
        <value alias="param_2_name">value</value>
    </params>
</dataset>

Un exemple concret est disponible dans la description de l’invokable IndentedGroupsUserObject.

Création d’invokable datasets spécifiques

Pour créer un invokable spécifique à une application :

  1. Si ce n’est pas déjà fait, créer les dossiers “Model” > “InvokableDataSet” dans le dossier “library” de l’application et ajouter le namespace “Model_” dans l’application.ini :
     ; équivalent à un set_include_path( APPLICATION_PATH "/library" . PATH_SEPARATOR . get_include_path() );
     includePaths.library = APPLICATION_PATH "/library"
     ; Notez bien l'underscore final "_", il est ABSOLUMENT necessaire
     autoloadernamespaces[] = "Model_"
    
  2. Dans le dossier “InvokableDataSet”, créer un fichier MyInvokable.php (remplacer MyInvokable par le nom souhaité) et un fichier MyInvokable.xml
  3. Dans MyInvokable.php
    • Créer une classe Model_InvokableDataSet_MyInvokable
    • La faire hériter de la classe Core_Library_Model_InvokableDataSet (il s’agit de la classe mère de tous les invokables, elle-même hérite de Core_Library_Project_BaseObject et implémente l’interface Core_Library_Model_InvokableDataSet_Interface).
    • Setter $this->_sXmlFilePath pour renseigner le chemin vers le fichier xml qui sera utilisé pour construire l’invokable (sauf si la classe hérite d’un invokable existant et que le xml correspondant convient déjà).
        public function __construct( array $aOptions = null ) {
       parent::__construct( $aOptions );
       $this->_sXmlFilePath = str_replace('.php', '.xml', __FILE__);
        }
      
    • Créer une méthode transform() où sera placée la logique de traitement et de remplacement du dataset initial, ainsi que la gestion des paramètres. La classe Core_Library_Model_InvokableDataSet implémente plusieurs helpers mais aucune logique n’est pré-définie pour la méthode transform().
  4. Dans MyInvokable.xml, décrire la structure xml du dataset ou du dataquery à partir duquel sera créé le dataset.
  5. Appeler cet invokable comme expliqué plus haut.

Plusieurs invokable exists dans le noyau et peuvent servir d’exmple. Ils sont disponibles dans le dossier src > library > Model > InvokableDatSet.

La classe Core_Library_Model_InvokableDataSet

A NOTER : la méthode \_executeInvokableDasetSet de la classe Core_Library_Model_Manager qui traite les datasets présentant l’attribut “invokable” fait appel aux méthodes transform() et checkformat() :

Les variables de classe (ont chacunes des getters et setters)

  • Variables définies automatiquement dans le constructeur de la classe Core_Library_Model_InvokableDataSet :

    • (Core_Library_Resource_XML_DataSet) _oInitialDataset : objet représentant le dataset initial.
    • (Core_Library_Resource_XML_DataQuery_Params | null) _oDataqueryParams : objet décrivant les paramètres du dataquery faisant appel à l’invokable.
    • (associative array \[alias => value] | null) _aDatasetParams : paramètres passés via le xml du dataset initial pour conditionner la transformation.
  • Variables à définir si besoin au sein de la classe Model_InvokableDataSet_MyInvokable :

    • (string) _sXmlFilePath : path vers le fichier xml décrivant l’invokable.
    • (array) _aExpectedAttributes : éventuels attributs attendus dans le dataset initial et nécessaires à la construction de l’invokable. Si pertinente, cette liste doit être settée dans le constructeur ou lors de l’instanciation de l’invokable.
    • (array) _aExpectedFields : éventuels champs attendus dans le dataset initial et nécessaires à la construction de l’invokable. Si pertinente, cette liste doit être settée dans le constructeur ou lors de l’instanciation de l’invokable.

Les méthodes

  • (SimpleXMLElement) public function GetXmlDescription() : Permet de récupérer le SimpleXMLElement correspondant au xml décrivant l’invokable.
  • (Core_Library_Resource_XML_DataSet) public function GetInvokedDataset(null|Core_Library_Resource_XML_DataQuery) : Permet une transformation simple du dataset inital en dataset invokable : crée l’invokable en se fondant sur $this->GetXmlDescription ou sur le dataquery passé en paramètre et lui attribue l’id du dataset initial.
  • (void) public function checkFormat() : Vérifie si le dataset initial contient les attributs et les champs attendus par l’invokable.

La méthode _executeInvokableDataset

Cette méthode de la classe Core_Library_Model_Manager instancie les invokable et appelle systématiquement les méthodes checkformat() et transform().

protected function _executeInvokableDataset( Core_Library_Resource_XML_DataSet $oDataset, Core_Library_Resource_XML_DataQuery_Params $oParams )
{
        // On utilise GetXml au lieu de GetSimpleXml, avec cette dernière l'attribut invoke_from disparait, car l'objet
        // simplexml est entièrement reconstruit.
        // JRD - 2019/07/17 - allow invokable execution from an application's specific invokable
        $sClassName = 'Model_InvokableDataSet_' . ucfirst($oDataset->GetXml()->attributes()->invoke_from);

        // JRD - 2019/07/17 - if specific invokable doesn't exist, check if it's available in core
        $sClassName = class_exists( $sClassName, true )
            ? $sClassName
            : 'Core_Library_Model_InvokableDataSet_' . ucfirst($oDataset->GetXml()->attributes()->invoke_from);

        // Vérification de l'existence de de la class $sClassName
        if ( false === class_exists( $sClassName, false ) )
        {
            if ( false === Zend_Loader_Autoloader::autoload($sClassName) )
            {
                throw new Core_Library_Exception(sprintf('Invokable dataset class %s not found', $sClassName));
            }
        }
        /** @var Core_Library_Model_InvokableDataSet $oInvokableDataSet */
        $oInvokableDataSet = new $sClassName(array(
            "initial_dataset" => $oDataset,
            "dataquery_params" => $oParams
        ));

        //Si le dataset n'a pas le format attendu pour la transformation, check format renvoie une exception
        $oInvokableDataSet->checkFormat();

        //Transformation du dataset, en général remplissage des données
        return $oInvokableDataSet->transform();
}

Templates existants

Axis

Récupération de la liste de tous les axes.

<!-- Liste des axes -->
<dataset id="axis" invoke_from="Axis"/>

Dataset généré :

{
  "id": "axis",
  "total_rows": 1,
  "begin": 0,
  "range": 14000,
  "sort": null,
  "sort_dir": null,
  "mode": "rw",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_axis": {
        "type": "primary_key",
        "mandatory": "false",
        "primary_key": [],
        "source": "table",
        "table": {
          "name": "voo4_pj_axis",
          "field": "id_axis",
          "mode": "r"
        }
      },
      "label": {
        "type": "string",
        "mandatory": "false",
        "string": {
          "length": "45"
        },
        "source": "table",
        "table": {
          "name": "voo4_pj_axis",
          "field": "id_axis",
          "mode": "r"
        }
      }
    },
    "variables": []
  },
  "rowdata": [
    {
      "id_axis": 1,
      "name": "Main axis"
    }
  ],
  "clientdata": null
}

Exports

Récupération de la liste de tous les axexporyses.

<!-- Liste des exports -->
<dataset id="exports" invoke_from="Exports"/>

Dataset généré :

{
  "id": "exports",
  "total_rows": 1,
  "begin": 0,
  "range": 14000,
  "sort": null,
  "sort_dir": null,
  "mode": "rw",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_resource": {
        "type": "primary_key",
        "mandatory": true,
        "default_label": "Identifiant",
        "default_short_label": "Identifiant",
        "primary_key": [],
        "source": "varset",
        "varset": {
          "name": "resource",
          "field": "id_data",
          "mode": "rw"
        }
      },
      "label": {
        "type": "string",
        "mandatory": true,
        "default_label": "Nom",
        "default_short_label": "Nom",
        "string": {
          "length": 45
        },
        "source": "varset",
        "varset": {
          "name": "resource",
          "field": "name",
          "mode": "rw"
        }
      }
    },
    "variables": [
      {
        "alias": "param_id_type_exp",
        "value": 78,
        "target_column": false,
        "entries": [
          {
            "type": "param",
            "name": "id_type_exp"
          }
        ]
      }
    ]
  },
  "rowdata": [
    {
      "id_resource": 51,
      "label": "export_film_test"
    },
    {
      "id_resource": 52,
      "label": "export_medecin_test"
    }
  ],
  "clientdata": null
}

Filters

Récupération de la liste de tous les axexporyses.

<!-- Liste des filtres -->
<dataset id="filters" invoke_from="Filters"/>

Dataset généré :

{
  "id": "filters",
  "total_rows": 1,
  "begin": 0,
  "range": 14000,
  "sort": null,
  "sort_dir": null,
  "mode": "rw",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_resource": {
        "type": "primary_key",
        "mandatory": true,
        "default_label": "Identifiant",
        "default_short_label": "Identifiant",
        "primary_key": [],
        "source": "varset",
        "varset": {
          "name": "resource",
          "field": "id_data",
          "mode": "rw"
        }
      },
      "label": {
        "type": "string",
        "mandatory": true,
        "default_label": "Nom",
        "default_short_label": "Nom",
        "string": {
          "length": 45
        },
        "source": "varset",
        "varset": {
          "name": "resource",
          "field": "name",
          "mode": "rw"
        }
      },
      "description": {
        "type": "string",
        "mandatory": false,
        "default_label": "Description",
        "string": {
          "length": 255
        },
        "source": "varset",
        "varset": {
          "name": "resource",
          "field": "description",
          "mode": "rw"
        }
      }
    },
    "variables": [
      {
        "alias": "param_id_type_flt",
        "value": 70,
        "target_column": false,
        "entries": [
          {
            "type": "param",
            "name": "id_type_flt"
          }
        ]
      }
    ]
  },
  "rowdata": [
    {
      "id_resource": 38,
      "label": "titre_film",
      "description": ""
    }
  ],
  "clientdata": null
}

IndentedGroups

Récupération de la liste de tous les groupes autorisés pour l’utilisateur courant, avec le niveau de profondeur où se situe chaque groupe. Le filtrage des groupes autorisés se fait depuis l’id de l’utilisateur courant.

<!-- Liste des groupes -->
<dataset id="groups" invoke_from="IndentedGroups"/>

Dataset généré :

{
  "id": "groups",
  "total_rows": 1,
  "begin": 0,
  "range": 0,
  "sort": null,
  "sort_dir": null,
  "mode": "r",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_group": {
        "type": "primary_key",
        "mandatory": false,
        "primary_key": []
      },
      "name": {
        "type": "string",
        "mandatory": false,
        "default_label": "Groupe",
        "string": {
          "length": 150
        }
      },
      "level": {
        "type": "integer",
        "mandatory": false,
        "integer": {
          "max": 999,
          "min": 0
        }
      },
      "id_axis": {
        "type": "integer",
        "mandatory": false,
        "integer": {
          "max": 999,
          "min": 0
        }
      },
      "id_parent": {
        "type": "integer",
        "mandatory": "false",
        "integer": {
          "max": 9999999999,
          "min": 0
        }
      }
    },
    "variables": []
  },
  "rowdata": [
    {
      "id_group": 1,
      "name": "Main",
      "id_axis": 1,
      "level": 0,
      "id_parent": null
    }
  ],
  "clientdata": null
}

IndentedGroupsUserObject

Récupération de la liste de tous les groupes autorisés pour l’utilisateur courant, avec le niveau de profondeur où se situe chaque groupe. Le filtrage des groupes autorisés se fait depuis l’objet user correspondant à l’utilisateur courant.

<!-- Liste des groupes -->
<dataset id="groups" invoke_from="IndentedGroupsUserObject"/>

Paramètres disponibles :

<!-- Liste des groupes -->
<dataset id="groups" invoke_from="IndentedGroupsUserObject">
    <params>
        <!-- Liste des groupes sans les groupes désactivés / à false par défaut, 0 pour mettre à true -->
        <value alias="exclude_disabled">0</value>
        <!-- Liste des groupes dont le "level" est inférieur ou égal à 1 / aucune limite par défaut -->
        <value alias="limit_to_level">1</value>
    </params>
</dataset>

Dataset généré (sans appliquer de paramètres) :

{
  "id": "groups",
  "total_rows": 1,
  "begin": 0,
  "range": 0,
  "sort": null,
  "sort_dir": null,
  "mode": "r",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_group": {
        "type": "primary_key",
        "mandatory": false,
        "primary_key": []
      },
      "name": {
        "type": "string",
        "mandatory": false,
        "default_label": "Groupe",
        "string": {
          "length": 150
        }
      },
      "level": {
        "type": "integer",
        "mandatory": false,
        "integer": {
          "max": 999,
          "min": 0
        }
      },
      "id_axis": {
        "type": "integer",
        "mandatory": false,
        "integer": {
          "max": 999,
          "min": 0
        }
      },
      "id_parent": {
        "type": "integer",
        "mandatory": "false",
        "integer": {
          "max": 9999999999,
          "min": 0
        }
      },
      "disabled": {
        "type": "boolean",
        "mandatory": false,
        "boolean": []
      }
    },
    "variables": []
  },
  "rowdata": [
    {
      "id_group": 1,
      "name": "Main",
      "id_axis": 1,
      "level": 0,
      "id_parent": null,
      "disabled": 0
    }
  ],
  "clientdata": null
}

Listings

Récupération de la liste de tous les listings.

<!-- Liste des listings -->
<dataset id="listing" invoke_from="Listings"/>

Dataset généré :

{
  "id": "listings",
  "total_rows": 2,
  "begin": 0,
  "range": 14000,
  "sort": null,
  "sort_dir": null,
  "mode": "rw",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_resource": {
        "type": "primary_key",
        "mandatory": true,
        "default_label": "Identifiant",
        "default_short_label": "Identifiant",
        "primary_key": [],
        "source": "varset",
        "varset": {
          "name": "resource",
          "field": "id_data",
          "mode": "rw"
        }
      },
      "label": {
        "type": "string",
        "mandatory": true,
        "default_label": "Nom",
        "default_short_label": "Nom",
        "string": {
          "length": 45
        },
        "source": "varset",
        "varset": {
          "name": "resource",
          "field": "name",
          "mode": "rw"
        }
      }
    },
    "variables": [
      {
        "alias": "param_id_type_lst",
        "value": 69,
        "target_column": false,
        "entries": [
          {
            "type": "param",
            "name": "id_type_lst"
          }
        ]
      }
    ]
  },
  "rowdata": [
    {
      "id_resource": 54,
      "label": "films"
    },
    {
      "id_resource": 57,
      "label": "test"
    }
  ],
  "clientdata": null
}

Roles

Récupération de tous les rôles

<!-- Liste des rôles -->
<dataset id="roles" invoke_from="Roles"/>

Dataset généré :

{
  "id": "roles",
  "total_rows": 2,
  "begin": 0,
  "range": 14000,
  "sort": null,
  "sort_dir": null,
  "mode": "r",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_role": {
        "type": "primary_key",
        "mandatory": false,
        "primary_key": [],
        "source": "table",
        "table": {
          "name": "voo4_pj_role",
          "field": "id_role",
          "mode": "r"
        }
      },
      "label": {
        "type": "string",
        "mandatory": false,
        "string": {
            "length": 100
        },
        "source": "table",
        "table": {
          "name": "voo4_pj_role",
          "field": "label",
          "mode": "r"
        }
      }
    },
    "variables": []
  },
  "rowdata": [
    {
      "id_role": 1,
      "label": "Administrator"
    },
    {
      "id_role": 2,
      "label": "test"
    }
  ],
  "clientdata": null
}

Users

Récupération de tous les utilisateurs actifs.

<!-- Liste de utilisateurs -->
<dataset id="users" invoke_from="Users"/>

Le dataset généré :

{
  "id": "users",
  "total_rows": 2,
  "begin": 0,
  "range": 14000,
  "sort": null,
  "sort_dir": null,
  "mode": "rw",
  "cacheable": true,
  "standby": true,
  "type": "standard",
  "auto_add_record": false,
  "mute_refresh_event": false,
  "metadata": {
    "fields": {
      "id_user": {
        "type": "primary_key",
        "mandatory": false,
        "primary_key": [],
        "source": "table",
        "table": {
          "name": "voo4_user_data",
          "field": "id_group",
          "mode": "r"
        }
      },
      "label": {
        "type": "string",
        "mandatory": false,
        "string": {
          "length": 50
        },
        "source": "table",
        "table": {
          "name": "voo4_user_data",
          "field": "username",
          "mode": "r"
        }
      }
    },
    "variables": [
      {
        "alias": "param",
        "value": 37,
        "target_column": false,
        "entries": [
          {
            "type": "param",
            "name": "status"
          }
        ]
      }
    ]
  },
  "rowdata": [
    {
      "id_user": 2,
      "label": "root"
    },
    {
      "id_user": 3,
      "label": "Juliette"
    }
  ],
  "clientdata": null
}