Comment créer votre propre page d'inscription dans WordPress Multisite. Comment créer votre propre bonus multisite de page d'inscription WordPress. Protection contre les spammeurs

Les liens à usage unique peuvent être utilisés dans diverses situations : pour fournir un accès temporaire à un fichier ou à une page, ou pour confirmer l'enregistrement. Dans ce tutoriel, nous allons vous montrer comment générer et intégrer des URL jetables.

Création d'URL

Supposons que nous ayons un système d'authentification des utilisateurs sur notre site. Après l'enregistrement, nous demandons à l'utilisateur de suivre la procédure de vérification par e-mail. Pour créer de tels liens, nous pouvons utiliser le paramètre de jeton spécial. Un exemple d'un tel lien :

Http : //example.com/activate? Token = ee97780 ...

On ne peut pas se passer d'une base de données ici, regardons donc le tableau avec lequel nous allons travailler.

CREATE TABLE pending_users (token CHAR (40) NOT NULL, nom d'utilisateur VARCHAR (45) NOT NULL, tstamp INTEGER UNSIGNED NOT NULL, PRIMARY KEY (token));

Nous allons stocker 3 champs dans la table : jeton, nom d'utilisateur et heure. Pour générer le jeton, nous utiliserons la fonction sha1(), qui génère une chaîne de 40 caractères. Le champ tstamp stockera l'heure à laquelle le jeton a été généré afin que nous puissions suivre les liens expirés.

Il existe de nombreuses façons de générer un jeton, mais dans ce tutoriel, nous utiliserons les fonctions uniqid () et sha1 (). Quelle que soit la façon dont le jeton est généré, assurez-vous que les valeurs générées sont différentes et que la probabilité de doublons est minime.

$ jeton = sha1 (uniqid ($ nom d'utilisateur, vrai));

La fonction uniqid () prend une chaîne en tant que paramètre et génère un identifiant unique basé sur l'argument passé et l'heure actuelle. De plus, comme deuxième argument, cette fonction prend une valeur booléenne, qui signalera à uniqid d'ajouter quelques caractères supplémentaires pour augmenter la probabilité que la valeur soit unique. La fonction sha1 prend un identifiant unique et crée un hachage.

Une fois que ces deux fonctions fonctionnent, nous aurons un jeton unique que nous pouvons utiliser pour générer des adresses URL. Maintenant, nous devons l'ajouter à la base de données :

$ query = $ db-> prepare ("INSERT INTO pending_users (username, token, tstamp) VALUES (?,?,?)"); $ query-> execute (array ($ username, $ token, $ _SERVER ["REQUEST_TIME"]));

Afin que nous sachions quel utilisateur doit être activé, le nom d'utilisateur sera également enregistré dans le tableau. Dans un exemple plus adapté pour un site réel, vous pouvez utiliser un identifiant utilisateur.

Maintenant que nous avons toutes les informations dont nous avons besoin, nous pouvons créer une URL temporaire :

$ url = "http://example.com/activate.php?token=$token" ;

$ message =<<

Examen

Nous avons maintenant besoin d'un script, grâce auquel nous effectuerons le contrôle. Tout ce que nous avons à faire est de comparer le jeton de l'url et le jeton de la base de données. S'il y en a un et que sa durée de vie n'a pas expiré, alors tout va bien.

// récupère le jeton if (isset ($ _ GET ["token"]) && preg_match ("/ ^ (40) $ / i", $ _GET ["token"])) ($ token = $ _GET ["token "] ;) else (lancer une nouvelle exception ("le jeton n'est pas valide.");) // vérifier le jeton $ query = $ db-> prepare ("SELECT nom d'utilisateur, tstamp FROM pending_users WHERE jeton =?"); $ query-> execute (array ($ token)); $ ligne = $ requête-> récupération (PDO :: FETCH_ASSOC); $ query-> closeCursor (); if ($ row) (extraire ($ row);) else (lancer une nouvelle exception ("le jeton n'est pas valide.");) // activer le compte utilisateur // ... // supprimer le jeton de la base de données $ query = $ db- > prepare ("DELETE FROM pending_users WHERE username =? AND token =? AND tstamp =?",); $ query-> execute (array ($ username, $ token, $ tstamp));

Nous devons également prévoir la vérification des tokens dont la durée de vie a expiré :

// 1 jour en secondes = 60 secondes * 60 minutes * 24 heures $ delta = 86400; // vérifier si ($ _SERVER ["REQUEST_TIME"] - $ tstamp> $ delta) (lancer une nouvelle exception ("le jeton a expiré.");) // activer le compte utilisateur // ...

Ainsi, nous aurons deux vérifications : l'une pour la validité du jeton, l'autre pour la durée de son existence.

Résultat

Cette méthode peut être utilisée non seulement pour activer des comptes d'utilisateurs, mais également pour d'autres besoins : par exemple, pour fournir un accès unique ou temporaire à une ressource ou à un service.

En plus de tout cela, vous pouvez créer un script qui supprimera les jetons que vous n'avez jamais utilisés. Vous pouvez exécuter ce script vous-même de temps en temps ou utiliser cron pour cela.

Aujourd'hui nous allons nous intéresser à l'exploitation d'une vulnérabilité critique 1day dans le populaire CMS Joomla, qui a tonné sur Internet fin octobre. Nous parlerons des vulnérabilités avec des chiffres CVE-2016-8869, CVE-2016-8870 et CVE-2016-9081... Tous trois proviennent d'un seul morceau de code qui a langui dans les entrailles du framework pendant cinq longues années, attendant que son heure se libère et amène avec lui chaos, sites piratés et larmes d'utilisateurs innocents de ce Joomla. Seuls les développeurs les plus vaillants et audacieux, dont les yeux sont rouges à cause de la lumière des moniteurs, et les claviers jonchés de miettes de pain, ont pu défier les mauvais esprits déchaînés et poser leur tête sur l'autel des correctifs.

ATTENTION

Toutes les informations sont fournies à titre informatif seulement. Ni le comité de rédaction ni l'auteur ne sont responsables des dommages éventuels causés par les matériaux de cet article.

Comment tout a commencé

Le 6 octobre 2016, Demis Palma a créé un sujet sur Stack Exchange, dans lequel il a demandé : pourquoi, en fait, dans la version 3.6 de Joomla, il y a deux méthodes pour enregistrer des utilisateurs avec le même nom register () ? Le premier se trouve dans UsersControllerRegistration et le second dans UsersControllerUser. Damis voulait savoir si la méthode UsersControllerUser :: register() est utilisée quelque part, ou s'il ne s'agit que d'un anachronisme évolutif hérité de l'ancienne logique. Il s'inquiétait du fait que même si cette méthode n'était utilisée par aucune vue, elle pouvait être invoquée à l'aide d'une requête générée. A quoi j'ai reçu une réponse d'un développeur sous le pseudo itoctopus, qui a confirmé que le problème existe vraiment. Et envoyé un rapport aux développeurs Joomla.

D'autres événements se sont développés de la manière la plus rapide. Le 18 octobre, les développeurs Joomla acceptent un rapport de Damis, qui avait alors esquissé un PoC pour permettre l'enregistrement des utilisateurs. Il a publié une note sur son site Web, où il a décrit le problème qu'il avait trouvé et ses réflexions à ce sujet. Le même jour, une nouvelle version de Joomla 3.6.3 est publiée, qui contient toujours le code vulnérable.

Après cela, Davide Tampellini déroule le bogue à l'état d'enregistrement non pas d'un simple utilisateur, mais d'un administrateur. Et déjà le 21 octobre, une nouvelle affaire arrive à l'équipe de sécurité Joomla. On parle déjà d'escalade de privilèges. Le même jour, une annonce apparaît sur le site Web de Joomla que le mardi 25 octobre, la prochaine version avec le numéro de série 3.6.3 sera publiée, qui corrige une vulnérabilité critique dans le noyau du système.

Le 25 octobre, la Joomla Security Strike Team découvre le dernier problème, créé par un morceau de code découvert par Damis. Ensuite, un commit daté du 21 octobre avec le nom discret Prepare 3.6.4 Stable Release est poussé vers la branche principale du référentiel officiel Joomla, ce qui corrige le bogue malheureux.

Après ce come-out, de nombreuses personnes intéressées sont connectées à la réunion des développeurs - elles commencent à détordre la vulnérabilité et à préparer des exploits.

Le 27 octobre, le chercheur Harry Roberts télécharge un exploit prêt à l'emploi dans le référentiel Xiphos Research qui peut télécharger un fichier PHP sur un serveur avec un CMS vulnérable.

Détails

Eh bien, nous avons terminé avec le contexte, passons à la partie la plus intéressante - l'analyse de la vulnérabilité. En tant que version de test, j'ai installé Joomla 3.6.3, donc tous les numéros de ligne seront pertinents pour cette version particulière. Et tous les chemins vers les fichiers que vous voyez ci-dessous seront indiqués par rapport à la racine du CMS installé.

Grâce à la découverte de Damis Palma, nous savons qu'il existe deux méthodes pour effectuer l'enregistrement des utilisateurs dans le système. Le premier est utilisé par le CMS et se trouve dans le fichier /components/com_users/controllers/registration.php:108. Le second (celui que nous devons appeler) réside dans /components/com_users/controllers/user.php:293. Regardons-le de plus près.

286 : / ** 287 : * Méthode pour enregistrer un utilisateur. 288: * 289: * @return booléen 290: * 291: * @since 1.6 292: * / 293: public function register() 294: (295: JSession :: checkToken ("post") ou jexit (JText :: _ ("JINVALID_TOKEN")); ... 300 : // Récupère les données du formulaire. 301 : $ data = $ this-> input-> post-> get ("user", array (), "array");. .. 315: $ return = $ model-> validate ($ form, $ data); 316: 317: // Vérifier les erreurs. 318: if ($ return === false) 319: (... 345: / / Terminer l'enregistrement.346 : $ return = $ model-> register ($ data) ;

Ici, je n'ai laissé que des lignes intéressantes. La version complète de la méthode vulnérable peut être consultée dans le référentiel Joomla.

Voyons ce qui se passe lors de l'enregistrement normal d'un utilisateur : quelles données sont envoyées et comment elles sont traitées. Si l'enregistrement de l'utilisateur est activé dans les paramètres, le formulaire se trouve à l'adresse http://joomla.local/index.php/component/users/? View = registration.


Une demande d'enregistrement d'utilisateur légitime ressemble à la capture d'écran suivante.


Le composant com_users est chargé de travailler avec les utilisateurs. Faites attention au paramètre de tâche dans la requête. Il est au format contrôleur $.Méthode $. Jetons un coup d'œil à la structure du fichier.

Les noms des scripts dans le dossier contrôleurs correspondent aux noms des contrôleurs appelés. Puisque notre requête contient maintenant $ controller = "registration", le fichier sera appelé inscription.php et sa méthode register().

Attention, question : comment passer un traitement d'enregistrement à une vulnérabilité dans le code ? Vous avez probablement déjà deviné. Les noms des méthodes vulnérables et réelles sont les mêmes (registre), il suffit donc de changer le nom du contrôleur appelé. Où se trouve le contrôleur vulnérable ? C'est vrai, dans le fichier utilisateur.php... Il s'avère que $ controller = "user". Rassembler le tout et obtenir task = user.register. Maintenant, la demande d'enregistrement est traitée par la méthode dont nous avons besoin.


La deuxième chose que nous devons faire est d'envoyer les données dans le bon format. Tout est simple ici. Le registre légitime () attend de nous un tableau appelé jform, dans lequel nous transmettons les données d'enregistrement - nom, login, mot de passe, mail (voir la capture d'écran avec la demande).

  • /components/com_users/controllers/registration.php: 124: // Récupère les données de l'utilisateur. 125 : $ requestData = $ this-> input-> post-> get ("jform", array (), "array");

Notre service obtient ces données d'un tableau nommé user.

  • /components/com_users/controllers/user.php: 301: // Récupère les données du formulaire. 302 : $ data = $ this-> input-> post-> get ("user", array (), "array");

Par conséquent, nous changeons les noms de tous les paramètres de la requête de jfrom à user.

Notre troisième étape consiste à trouver un jeton CSRF valide, car sans lui, il n'y aura pas d'enregistrement.

  • /components/com_users/controllers/user.php: 296: JSession :: checkToken ("post") ou jexit (JText :: _ ("JINVALID_TOKEN"));

Cela ressemble à un hachage MD5, et vous pouvez le prendre, par exemple, à partir du formulaire d'autorisation sur le site /index.php/component/users/?view=login.


Vous pouvez maintenant créer des utilisateurs via la méthode souhaitée. Si tout s'est bien passé, alors félicitations - vous venez d'exploiter une vulnérabilité CVE-2016-8870"Contrôle manquant des autorisations pour enregistrer de nouveaux utilisateurs."

Voici à quoi cela ressemble dans la méthode register () "de travail" du contrôleur UsersControllerRegistration :

  • /components/com_users/controllers/registration.php: 113: // Si l'enregistrement est désactivé - Rediriger vers la page de connexion. 114: if (JComponentHelper :: getParams ("com_users") -> get ("allowUserRegistration") == 0) 115: (116: $ this-> setRedirect (JRoute :: _ ("index.php? Option = com_users & view = login ", false)); 117 : 118 : return false ; 119 :)

Et donc chez les vulnérables :

  • /components/com_users/controllers/user.php :

Ouais, pas moyen.

Pour comprendre le deuxième problème, beaucoup plus grave, envoyons la requête que nous avons formée et traçons comment elle est exécutée dans différentes parties du code. Voici le morceau qui est responsable de la validation des données soumises par l'utilisateur dans une méthode de travail :

La suite est disponible uniquement pour les participants

Option 1. Rejoignez la communauté "site" pour lire tous les documents sur le site

L'adhésion à la communauté pendant la période spécifiée vous ouvrira l'accès à TOUS les documents de Hacker, augmentera votre remise cumulative personnelle et vous permettra d'accumuler un score Xakep professionnel !

Nous créons notre propre page d'inscription pour le multisite au lieu du wp-signup.php standard.

Dans une installation WordPress typique, la page d'enregistrement (connexion, réinitialisation du mot de passe) affiche le fichier wp-login.php.

  • /wp-login.php - autorisation
  • /wp-login.php?action=register - inscription
  • /wp-login.php?action=lostpassword - réinitialisation du mot de passe

Il existe des conditions distinctes pour le multisite dans wp-login.php. Ainsi, lorsque vous cliquez sur le lien /wp-login.php?action=register sur un multisite, WordPress va rediriger vers la page /wp-signup.php. Dans de nombreux thèmes, la page n'a pas l'air très attrayante, nous allons donc créer la nôtre.

Site principal du réseau

Par défaut, WordPress ouvre une page d'enregistrement (wp-signup.php) sur le domaine principal (site) du réseau. Cependant, il est possible de créer une page d'inscription distincte pour chaque site du réseau, même s'ils ont des thèmes différents. Nous considérerons le cas où tous les sites du réseau ont leur propre page d'inscription, mais le même thème est utilisé et les sites ne diffèrent que par la langue. Si différents thèmes sont utilisés, plus de code devra être écrit.

fonctions.php?

Non. Le nom de ce fichier semble être mentionné dans chaque article WordPress. Dans notre cas, étant donné que la fonctionnalité d'enregistrement est conçue pour plusieurs sites, il est logique de la déplacer dans les plugins MU qui sont chargés lorsque vous ouvrez un site.

Digression lyrique

Il convient de noter que les plugins MU sont chargés plus tôt que les plugins classiques et avant que le noyau WordPress ne soit complètement chargé, donc l'appel de certaines fonctions peut entraîner des erreurs fatales dans PHP. Ce chargement « précoce » a aussi ses avantages. Par exemple, dans n'importe quel thème, vous ne pouvez pas vous accrocher à certaines actions qui sont déclenchées avant même que le fichier functions.php ne soit chargé à partir du thème. Un exemple en est les actions du plugin Jetpack de la forme jetpack_module_loaded_related-posts (related-posts - le nom du module) avec lesquelles il est possible de suivre l'activité des modules dans Jetpack. Il est impossible de "s'accrocher" à cette action depuis le fichier de thème, car l'action a déjà été déclenchée avant que le thème ne soit chargé - les plugins sont chargés avant les thèmes. Pour une image générale de l'ordre de chargement de WordPress, consultez la page Référence d'action dans le codex.

Ordre des fichiers

Les plugins MU peuvent contenir n'importe quel nombre de fichiers et n'importe quelle structure qui vous semble logique. Je m'en tiens à quelque chose comme cette hiérarchie :

| -mu-plugins | - | -load.php | - | - | -selena-network | - | - | - | -signup | - | - | - | - | -plugin.php | - | - | - | - | -... | - | - | - | -jetpack | - | - | - | - | -plugin.php

Tous les "plugins" nécessaires à notre réseau sont connectés dans le fichier load.php :

// Charger les Traslates pour tous les addons load_muplugin_textdomain ("selena_network", "/ selena-network / languages ​​​​/"); // L'inscription au réseau nécessite WPMU_PLUGIN_DIR. "/selena-network/signup/plugin.php" ; // Un autre plugin // nécessite WPMU_PLUGIN_DIR ...

Dans le dossier selena-network, les dossiers des plugins sont stockés, chacun a son propre plugin.php, que nous incluons dans load.php. Cela vous donne de la flexibilité et la possibilité d'éteindre et d'allumer rapidement les choses.

Adresse de la page d'inscription

Pour spécifier l'adresse de la page d'inscription, le filtre wp_signup_location est utilisé. Il se trouve dans le fichier wp-login.php et est responsable de la redirection vers wp-signup.php.

Case "register": if (is_multisite ()) (wp_redirect (apply_filters ("wp_signup_location", network_site_url ("wp-signup.php"))); exit ;

Ajoutons notre fonction à mu-plugins / selena-network / signup / plugin.php, qui renverra l'adresse de la page d'inscription sur le site actuel :

Fonction selena_network_signup_page ($ url) (retour home_url(). "/ Signup /";) add_filter ("wp_signup_location", "selena_network_signup_page", 99);

selena_network est le préfixe que j'utilise dans les noms de toutes les fonctions des plugins MU sur mon site pour éviter les collisions, il doit être remplacé par mon propre préfixe unique. Le filtre a une priorité de 99 car certains plugins comme bbPress et BuddyPress peuvent écraser cette URL avec le leur (les plugins MU se chargent plus tôt que les plugins normaux, voir ci-dessus). Notez que home_url() est utilisé à la place de network_site_url() pour garder le visiteur sur le même domaine. N'importe quelle URL peut être utilisée comme adresse.

Créer une page

Créons maintenant une page avec l'adresse site.com/signup/ via l'interface standard, et dans le dossier du thème enfant, le modèle de notre nouvelle page est page-signup.php. Un identifiant unique peut être utilisé à la place du mot « inscription ».

Dans le nouveau modèle, vous devez appeler la fonction selena_network_signup_main (), qui affichera le formulaire d'inscription.

Il convient de noter que l'ensemble du processus avec les modèles n'est pas requis et que vous pouvez à la place créer votre propre shortcode, qui appellera également la fonction selena_network_signup_main ().

wp-signup.php et wp-activate.php

Commençons maintenant à créer une fonction qui affichera le formulaire d'inscription. Pour ce faire, copiez les fichiers wp-signup.php et wp-activate.php de la racine WordPress vers mu-plugings / selena-network / signup / (et n'oubliez pas de les connecter dans mu-plugins / selena-network / inscription / plugin.php) ... D'autres manipulations avec des fichiers sont extrêmement difficiles et longues à décrire, vous devrez donc les faire vous-même. Je vais seulement décrire ce qu'il faut faire exactement et publier les fichiers sources de mon projet :

  1. Au début du fichier, supprimez tous les require, les appels de fonction et tout autre code en dehors des fonctions.
  2. Renommez toutes les fonctions en ajoutant des préfixes uniques aux noms.
  3. Enveloppez la partie inférieure du code wp-signup.php dans la fonction selena_network_signup_main et écrivez global $ active_signup au tout début ; ...
  4. Remplacez la mise en page par la vôtre aux bons endroits.

Dans wp-activate.php, vous devez faire à peu près la même chose :

  1. Supprimez tout le code en dehors des fonctions, enveloppez la mise en page dans une fonction distincte.
  2. Modifiez la mise en page si nécessaire.

Le fichier wp-activate.php est responsable de la page d'activation du compte. Comme pour la page d'inscription, vous devez créer un modèle distinct pour celle-ci, dans lequel vous appelez la fonction à partir du fichier wp-activate.php.

Nous envoyons des lettres d'activation

La page d'inscription envoie au visiteur un e-mail avec un lien pour activer son compte. Par défaut, cela est fait par la fonction wpmu_signup_user_notification() du fichier ms-functions.php. Sa fonctionnalité peut être empruntée pour votre fonction. La raison pour laquelle vous arrêtez d'utiliser cette fonctionnalité est qu'elle envoie le lien d'activation du compte depuis wp-activate.php. Vous pouvez "désactiver" cette fonction en utilisant le filtre wpmu_signup_user_notification, en lui donnant false (si vous ne le faites pas, la lettre d'activation sera envoyée deux fois, d'accord, en fait, deux lettres différentes).

Fonction armyofselenagomez_wpmu_signup_user_notification ($ user, $ user_email, $ key, $ meta = array ()) (// ... // Code de la fonction wpmu_signup_user_notification () wp_mail ($ user_email, wp_specialchars_decode ($ message_headers), $ message), $ ; return false;) add_filter ("wpmu_signup_user_notification", "armyofselenagomez_wpmu_signup_user_notification", 10, 4);

En conséquence, la page d'inscription dans le thème Selena semble beaucoup plus propre et plus précise.

Conclusion

Il existe de nombreuses autres façons pas très correctes de faire la même chose sur Internet - les redirections Apache, les formulaires AJAX qui ne fonctionneront pas sans Java Script, etc. propre site Web.

Notez que vous devez éditer les fichiers avec soin et essayer de ne pas trop vous écarter de l'original, de sorte que plus tard, si WordPress modifie les fichiers wp-signup.php et wp-activate.php, il serait plus facile de les comparer pour trouver des modifications.

N'oubliez pas de regarder dans le code source de toutes les fonctions décrites ci-dessus pour bien comprendre ce qui se passe à l'intérieur du code et comment.

Prime. Protection contre les spammeurs

Même les plus petits sites WordPress sont soumis à de fréquents enregistrements de spam. Vous pouvez écrire des conditions infinies pour filtrer les bots, souvent plus comme une tentative de création d'intelligence artificielle 🙂 Dans le cas d'un multisite, la redirection habituelle dans Apache m'a beaucoup aidé, avec laquelle, lors de l'ouverture de /wp-signup.php et /wp -acitvate.php, j'ai demandé 404 (je ne suis pas un expert en configuration Apache, donc mes règles ne sont peut-être pas très correctes).

RewriteEngine On RewriteBase / RewriteRule ^ wp-signup \ .php - RewriteRule ^ wp-activate \ .php - # BEGIN WordPress # Ne touchez pas aux règles WordPress par défaut :) # ... # END WordPress

P. S. J'essaie de décrire le plus en détail possible certaines choses de tiers, car quand j'ai commencé, il n'y avait parfois personne pour inciter et expliquer beaucoup de choses. Je crois aussi que de si petits conseils sur d'autres matériaux pousseront quelqu'un à apprendre quelque chose de nouveau et à élargir son champ de connaissances. Les expressions régulières sont utilisées dans les entrées RewriteRule, elles ne sont pas du tout complexes, par exemple, le caractère ^ signifie le début d'une ligne.

Enregistre une fonction à déclencher lorsque le plugin est activé.

Cette fonction attache la fonction de rappel spécifiée au hook activate_ (plugin) et est un emballage pour ce crochet.

(plugin) dans le hook activate_ (plugin) est remplacé par le nom du plugin relatif au fichier principal du plugin. Par exemple, si le plugin se trouve : wp-content / plugins / sampleplugin / sample.php, alors le nom du hook sera : activate_sampleplugin / sample.php.

Depuis la version 3.1. Le hook ne se déclenche que lorsque le plugin est activé et ne se déclenche pas lorsque le plugin est automatiquement mis à jour.

Comment ça fonctionne

Plugin activé par fonction activate_plugin () où le hook activate_ (plugin) se déclenche.

La fonction activate_plugin () dans le noyau est appelée après chargement de l'environnement VI... Cette fonction inclut le fichier principal du plugin (et tout ce qui y est spécifié), puis active la fonction de rappel spécifiée via un hook. Pour cette raison, toutes les fonctions et classes du plugin sont disponibles dans notre fonction de rappel. Mais, étant donné que tous les hooks principaux de WP ont déjà été déclenchés lorsque l'environnement VI est chargé, aucun événement de plugin suspendu aux hooks, par exemple plugins_loaded, ne se déclenchera plus lorsque le fichier de plugin principal est connecté. Cela signifie que notre plugin sera connecté, mais pas complètement : pas comme il devrait l'être lorsqu'il est déjà activé.

Ainsi, par exemple, si un plugin fait quelque chose pendant l'événement plugins_loaded, alors toutes ces actions ne se produiront tout simplement pas lorsque le plugin est activé. Par exemple, s'il connecte un fichier de traduction, alors le fichier de traduction ne sera pas connecté au moment où la fonction de rappel spécifiée pour register_activation_hook() est déclenchée.

En règle générale, après le déclenchement de la fonction de rappel, il y a 2 événements sur lesquels vous pouvez raccrocher les fonctions : enabled_plugin et shutdown.

Pour faire quelque chose d'extraordinaire lors de l'activation d'un plugin, voir l'exemple 5.

Conditions d'utilisation

La fonction ne fonctionnera pas si vous l'appelez au moment où un hook est déclenché, par exemple plugins_loaded, init. La fonction doit être appelée directement depuis le fichier principal du plugin. Règles d'activation :

    register_activation_hook () doit être appelé à partir du fichier de plugin principal où se trouve la directive Plugin Name: ... et ne doit pas être appelé à partir d'un hook comme plugins_loaded ou init.

    La fonction hook doit être dans le même fichier que le hook ou être incluse à l'avance à partir d'un autre fichier.

    Dans la fonction hook, l'écho ne fonctionne pas. Parce qu'il y a une redirection et vous ne verrez pas d'écho. Mais vous pouvez utiliser die ().

  1. Les variables globales (le cas échéant) doivent être définies explicitement pour être accessibles à partir de la fonction hook.

Une note sur la portée variable

Lorsqu'un plugin est activé, le fichier principal du plugin n'est pas inclus dans la portée globale, mais à l'intérieur de la fonction activate_plugin(). Par conséquent, les variables considérées comme globales dans le fonctionnement normal du plug-in ne seront pas globales.

Par exemple, la fonction utilisée dans register_activation_hook() peut ne pas voir les variables globales, même si vous les avez déclarées comme globales dans cette fonction. Exemple:

$ mavar = "quelque chose"; register_activation_hook (__ FILE__, "myplugin_activate"); function myplugin_activate () (global $ myvar; echo $ myvar; // La variable n'est pas égale à "quelque chose")

En raison de cette fonctionnalité, les variables globales doivent toujours être spécifiées explicitement. Toutes les variables globales doivent être définies comme globales, même si la variable est spécifiée dans le corps du plugin. Seulement dans ce cas, il y aura accès n'importe où. Exemple:

Global $ myvar ; // nous indiquons explicitement qu'il s'agit d'une variable globale $ myvar = "quelque chose"; register_activation_hook (__ FILE__, "myplugin_activate"); function myplugin_activate () (global $ myvar; echo $ myvar; //> quelque chose)

Il n'y a pas de crochets.

Retour

nul. Ne renvoie rien.

Usage

register_activation_hook (fichier $, fonction $); fichier $ (chaîne) (obligatoire) Le chemin d'accès au fichier php principal du plugin, y compris le nom du plugin lui-même. Habituellement, la constante PHP magique __FILE__ est utilisée. fonction $ (chaîne / tableau / lambda) (obligatoire)

Le nom de la fonction de rappel. Pour les classes, utilisez un tableau : array ($ this, "function_name"); ...

La fonction recevra une variable booléenne $ network_wide - si le plugin est activé pour l'ensemble du réseau de sites en multisite.

Exemples de

#un. Exécuter une fonction lors de l'activation d'un plugin

Supposons que nous ayons une fonction my_plugin_activate() dans le fichier principal du plugin : wp-content / plugins / myplugin / myplugin.php, alors pour exécuter cette fonction lors de l'activation du plugin, utilisez le code suivant :

Register_activation_hook (__ FILE__, "my_plugin_activate"); fonction my_plugin_activate() (// Code d'activation ...)

# 2. Exécuter une méthode de classe

Si le plugin utilise une classe PHP, le code d'activation est ajouté comme ceci :

Register_activation_hook (__ FILE__, tableau ("My_Plugin", "install")); class My_Plugin (static function install () (// Ne créez aucune sortie ici ...))

# 3. Exécuter une méthode de classe à partir d'un fichier séparé

Si la classe qui contient la fonction d'activation se trouve dans un fichier séparé, enregistrez la fonction d'activation comme ceci :

Inclure_une fois __DIR__. "/class-Mon_Plugin.php" ; register_activation_hook (__ FILE__, tableau ("My_Plugin", "on_activate_function"));

#4. Exécuter une méthode de classe à partir de la classe elle-même

Si vous êtes dans __construct(). Il est important de noter que __FILE__ doit « regarder » le fichier principal du plugin :

Register_activation_hook (__ FILE__, tableau ($ this, "YOUR_METHOD_NAME"));

#5 Faites quelque chose juste après avoir activé le plugin

Après avoir activé le plugin, seuls deux hooks sont déclenchés : enabled_plugin et shutdown.

Lorsque vous devez faire quelque chose immédiatement après avoir activé un plugin, vous pouvez leur attacher une fonction.

Lorsqu'une telle solution ne fonctionne pas, vous pouvez utiliser les options WP : enregistrez les données dans une option, puis vérifiez l'option et faites quelque chose s'il existe une option :

// Fichier principal du plugin. ... fonction my_plugin_activate() (// ajouter une option pour que plus tard s'il y en a un pour faire quelque chose. add_option ("Activated_Plugin", "Plugin-Slug"); // Voici le code d'activation ...) register_activation_hook ( __ FILE__, " my_plugin_activate "); function load_plugin () (if (is_admin () && get_option ("Activated_Plugin") == "Plugin-Slug") (// supprimer l'option ajoutée pour qu'elle ne fonctionne plus // et faire ce dont nous avons besoin ... delete_option ( "Activated_Plugin "); // Faire quelque chose une fois, après avoir activé le plugin // Par exemple : add_action (" init "," my_init_function ");)) add_action (" admin_init "," load_plugin ");

Une autre option pour faire quelque chose pendant l'activation du plugin est de créer votre événement comme ceci :

Function my_plugin_activate () (// Installer notre propre hook afin que vous puissiez y attacher à partir des fichiers du plugin lui-même do_action ("my_plugin_activate");) register_activation_hook (__ FILE__, "my_plugin_activate");

# 6 Une autre démonstration d'utilisation de la fonction

Un petit plugin démontrant comment utiliser la fonction :

/ * Nom du plugin : Un test Description : Un test * / require_once dirname (__ FILE__). "/mon_autre_fichier.php" ; / * Ce code ne fonctionnera pas. Le hook d'activation doit être appelé à partir du fichier principal. register_activation_hook (dirname (__ FILE__). "/my_other_file.php", "my_other_function"); * / // Ceci est un code fonctionnel. register_activation_hook (__ FILE__, "test_activated"); / * C'est la manière correcte de déclarer et d'accéder aux variables globales. Les variables globales doivent être déclarées clairement. Sans cela, vous n'y aurez pas accès. * / global $ some_var; $ some_var = "hey"; // Fonction d'activation fonction test_activated () (// ici $ some_var ne sera pas égal à hey global $ some_var; // Et ici $ some_var sera égal à hey // Cette fonction est définie dans le fichier "my_other_file.php" my_other_function () ; / * Cela ne fonctionnera pas. Si vous devez écrire des journaux dans un fichier temporaire, utilisez fopen / fwrite. Si vous voulez tester si le hook d'activation fonctionne, utilisez exit () dans la fonction hook. * / echo " test_activated appelé !";)