Matt Biscay: développeur WordPress et WooCommerce pour SkyMinds
Réalisation de votre projet web photo

Réalisons votre projet WordPress ou WooCommerce

Nos compétences au service de vos besoins

Stratégie

Nous étudions le parcours de votre site et vos besoins pour vous fournir une solution à long-terme, qui correspond à votre vision.

Développement

Vous souhaitez ajouter de nouvelles fonctionnalités à votre site ou boutique? Nous pouvons coder la solution!

Performance

Votre site doit être rapide et optimisé sur tous supports afin de convertir vos visiteurs. Nous auditons votre site et proposons la solution adaptée.

Hébergement

Vos projets ont besoin d’un hébergement de qualité, c’est la fondation de votre site web et elle doit être solide car c’est sur elle que tout repose.

Maintenance

Votre site a besoin d’une maintenance régulière afin de toujours utiliser la dernière mouture du code et rester sécurisé face aux menaces.

Assistance

Vous avez besoin d’aide ponctuelle? Pas de problème, nous sommes à votre écoute pour vous dépanner rapidement et sereinement.

Lire la suite

Group photo of all devs at Cloudfest Hackathon 2022

Le Hackathon du CloudFest 2022

Cette année, j’ai eu la chance et le grand honneur d’être invité au CloudFest 2022 pour le hackathon: 3 jours de code sur un projet web en mode open-source pour faire avancer les choses.

Le Cloudfest

Le Cloudfest est une convention de développeurs et d’acteurs du web qui peuvent être extrêmement variés: cela va des hébergeurs web aux plateformes comme Codeable mais aussi avec de gros acteurs comme Airbus, Intel, Automattic, HP, Cpanel, Plesk…

Les conférences sont très variées: intelligence artificielle, business… et il est très facile de rencontrer des gens très connus sur le web pour se faire un réseau.

Le Cloudfest se tient à Rust, en Allemagne, à l’Europa Park.

Le Hackathon

Cette année le hackathon proposait plusieurs projets mais j’ai opté pour travailler sur wp-cli pour ajouter une nouvelle commande qui permettre de sécuriser 80% des attaques contre les instances WordPress, en appliquant simplement les meilleures pratiques de sécurité courantes.

Les devs du Hackathon 2022
Les devs du Hackathon 2022

Concrètement, nous avons identifié les problèmes de sécurité courants et nous avons développé une extension de l’interface de ligne de commande WordPress (wp-cli) pour offrir une alternative sécurisée et facile à utiliser aux plugins de sécurité WordPress généralement non sécurisés.

Avec la simple commande wp secure all, les meilleures pratiques courantes sont appliquées automatiquement à votre instance WordPress, et en moins de 60 secondes, vous attenuez la grande majorité des vecteurs d’attaque WordPress actuels : permissions de fichiers et de dossiers, entêtes de sécurité, bloquer l’accès aux fichiers sensibles…

Lire la suite

WordPress : rediriger la page d'attachement vers l'article auquel les fichiers médias appartiennent photo

WordPress : rediriger la page d’attachement vers l’article parent

WordPress publie par défaut une page d’attachement pour chaque fichier média que vous publiez sur votre site.

En règle générale, un fichier média (image, vidéo, autre) appartient à un article: on attache souvent ce type de fichier lors de la rédaction des articles, pour les insérer dans le corps des billets.

Le problème est donc que WordPress crée gentiment une page dédiée à chaque média publié. Cette page ne contient aucun contenu, à part afficher le média en question, ce qui n’est pas vraiment idéal au point de vue SEO puisque l’on se retrouve avec énormément de pages mais qui ne seront jamais indexées au vu du contenu inexistant. S’il est donc superflu d’avoir ces pages, autant s’en séparer!

C’est là que nous allons tenter d’être malin : pourquoi ne pas rediriger ces pages d’attachement vers l’article auquel ces fichiers media appartiennent?

Jusqu’à très récemment, j’utilisais le module Origin de The SEO Framework, qui fonctionne très bien si le média a été uploadé sur un article. La page d’attachement est alors automatiquement redirigée vers l’article.

Le hic, c’est que si le fichier média a été uploadé directement depuis la page WP Admin > Média, alors nous sommes redirigé vers /wp-admin, ce qui ne fait aucun sens.

Voici donc la solution que j’utilise sur le site:

