API d’autorisation / restrictions des champs extras
Comme dans la version précédente, il est possible de restreindre l’usage de champs extras à certains secteurs ou rubriques. La fonction d’API restreindre_extras
est identique, cependant, les noms des fonctions d’autorisations sous-jacentes ont, eux, évolué.
La fonction restreindre_extras
facilite les restrictions des champs, c’est à dire des restrictions d’affichages définies en fonction de la rubrique à laquelle ces champs appartiennent. Ces fonctions sont à placer dans le fichier squelettes/mes_fonctions.php
. Leur rôle est de créer « à la volée » les fonctions d’autorisations adéquates (elles sont décrites plus loin).
Pour leur bon fonctionnement, il est nécessaire de charger la librairie inc/cextras_autoriser
.
Les arguments de cette fonction sont :
- objet incriminé (article, rubrique, mot, site...)
- nom du/des champ(s) extras
- identifiants de restriction (par défaut des rubriques)
- cible (par défaut ’rubrique’, mais peut aussi être ’secteur’ ou ’groupe’)
- recursif (false par défaut) (applique t-on aux éléments enfants ?)
Un exemple de fichier d’autorisation et diverses autorisations :
<?php
include_spip('inc/cextras_autoriser');
// restreindre le champ 'gamma' des articles, sur la rubrique 2
restreindre_extras('article', 'gamma', 2);
// restreindre le champ 'alpha' et 'beta' des articles, sur les rubriques 2 et 3
restreindre_extras('article', array('alpha', 'beta'), array(2, 3));
// restreindre le champ 'iota' des rubriques, sur la rubrique 37
restreindre_extras('rubrique', 'iota', 37);
// restreindre le champ 'iota' des rubriques, sur la rubrique 37 et ses sous rubriques
restreindre_extras('rubrique', 'iota', 37, 'rubrique', true);
// restreindre les champs 'alpha' et 'beta' des articles, sur les rubriques 37 et 38 et leurs enfants
restreindre_extras('article', array('alpha', 'beta'), array(37, 38), 'rubrique', true);
// lorsqu'on veut appliquer sur un secteur, préférer 'secteur' plutôt que rubriques récursives. Pour restreindre au secteur 2 :
restreindre_extras('article', 'beta', 2, 'secteur');
?>
Un argument supplémentaire permet donc de définir la fonction qui fera la recherche de validité, et vaut par défaut ’rubrique’, ce qui charge la fonction inc_restreindre_extras_objet_sur_{rubrique}_dist
. Le plugin supporte aussi secteur et groupemot :
// restreindre les champs 'motin' et 'moteur' des mots, sur le groupe 2
restreindre_extras('mot', array('motin', 'moteur'), 3, 'groupemot');
Depuis la version 3.3.0, il est aussi possible de restreindre les champs extras en fonction de la composition de l’objet, ex :
// restreindre le champ 'loisirs' sur les articles qui portent la composition 'cv'
restreindre_extras('article', 'loisirs', 'cv', 'composition');
Depuis la version 3.7.0, il est aussi possible de restreindre les champs extras en fonction d’un mot clé lié à l’objet, ex :
// restreindre le champ 'loisirs' sur les articles qui portent un des mots clés n°9 ou 10
restreindre_extras('article', 'loisirs', array(9, 10), 'mot');
Notes :
- Par souci d’optimisation (moins de requêtes SQL), il est préférable de regrouper en un seul appel au lieu de plusieurs lorsque c’est possible,
- Il n’est pas possible de définir deux restrictions différentes pour un même champ extra.
// impossible (seul le 1er est pris en compte) : restreindre_extras('article', 'c1', 1); restreindre_extras('article', 'c1', 2); // Utiliser : restreindre_extras('article', 'c1', array(1, 2)); // Mais grouper les champs dés que c'est possible (mêmes identifiants d'application). Si : restreindre_extras('article', 'c1', array(1, 2)); restreindre_extras('article', 'c2', array(1, 2)); // Préférer : restreindre_extras('article', array('c1', 'c2'), array(1, 2));
Fonctions d’autorisations précises
Certains cas sont bien plus complexes et peuvent nécessiter que vous créiez vous-même les fonctions d’autorisations avec leurs actions qui vont bien. Ces fonctions doivent être nommées (le _dist n’est pas obligatoire) :
-
autoriser_{objet}_voirextra_{champ}_dist
-
autoriser_{objet}_modifierextra_{champ}_dist
Cela peut donner une fonction (table auteurs, champ prenom) :
-
autoriser_auteur_voirextra_prenom_dist
-
autoriser_auteur_modifierextra_prenom_dist
Un exemple de code simple pourrait être :
// seuls les rédacteurs et admins peuvent voir
function autoriser_auteur_voirextra_prenom_dist($faire, $type, $id, $qui, $opt) {
return in_array($qui['statut'], array('0minirezo', '1comite'));
}
// seuls les admins peuvent modifier
function autoriser_auteur_modifierextra_prenom_dist($faire, $type, $id, $qui, $opt) {
return in_array($qui['statut'], array('0minirezo'));
}
Voici un autre exemple plus complet qui teste si un article a une certaine composition, la composition « carte », pour afficher ou non des champs extras :
/* AUTORISATIONS */
function grainepc_objet_est_carto($objet, $id) {
$compo = compositions_determiner($objet, $id);
return ($compo == 'carte');
}
// autorisations des champs extras de carte ...
foreach (array(
'declinaison',
'structure',
'affichage',
'date_creation',
'coordonnees',
'presentation',
'infos') as $nom)
{
$m = "autoriser_article_modifierextra_" . $nom . "_dist";
$v = "autoriser_article_voirextra_" . $nom . "_dist";
$code = "
if (!function_exists('$m')) {
function $m(\$faire, \$type, \$id, \$qui, \$opt) {
return grainepc_objet_est_carto(\$type, \$id);
}
}
if (!function_exists('$v')) {
function $v(\$faire, \$type, \$id, \$qui, \$opt) {
return grainepc_objet_est_carto(\$type, \$id);
}
}
";
# var_dump($code);
eval($code);
}
Créer un plugin en utilisant les API de Champs Extras
Vous le savez, le plugin « Champs Extras Interfaces » s’appuie sur une API de Champs Extras pour proposer une gestion graphique des champs. Cependant, des plugins peuvent aussi s’appuyer sur cette API afin de décharger sur le plugin champs extras la gestion de l’affichage, de la vérification et le traitement de nouveaux champs. Il n’y a rien d’obligatoire à cette utilisation, vous pouvez très bien développer un plugin qui crée des nouveaux champs en base et les gère de lui-même en utilisant les pipelines fournis par SPIP. L’avantage ici, est que toutes les déclarations sont regroupées dans un seul pipeline, et que la procédure d’installation et de désinstallation est simplifiée. Voyons un exemple, l’extension de démonstration nommée « Titre court pour rubriques ».
Tout d’abord, il faut créer un paquet.xml
présentant le plugin :
<paquet
prefix="titrecourt"
categorie="outil"
version="1.1.0"
etat="stable"
compatibilite="[3.0.0-beta;["
logo=""
schema="0.0.1"
>
<nom>Titre Court pour Rubriques</nom>
<auteur>Matthieu Marcillaud [->magraine.net]</auteur>
<licence>GNU/GPL</licence>
<necessite nom="cextras" compatibilite="[3.0.5;[" />
<pipeline nom="declarer_champs_extras" inclure="base/titrecourt.php" />
</paquet>
On remarque l’indication de dépendance à « cextras » qui est, donc, le cœur de Champs Extras, son API (« iextras » étant le plugin d’interface graphique), ainsi que l’appel d’un pipeline declarer_champs_extras
.
Nous allons remplir le pipeline de notre nouveau champ « titrecourt » sur la table des rubriques. Pour cela, on crée le fichier base/titrecourt.php
avec comme contenu :
<?php
if (!defined("_ECRIRE_INC_VERSION")) return;
function titrecourt_declarer_champs_extras($champs = array()) {
$champs['spip_rubriques']['titre_court'] = array(
'saisie' => 'input',//Type du champ (voir plugin Saisies)
'options' => array(
'nom' => 'titre_court',
'label' => _T('titrecourt:titre_court'),
'sql' => "varchar(30) NOT NULL DEFAULT ''",
'defaut' => '',// Valeur par défaut
'restrictions'=>array('voir' => array('auteur' => ''),//Tout le monde peut voir
'modifier' => array('auteur' => 'webmestre')),//Seuls les webmestres peuvent modifier
),
);
return $champs;
}
?>
Observons. Le code remplit un tableau de description dans $champs['spip_rubriques']['titre_court']
. Le principe est donc de remplir le tableau $champs
avec une clé indiquant la table SQL, puis une clé indiquant la colonne SQL $champs[table][champ]
.
Le tableau de description est ensuite au format du plugin « Saisies » (puisque Champs Extras s’appuie dessus). On trouve cependant 6 options supplémentaires :
- « nom » indique le nom le la colonne SQL désirée,
- « sql » indique la ligne SQL correspondante,
- « rechercher » (optionnel) permet d’indiquer si le champ doit être pris en compte dans les recherches. Vous pouvez renseigner la valeur
true
(la pondération appliquée par défaut est2
), ou toute valeur entière de pondération de recherche désirée, par exemple5
; - « versionner » (optionnel) permet d’indiquer si le champ peut être versionné lorsque les révisions sont activées (plugin révisions) sur l’objet éditorial sur lequel est ajouté le champs extras.
true
pour activer le versionnage ; - « restrictions » (optionnel) permet d’indiquer les restrictions appliquées automatiquement dans l’espace privé. On peut trouver dedans les options :
- ’voir’ => array(’auteur’=>’’) // tout le monde peut voir (c’est l’action par défaut !)
- ’voir’ => false // personne peut voir
- ’modifier => array(’auteur’ => ’admin’) // seuls les admins.
- ’modifier => array(’auteur’ => ’admin_complet’) // seuls les admins non restreints
- ’modifier => array(’auteur’ => ’webmestre’) // seuls les webmestres.
- ’secteur’ => ’3’ (restreint au secteur 3).
- ’secteur’ => ’3:5:8’ (restreint au secteurs 3, 5 et 8).
- ’branche’ => ’2’ (restreint à la branche 2...).
- ’rubrique’ => ’1’.
- ’groupe’ => ’4’.
- « traitements », traitements typographiques à appliquer, soit une constante prédéfinie, soit un chaîne décrivant les fonctions à appliquer. Lire la documentation sur Programmer avec SPIP.
Notez que si ces restrictions ne sont pas suffisantes, vous pouvez créer comme on l’a vu plus haut les fonctions d’autorisations spécifiques à vos champs extras.
Le dernier fichier à créer gère l’installation et la désinstallation des champs. C’est dans notre exemple le fichier titrecourt_administrations.php
et il contient le minimum syndical :
<?php
if (!defined("_ECRIRE_INC_VERSION")) return;
include_spip('inc/cextras');
include_spip('base/titrecourt');
function titrecourt_upgrade($nom_meta_base_version,$version_cible) {
$maj = array();
cextras_api_upgrade(titrecourt_declarer_champs_extras(), $maj['create']);
include_spip('base/upgrade');
maj_plugin($nom_meta_base_version, $version_cible, $maj);
}
function titrecourt_vider_tables($nom_meta_base_version) {
cextras_api_vider_tables(titrecourt_declarer_champs_extras());
effacer_meta($nom_meta_base_version);
}
?>
On trouve les fonctions upgrade()
et vider_tables()
des plugins, qui appellent des fonctions cextras_api_upgrade()
et cextras_api_vider_tables()
avec le contenu de la fonction qui liste les champs que l’on crée, ici titrecourt_declarer_champs_extras()
.
Pour la fonction d’upgrade, on indique aussi où l’on souhaite créer les mises à jour, ici dans $maj['create']
qui est « à la création du plugin », mais cela aurait pu être appelé aussi lors d’une mise à jour (par exemple si vous avez ajouté un champ de plus).
$maj = array();
cextras_api_upgrade(titrecourt_declarer_champs_extras(), $maj['create']);
// mise à jour de la version 1.2 (nouveaux champs a créer)
cextras_api_upgrade(titrecourt_declarer_champs_extras(), $maj['1.2']);
Un autre exemple...
Voici un autre exemple plus complexe. C’était pour cet exemple que les autorisations par compositions avaient aussi été créées. Ici, plusieurs champs sont présents sur des tables différentes et plusieurs mises à jour sont faites.
Déclaration des champs
<?php
if (!defined("_ECRIRE_INC_VERSION")) return;
function grainepc_declarer_champs_extras($champs = array()){
$champs['spip_auteurs']['telephone'] = array(
'saisie' => 'input', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'telephone',
'label' => _T('grainepc:info_telephone'),
'sql' => "varchar(30) NOT NULL DEFAULT ''",
'defaut' => '',// Valeur par défaut
));
$champs['spip_articles']['declinaison'] = array(
'saisie' => 'input', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'declinaison',
'label' => _T('grainepc:info_declinaison'),
'sql' => "text DEFAULT '' NOT NULL",
'defaut' => '',// Valeur par défaut
'traitements' => '_TRAITEMENT_TYPO',
));
$champs['spip_articles']['structure'] = array(
'saisie' => 'radio', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'structure',
'label' => _T('grainepc:info_type_structure'),
'sql' => "varchar(30) NOT NULL DEFAULT ''",
'defaut' => '',// Valeur par défaut
'datas' => array(
'' => _T('grainepc:info_rien'),
'structure' => _T('grainepc:info_structure'),
'structure_adherente' => _T('grainepc:info_structure_adherente'),
),
));
$champs['spip_articles']['affichage'] = array(
'saisie' => 'radio', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'affichage',
'label' => _T('grainepc:info_affichage'),
'sql' => "varchar(30) NOT NULL DEFAULT 'complet'",
'defaut' => 'complet',// Valeur par défaut
'datas' => array(
'complet' => _T('grainepc:info_complet'),
'reduit' => _T('grainepc:info_reduit'),
),
));
$champs['spip_articles']['date_creation'] = array(
'saisie' => 'date', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'date_creation',
'label' => _T('grainepc:info_date_creation'),
'sql' => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
'defaut' => '0000-00-00 00:00:00',// Valeur par défaut
),
'verifier' => array(
'type' => 'date',
'options' => array(
'normaliser' => 'datetime',
)
));
$champs['spip_articles']['coordonnees'] = array(
'saisie' => 'textarea', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'coordonnees',
'label' => _T('grainepc:info_coordonnees'),
'sql' => "text DEFAULT '' NOT NULL",
'defaut' => '',// Valeur par défaut
'rows' => 4,
'traitements' => '_TRAITEMENT_RACCOURCIS',
));
$champs['spip_articles']['presentation'] = array(
'saisie' => 'textarea', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'presentation',
'label' => _T('grainepc:info_presentation'),
'sql' => "text DEFAULT '' NOT NULL",
'defaut' => '',// Valeur par défaut
'rows' => 6,
'traitements' => '_TRAITEMENT_RACCOURCIS',
));
$champs['spip_articles']['infos'] = array(
'saisie' => 'textarea', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'infos',
'label' => _T('grainepc:info_infos'),
'sql' => "text DEFAULT '' NOT NULL",
'defaut' => '',// Valeur par défaut
'rows' => 5,
'traitements' => '_TRAITEMENT_RACCOURCIS',
));
return $champs;
}
?>
Installation
<?php
include_spip('inc/cextras');
include_spip('base/grainepc');
function grainepc_upgrade($nom_meta_base_version,$version_cible){
$maj = array();
cextras_api_upgrade(grainepc_declarer_champs_extras(), $maj['create']);
cextras_api_upgrade(grainepc_declarer_champs_extras(), $maj['1.1.0']);
cextras_api_upgrade(grainepc_declarer_champs_extras(), $maj['1.2.0']);
$maj['1.2.0'][] = array('sql_alter',"TABLE spip_auteurs DROP type");
cextras_api_upgrade(grainepc_declarer_champs_extras(), $maj['1.3.0']);
include_spip('base/upgrade');
maj_plugin($nom_meta_base_version, $version_cible, $maj);
}
function grainepc_vider_tables($nom_meta_base_version) {
cextras_api_vider_tables(grainepc_declarer_champs_extras());
effacer_meta($nom_meta_base_version);
}
?>
Un autre exemple... en utilisant un ou plusieurs fieldset pour séparer les nouveau champs ajoutés
Voici un autre exemple où les champs sont regroupés par fieldsets (suite à une question posée dans les forums de cet article).
Ici, l’ensemble des champs sont sur la même table, et sont regroupés en deux fieldsets différents numeros et adresse.
Déclaration des champs
<?php
if (!defined("_ECRIRE_INC_VERSION")) return;
function numadresse_declarer_champs_extras($champs = array()){
$champs['spip_auteurs']['numeros'] = array(
'saisie' => 'fieldset',//Type du champ (voir plugin Saisies)
'options' => array(
'nom' => "numeros",
'label' => _T('numadresse:legend_numeros')
),
'saisies' => array(
'telephone' => array(
'saisie' => 'input', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'telephone',
'label' => _T('numadresse:info_telephone'),
'sql' => "varchar(30) NOT NULL DEFAULT ''",
'defaut' => '',// Valeur par défaut
)),
'fax' => array(
'saisie' => 'input', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'fax',
'label' => _T('numadresse:info_fax'),
'sql' => "varchar(30) NOT NULL DEFAULT ''",
'defaut' => '',// Valeur par défaut
))
)
);
$champs['spip_auteurs']['adresse'] = array(
'saisie' => 'fieldset',//Type du champ (voir plugin Saisies)
'options' => array(
'nom' => "adresse",
'label' => _T('numadresse:legend_adresse')
),
'saisies' => array(
'adresse' => array(
'saisie' => 'input', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'adresse',
'label' => _T('numadresse:info_adresse'),
'sql' => "text NOT NULL DEFAULT ''",
'defaut' => '',// Valeur par défaut
)),
'code_postal' => array(
'saisie' => 'input', // Type du champs (voir plugin Saisies)
'options' => array(
'nom' => 'code_postal',
'label' => _T('numadresse:info_code_postal'),
'sql' => "varchar(30) NOT NULL DEFAULT ''",
'defaut' => '',// Valeur par défaut
))
)
);
return $champs;
}
?>
Pour l’installation de ces champs, faire comme l’exemple situé plus haut.
Les quatres nouveaux champs sont ainsi répartis dans deux fieldsets différents en bas du profil de l’auteur.
Discussions par date d’activité
35 discussions
Mathieu, je t’ai déjà dis que tu cartonnais ? ^^
Répondre à ce message
Bonjour :)
Tout d’abord merci pour la « magie » qu’offre cette nouvelle version !
J’ai peut être une question bête, mais je n’ai pas trouvé encore la réponse alors je tente ma chance :
Les champs extra reposent sur #SAISIE, on créé donc des champs extras via saisie sur les objets. Lors de la création ceux-ci s’affiche pour l’objet complet dans « champs_extras_edit&objet=mon_objet ».
Coté public je suis sur la réalisation d’une fiche perso pour un auteur. Mais je ne cherche pas forcément à lui faire modifier tout les champs extra définis. Je souhaiterai permettre l’édition au cas par cas de mes #CHAMPS_EXTRA. Donc, exsisterai t’il un moyen, une balise, qui soit du genre #SAISIR_CHAMPS_EXTRAmonchamp_extra ?
Pour l’instant je passe par
[(#SAISIE{input, monchamps, label=[(#CHAMP_EXTRA{monchamps, label}) : ], obligatoire=oui,defaut=#MONCHAMP})]
La création d’une nouvelle balise pourrait être utile pour cela ?
Question supplémentaire, si c’est la bonne methode, comment fournir sous forme d’#ARRAY pour datas (boutons radio, checkbox) de #SAISIE avec #LISTER_VALEURS et #LISTER_CHOIX (car c’est soir l’un soit l’autre à priori).
Et enfin, existe t il une option (pas vu) qui permette d’afficher un #CHAMP_EXTRA en fonction de la valeur d’un Champs précédent : exemple type -> boutons radio • Particulier | • société qui afficherai un champs « Fonction » si société est sélectionné, sinon serait caché.
Voila :) merci beaucoup pour vos éclaircissements
Répondre à ce message
Bonjour,
Vue personnalisée : il est précisé dans l’article Champs Extras (Interface) que l’on peut créer ses propres saisies. Je souhaite personnaliser la vue d’un champ de type input.
J’ai deux questions à ce sujet :
(1) je n’ai pas trouvé le fichier input.html dans le répertoire saisies-vues du plugin saisies. Quel est le fichier à modifier ?
(2) où le fichier input.html doit-il être enregistré (dans le dossier saisies-vues du plugin ajoutant les champs extras) ?
Merci pour vos réponses,
— Olivier
Répondre à ce message
Bonjour Mathieu,
Merci pour cet article. J’en ai profité pour mettre à jour mon plugin d’extension des champs auteurs pour Spip 3 / Champs Extra.
Je bute toutefois sur les fonctions d’autorisations qui ne sont pas opérantes chez moi. Deux questions :
(1) à quoi servent les autorisations autorisations voir/modifier définies pour chaque champ dans le plugin par rapports aux fonctions définies dans squelettes/mes_fonctions.php ? Cela fait-il doublon ?
(2) malgré la définition des fonctions ad hoc dans mes_fonctions.php, un auteur peut modifier des champs réservés aux seuls admin. Est-ce que le nom des champs extras peut accepter un underscore (asso_prenom) ?
Merci,
— Olivier
1) oui, cela fait doublon. En fait c’est pour éviter d’avoir à déclarer des fonctions lorsque les restrictions sont des cas courants (on a le même principe avec le plugin d’interface).
2) attention : les fonctions ne sont plus nommées comme avec l’api pour SPIP 2.1. Il faut donc mettre à jour leur noms pour cette API là. et 2bis) les underscore devraient passer.
Si c’est pas le cas, c’est un bug.
SPIP 3.0.0-beta2 [19139]
Champs Extras 3.0.6 SVN [59573]
L’interface privée ne semble pas tenir compte des restrictions (pas de fonction spécifique dans mes_fonctions.php). Exemple :
Connecté en temps que rédacteur, je peux voir le champ (ma fiche et celle des autres auteurs) et je peux modifier ce champs de ma fiche. J’ai essayé avec webmestre ou 0minirezo : même résultat.
Reproduis-tu le même comportement ?
Quelque soit le nom du champ (avec / sans souligné) ?
Bien bien bien, petite erreur de frappe dans la doc :)
http://zone.spip.org/trac/spip-zone/changeset/59831
MM.
En effet, ça change tout ;-) !
Merci,
— Olivier
P.S. : les champs extras avec un souligné fonctionnent normalement.
Répondre à ce message
Super !! Merci
Répondre à ce message
Ajouter un commentaire
Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :
Merci d’avance pour les personnes qui vous aideront !
Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.
Suivre les commentaires : |