<?php
/*
Script Name: Redirect attachment page to parent post.
Script URI: https://www.skyminds.net/?p=32314
Description: Redirects attachment to parent post (if it exists), or redirects to the homepage otherwise.
Version: 2.6.0
Author: Matt Biscay
Author URI: https://mattbiscay.com
*/
add_action( 'template_redirect', 'sky_redirect_attachment_to_post' );
function sky_redirect_attachment_to_post(){
  // if not an attchment, bail out early
  if( !is_attachment() ) {
    return;
  }
  // check if parent post is defined
  if( isset( $post ) && isset( $post->post_parent ) && is_numeric( $post->post_parent ) && ( $post->post_parent != 0 ) ) :
    // redirect to parent post
    wp_redirect( esc_url( get_permalink( $post->post_parent ) ) ); exit;
  else: // media has been uploaded through the Media page or is unattached to a specific post
    // redirect to homepage
    wp_redirect( esc_url( home_url( '/' ) ) ); exit;
    // or redirect to the media itself
    // wp_redirect( esc_url( wp_get_attachment_url() ) ); exit;
  endif;
}

Ce code est à copier-coller dans le fichier functions.php de votre thème enfant. Vous pouvez également l’enregistrer en tant que plugin.

Une fois activé, si vous visionnez l’adresse d’une page d’attachement, vous devriez être redirigé sur l’article parent.

Notez que je vous ai mis 2 possibilités pour la redirection lorsque le media n’a pas été attaché à un article: une redirection vers la page d’accueil ou alors vers le fichier média directement.

A vous de choisir ce qui vous correspond le mieux :)

Ajouter un lien avec le nombre d'articles et le total du panier WooCommerce photo

Rendre la page panier WooCommerce réactive

Lors de mon dernier projet WooCommerce, j’ai remarqué que la page panier de WooCommerce n’était pas vraiment réactive sous Safari (iPhone, iOS) : le tableau ne s’empile pas comme il le devrait et toutes les colonnes sont comprimées. Les dernières colonnes sont hors du viewport.

Safari sous iOS (iPhone) semble être le seul concerné – je n’ai pas réussi à reproduire ce comportement sur FireFox, Chrome ou Opera.

Le site en question utilise Astra, qui est vraiment bien éprouvé, ainsi qu’Elementor comme constructeur de page.

Voici comment rendre le tableau du panier WooCommerce réactif, en utilisant quelques lignes de CSS.

Forcer la réactivité du panier WooCommerce

J’ai opté pour une solution propre, en CSS, en ne ciblant que les iPhones puisqu’ils sont les seuls concernés (Safari + résolution d’écran).

Voici donc le code utilisé pour rendre le panier WooCommerce réactif:

/*
Plugin Name: Sky WooCommerce Responsive Cart
Plugin URI: https://mattbiscay.com
Description: Make WooCommerce cart responsive
Version: 1.1
Author: Matt Biscay
Author URI: https://mattbiscay.com
*/

/* responsive cart */
@media only screen and ( max-width: 479px ) {
  
  .short-description, .product_meta, body.woocommerce div.product .woocommerce-tabs, body.woocommerce #content div.product .woocommerce-tabs { display: none; }
  body.woocommerce .images { float: none !important; width: auto !important; margin-bottom: 40px !important; clear: both !important; }
  
  table .product-thumbnail { display: none; }
  
  .woocommerce-page #content div.product form.cart .variations { margin-left: 0; }
  
  table.cart th, #content table.cart th, table.cart td, #content table.cart td, table.cart tr, #content table.cart tr, #content-area table tr, #content-area table td, #content-area table th { padding: .857em 0.287em; }
  
  .woocommerce .woocommerce .col2-set .col-1, .woocommerce-page .col2-set .col-1, .woocommerce .col2-set .col-2, .woocommerce-page .col2-set .col-2 { width: 100% !important; }
  .woocommerce .woocommerce form .form-row, .woocommerce-page form .form-row { width: auto !important; float: none !important; }
  
  #order_review .shop_table { margin-left: 0; }
  
  /* cart: tax on its own line */
  .includes_tax { display: block; }
  
}

/* cart weird bug on Safari: cart table is not collapsing */
/* this corrects the bug on iphones */

@media (max-width: 768px){
  .iphone .woocommerce table.shop_table_responsive tr,
  .iphone .woocommerce-page table.shop_table_responsive tr {
    display: flex;
    flex-direction: column;
    flex-basis: 100%;
    flex: 1;
  }
  
  .woocommerce table.shop_table_responsive tr td::before, .woocommerce-page table.shop_table_responsive tr td::before {
    content: attr(data-title) ' ';
    font-weight: 700;
    float: left;
  }
  
  p.no-shipping-options {
    clear: both;
    margin-top: 3rem;
  }
}

Lire la suite

Créer un site staging pour WordPress sur un sous-domaine photo

Créer un site staging pour WordPress sur un sous-domaine

Le Centre de Kriya Yoga France n’avait pas de site staging, ce site de développement et de test qui permet de tester, développer ou mettre à jour de nouvelles extensions, sans affecter le site principal.

Une des extensions a eu besoin d’être débugguée par ses concepteurs mais pour des raisons de confidentialité, il nous est apparu intéressant et plus sécurisé de donner accès à un site de développement, fraîche copie du site original, pour le débuggage.

Si vous avez besoin de créer un site staging pour votre site WordPress et que votre hébergeur ne le propose pas, voici comment faire.

Étape 1 : créer un sous-domaine au niveau DNS

Nous choisissons la solution la plus simple: servir le site STAGING depuis un sous-domaine. Il suffit de créer un nouvel enregistrement DNS sous la forme:

staging IN A xxx.xxx.xxx.xxx

staging represente le sous-domaine et xxx.xxx.xxx.xxx représente l’adresse IPv4 du serveur.

Étape 2 : créer le server block sous NginX

Le domaine étant déjà actif, j’ai uniquement rajouté ce server block:

### STAGING ###
 server {
 listen              443 ssl http2;
 listen              [::]:443 ssl http2;
 server_name staging.kriyayoga.fr;
 root /home/www/kriyayoga/staging/public_html;
 set $root /home/www/kriyayoga/staging/public_html;
 index index.php index.htm index.html;
 error_log /var/log/nginx/kriyayoga_staging_error.log;
 #SSL
 ssl_certificate        /etc/nginx/ssl/kriyayoga.fr/fullchain.pem;
 ssl_certificate_key    /etc/nginx/ssl/kriyayoga.fr/privkey.pem;
 include snippets/mime-types.conf;
 #Exclusions
 include snippets/exclusions.conf;
 #Security
 include snippets/security.conf;
 #Static Content
 include snippets/static-files.conf;
 #Fastcgi cache rules
 include snippets/fastcgi-cache.conf;
 include snippets/limits.conf;
 include snippets/nginx-cloudflare.conf;
 #Gzip
 include snippets/gzip.conf;
 location / {
 try_files $uri $uri/ /index.php?$args;
 }
 location ~ .php$ {
 try_files $uri =404;
 include snippets/fastcgi-params.conf;
 fastcgi_pass unix:/run/php/php7.4-fpm.sock;
 #Skip cache based on rules in snippets/fastcgi-cache.conf.
 fastcgi_cache_bypass $skip_cache;
 fastcgi_no_cache $skip_cache;
 #Define memory zone for caching. Should match key_zone in fastcgi_cache_path above.
 fastcgi_cache kriyayoga;
 #Define caching time.
 fastcgi_cache_valid 60m;
 #increase timeouts
 fastcgi_read_timeout 6000;
 fastcgi_connect_timeout 6000;
 fastcgi_send_timeout 6000;
 proxy_read_timeout 6000;
 proxy_connect_timeout 6000;
 proxy_send_timeout 6000;
 send_timeout 6000;
 #these lines should be the ones to allow Cloudflare Flexible SSL 
 #to be used so the server does not need to decrypt SSL if you wish
 proxy_set_header X-Forwarded-Host $host;
 proxy_set_header X-Forwarded-Server $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto https;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-NginX-Proxy true;
 }
 #Protect WooCommerce upload folder from being accessed directly.
 #You may want to delete this config if you are using "Redirect Only" method for downloadable products.
 #Place this config towards the end of "server" block in NginX configuration.
 location ~* /wp-content/uploads/woocommerce_uploads/ {
   if ( $upstream_http_x_accel_redirect = "" ) {
     return 403;
     }
     internal;
 }
 }

Testez la nouvelle configuration:

nginx -t

Puis redémarrez NginX:

service nginx reload

Note: il est important de noter que je n’ai pas besoin de créer de certificat SSL puisque mes certificats sont wildcard par défaut. Si ce n’est pas le cas chez vous, pensez à en générer pour votre sous-domaine.

Lire la suite

Nettoyer un site WordPress infecté par un script shell photo 1

Nettoyer un site WordPress infecté par un script shell

Il n’est pas rare de voir des sites WordPress infectés par des scripts shell, qui peuvent exploiter certaines failles du core WordPress, de plugins ou de thèmes.

Ces attaques de WordPress sont courantes et concernent les sites qui n’ont pas été protégés par un antivirus ou un plugin de sécurité comme iThemes Security.

Il peut donc arriver que certains malwares infestent votre site WordPress, de manière automatisée si certaines composantes (core, plugins, themes) ne sont pas mis à jour régulièrement.

La technique détaillée ci-dessous vous permet d’identifier et de supprimer ces fichiers dans vos dossiers WordPress.

Important: avant de commencer, faites une sauvegarde du site: fichiers et base de données.

Étape 1 : suppression des fichiers potentiellement infectés

Sur l’installation en question, ces fichiers n’appartiennent pas à WordPress ou sont infectés. Nous les supprimons à vue:

rm 1index.php index.php db.php del.php wikindex.php

Nous supprimons également les répertoires wp-admin et wp-includes de WordPress car souvent des fichiers malfaisants sont copiés dedans:

rm wp-admin -rf
rm wp-includes -rf

Étape 2 : réinstallation de WordPress

On réinstalle WordPress:

wp core download --force --skip-content --locale=fr_FR --allow-root

Lire la suite

Jethro Tull - Aqualung photo

Local : importer une base de données depuis le shell

Local possède une version d’Adminer dans les options de chaque site qui est très utile puisqu’elle permet d’accéder rapidement à la base de données, ou d’importer une petite base de données.

Par contre, s’il s’agit d’importer une base qui fait plus de 80 Mo, mieux vaut se tourner vers un outil un peu plus robuste: le shell.

Accéder au shell depuis Local

Et cela tombe bien : Local possède son propre shell, accessible sur simple clic-droit sur le nom du site sur lequel vous souhaitez ouvrir une fenêtre de terminal:

local open site shell new 1280x787

Voici la marche à suivre : Démarrez votre site > sélectionnez le nom du site > clic-droit > Open Site Shell

Importer une base de données dans un site Local

Lorsque j’ai besoin de répliquer un site rapidement, je copie la base données dans le répertoire app du site Local en question.

Pour mon site de test (skyminds-2020 ), le chemin sur ma machine est /Users/matt/Local Sites/skyminds2020/app . C’est dans ce dossier que je place le fichier SQL à importer.

Ensuite, dans le shell Local, il suffit de faire un simple import SQL dans la base qui, par défaut, s’appelle local (et ce, pour tous vos sites Local, bien qu’elles soient toutes indépendantes).

L’utilisateur est root et le mot de passe root également, ce qui est plutôt pratique.

Le shell est par défaut sous app/public donc on remonte d’un cran dans l’arborescence pour pointer vers notre fichier (qui se trouve dans /app ).

Voilà ce que cela nous donne:

mysql -u root -proot local < ../db.sql

Résultat:

mysql: [Warning] Using a password on the command line interface can be insecure.
bash-3.2$

L’importation de la base de données SQL ne prend que quelques secondes, alors que cela se plante allégrement lorsque l’on utilise Adminer.

A utiliser sans modération, cela ne vaut vraiment pas le coup de s’embêter avec une interface graphique (ou à placer le fichier dans le répertoire d’adminer comme il l’indique sur la page d’importation).

WordPress: retirer l'option de supprimer les plugins dans l'interface d'administration photo

WordPress: retirer l’option de supprimer les extensions dans l’interface d’administration

C’est assez rare comme demande mais je me suis exécuté: comment faire pour retirer le lien qui permet de supprimer les plugins désactivés dans l’interface d’administration, même si l’on est administrateur ?

Et bien c’est assez simple, il suffit de filtrer le tableau des liens. Voici deux exemples simple pour mettre cela en place.

Retirer le lien de suppression pour toutes les extensions

Voici le code qui vous permet de retirer le lien “Supprimer” qui se trouve en dessous de chaque extension sur la page Extensions:

<?php
/*
Plugin Name: Disable Plugin Deletion
Plugin URI: https://www.skyminds.net/?p=32830
Description: Disable all plugins' deletion links on the plugins page.
Version: 1.0
Author: Matt Biscay
Author URI: https://mattbiscay.com
*/
add_filter( 'plugin_action_links', 'sky_disable_plugin_deletion', 10, 4 );
function sky_disable_plugin_deletion( $actions, $plugin_file, $plugin_data, $context ) {
  // Remove delete link for all installed plugins         
  unset( $actions['delete'] );     
  return $actions;
} 

Retirer le lien de suppression pour des extensions spécifiques

Voici le code qui vous permet de retirer le lien “Supprimer” qui se trouve en dessous des extensions dont vous spécifiez le chemin (dossier et nom du fichier de l’extension à charger) sur la page Extensions:

<?php
 /*
 Plugin Name: Disable Plugin Deletion
 Plugin URI: https://www.skyminds.net/?p=32830
 Description: Disable all plugins' deletion links on the plugins page.
 Version: 1.0
 Author: Matt Biscay
 Author URI: https://mattbiscay.com
 */
 add_filter( 'plugin_action_links', 'sky_disable_plugin_deletion_selected', 10, 4 );
 function sky_disable_plugin_deletion_selected( $actions, $plugin_file, $plugin_data, $context ) {
   // Remove delete link for specific plugins
   if ( array_key_exists( 'delete', $actions ) && in_array( $plugin_file,
   [
     'akismet/akismet.php',
     'redirection/redirection.php',
   ]
   ) ) {
     unset( $actions['delete'] );
   }
   return $actions;
 }

Dans ce dernier snippet, pensez à modifier le nom du répertoire et celui du plugin de manière à ce qu’ils coïncident avec les plugins qui ne doivent pas être supprimés.

A l’origine, c’était pour un de mes clients pour éviter que ses collaborateurs ne suppriment des plugins par inadvertance.

Je m’en sers également sous LocalWP pour éviter de supprimer un plugin en cours de développement – on ne sait jamais!

Ajouter un lien avec le nombre d'articles et le total du panier WooCommerce photo

Ajouter un lien avec le nombre d’articles et le total du panier WooCommerce

Rares sont désormais les thèmes WordPress qui n’offrent pas le support de WooCommerce tant l’extension qui propulse aujourd’hui des millions de boutiques en ligne est populaire.

Toutefois, le code de WooCommerce évolue en permanence et certaines fonctions changent de nom ou sont appelées différemment.

Un thème compatible avec WooCommerce 2.6 ne l’était plus avec WooCommerce 3.3 par exemple, lorsque toutes les fonctions relatives au panier sont passées à des fonctions objets.

Montrer le nombre d’articles dans le panier dans le thème

Un client Codeable m’a récemment demandé de mettre à jour son thème, qui n’est plus supporté par son auteur, pour afficher le nombre d’articles dans le panier.

Voici le code à insérer, soit dans un des fichiers de votre thème (header.php est le plus indiqué dans notre cas) ou alors dans un widget HTML:

<a class="cart-custom" href="<?php echo wc_get_cart_url(); ?>" title="<?php _e( 'View your shopping cart' ); ?>"><?php echo sprintf ( _n( '%d item', '%d items', WC()->cart->get_cart_contents_count() ), WC()->cart->get_cart_contents_count() ); ?> - <?php echo WC()->cart->get_cart_total(); ?></a>

Lire la suite

Redémarrer la machine virtuelle de Local by Flywheel photo

Local : résoudre les problèmes d’importation de la base de données

Aujourd’hui, on importe la base de données d’un site existant dans la nouvelle version de Local Lightning, estampillée 5.4.1.

D’habitude, je lance Adminer > Import, je sélectionne mon fichier de base de données et boom, la base est importée. Mais aujourd’hui, rien ne se passe comme prévu: Adminer mouline, mouline, perd la moitié du design de sa page et n’importe pas la base.

SSH à la rescousse

Je me dis qu’on aura peut-être plus de chance depuis la console SSH. Dans Local, faites un clic droit sur le site > Open Site Shell. Une fenêtre de terminal apparaît alors.

Utilisation de WP-CLI

On commence d’abord par la méthode wp-cli. On copie notre fichier adminer.sql sous /app/public et on lance la commande suivante:

wp db import ./adminer.sql

Résultat:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

Cela commence bien. La version 5 de Local utilise MySQL 8 donc certaines choses ne sont peut-être pas tout à fait au point. Comme il n’y a pas de socket mysql dans /tmp/mysql.sock, nous allons manuellement spécifier notre socket MySQL dans notre commande. Local nous donne l’adresse du socket dans l’onglet Database:

wp db import ./adminer.sql --socket="/Users/matt/Library/Application Support/Local/run/rvrb6Ce-Z/mysql/mysqld.sock"

Résultat:
ERROR 1067 (42000) at line 23841 in file: './adminer.sql': Invalid default value for 'comment_date'

La bonne nouvelle, c’est que l’on peut se connecter à la base de données MySQL. Mais tiens donc, nous sommes déjà tombés sur cette erreur Invalid default value for comment_date !

Configuration de MySQL

Pour régler le problème sous Local, la marche à suivre diffère un peu de ce que nous avions lancé sur notre serveur puisqu’il n’y a pas une mais deux variables de configuration de mysqld à modifier.

On se connecte au serveur mysql:

mysql -u root -proot

Commençons par voir ce que les variables sql_mode contiennent:

SELECT @@GLOBAL.sql_mode; SELECT @@SESSION.sql_mode; 

Résultat:

+------------------------------------------------------------------------------------------+
| @@GLOBAL.sql_mode                                                                        |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

+------------------------------------------------------------------------------------------+
| @@SESSION.sql_mode                                                                       |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+

Le problème est, comme la dernière fois, la présence de ces deux instructions: NO_ZERO_IN_DATE,NO_ZERO_DATE.

On enlève donc ces deux instructions de nos deux directives:

SET @@GLOBAL.sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";
SET @@SESSION.sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION";

Voilà ce que nous obtenons au final:

+------------------------------------------------------------------------------------------+
| @@GLOBAL.sql_mode                                                                        |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

+------------------------------------------------------------------------------------------+
| @@SESSION.sql_mode                                                                       |
+------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

On peut désormais importer notre fichier SQL:

mysql -u root -proot local < ./adminer.sql 

Hop l’import de la base de données se passe maintenant sans aucun problème.

Gravity Forms : activer l'anti-spam honeypot sur tous les formulaires photo

Gravity Forms : supprimer les entrées mais garder les fichiers uploadés sur le site

Gravity Forms garde en base de données toutes les entrées des formulaires. Sur un site qui génère énormément de demandes (formulaire de contact, demandes d’informations, formulaire de commande ou pré-commande…).

Cela signifie des milliers d’enregistrements dans la base de données, ce qui n’est pas toujours souhaitable, pour des raisons de stockage et de performance.

Supprimer les entrées des formulaires Gravity Forms

Si vous avez besoin de supprimer les entrées créées par Gravity Forms une fois que le message a été envoyé, vous pouvez utiliser cette fonction:

// Delete all entries from form ID  1.
add_action( 'gform_after_submission_1', 'sky_remove_form_entry' );
function sky_remove_form_entry( $entry ) {
    GFAPI::delete_entry( $entry['id'] );
}

Dans l’exemple ci-dessus, on ne supprime que les entrées du formulaire qui a l’ID 1. Si vous souhaitez supprimer toutes les entrées de tous les formulaires Gravity Forms d’un site, il suffit d’enlever le _1de la cible de l’action gform_after_submission:

// Delete all entries from all forms.
add_action( 'gform_after_submission', 'sky_remove_form_entry' );
function sky_remove_form_entry( $entry ) {
    GFAPI::delete_entry( $entry['id'] );
}

Garder les fichiers uploadés lors de la suppression des entrées

Attention: supprimer les entrées Gravity Forms revient également à supprimer les fichiers qui auront été uploadés via les formulaires. C’est tout à fait normal puisqu’ils font partie des champs du formulaire.

Pour garder les fichiers uploadés, même si les entrées associées sont supprimées, il faut utiliser le filtre gform_field_types_delete_files:

add_filter( 'gform_field_types_delete_files', '__return_empty_array' );

Supprimer les fichiers associés à un champ upload particulier

Si vous souhaitez supprimer tous les fichiers qui auront été uploadés via un champ upload particulier, il suffit de préciser ce champ dans le tableau $field_types avant de le passer à gform_field_types_delete_files:

add_filter( 'gform_field_types_delete_files', 'sky_delete_custom_upload_field' );
function sky_delete_custom_upload_field( $field_types ) {
    $field_types[] = 'my_custom_upload_field';
    return $field_types;
}

Dans cet exemple, notre champ upload s’appelle my_custom_upload_field.