Initial commit

This commit is contained in:
2026-05-12 23:33:46 +02:00
commit ccf32dcece
104 changed files with 17439 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
<?php
/**
* Intercepte les erreurs de validation Pods lors du save d'un post admin :
* - Empêche wp_die() (qui publiait quand même le post sans les champs Pods)
* - Annule le changement de statut si le post n'était pas encore publié
* - Redirige vers la page d'édition avec les champs restaurés via transient
*/
// Capture l'ID du post en cours de sauvegarde (avant Pods, qui peut le créer pour les nouveaux posts)
add_action( 'save_post', function ( $post_id ) {
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
$GLOBALS['thalim_saving_post_id'] = $post_id;
}, 1 );
// Intercepte wp_die() de Pods pendant un save admin
add_filter( 'pods_error_die', function ( $die, $error ) {
if ( ! is_admin() || ! isset( $_REQUEST['action'] ) || $_REQUEST['action'] !== 'editpost' ) {
return $die;
}
$post_id = $GLOBALS['thalim_saving_post_id'] ?? intval( $_POST['post_ID'] ?? 0 );
if ( ! $post_id ) {
return $die;
}
$user_id = get_current_user_id();
// Collecter les valeurs Pods soumises
$restore = [];
foreach ( $_POST as $key => $val ) {
if ( str_starts_with( $key, 'pods_meta_' ) ) {
$restore[ $key ] = is_array( $val ) ? array_map( 'wp_unslash', $val ) : wp_unslash( $val );
}
}
$error_text = is_wp_error( $error ) ? $error->get_error_message() : (string) $error;
$restore['_msg'] = wp_strip_all_tags( $error_text );
$restore['_title'] = sanitize_text_field( wp_unslash( $_POST['post_title'] ?? '' ) );
set_transient( 'thalim_pods_restore_' . $post_id . '_' . $user_id, $restore, 10 * MINUTE_IN_SECONDS );
$GLOBALS['thalim_pods_error_post_id'] = $post_id;
return false; // empêche wp_die()
}, 10, 2 );
// Après le save : rediriger vers la page d'édition + annuler le statut si besoin
add_filter( 'redirect_post_location', function ( $location ) {
$post_id = $GLOBALS['thalim_pods_error_post_id'] ?? 0;
if ( ! $post_id ) {
return $location;
}
// Annuler le changement de statut vers publish si le post n'était pas encore publié
$original = isset( $_POST['original_post_status'] ) ? sanitize_key( $_POST['original_post_status'] ) : '';
$post = get_post( $post_id );
if (
$post &&
in_array( $post->post_status, [ 'publish', 'future', 'pending' ], true ) &&
! in_array( $original, [ 'publish', 'future', 'pending' ], true )
) {
global $wpdb;
$wpdb->update(
$wpdb->posts,
[ 'post_status' => $original ?: 'draft' ],
[ 'ID' => $post_id ],
[ '%s' ],
[ '%d' ]
);
clean_post_cache( $post_id );
}
return admin_url( 'post.php?post=' . $post_id . '&action=edit' );
}, 10 );
// Sur la page d'édition (GET) : lire le transient une seule fois → global → supprimer
add_action( 'current_screen', function ( $screen ) {
if ( $screen->base !== 'post' ) {
return;
}
$post_id = isset( $_GET['post'] ) ? intval( $_GET['post'] ) : 0;
if ( ! $post_id ) {
return;
}
$user_id = get_current_user_id();
$key = 'thalim_pods_restore_' . $post_id . '_' . $user_id;
$data = get_transient( $key );
if ( ! $data ) {
return;
}
$GLOBALS['thalim_pods_restore'] = [
'post_id' => $post_id,
'data' => $data,
];
delete_transient( $key );
} );
// Injecter les valeurs dans get_post_meta → Pods DFV les embarque dans son JSON React
add_filter( 'get_post_metadata', function ( $value, $object_id, $meta_key, $single ) {
$restore = $GLOBALS['thalim_pods_restore'] ?? null;
if ( ! $restore || $restore['post_id'] !== (int) $object_id ) {
return $value;
}
$pods_key = 'pods_meta_' . $meta_key;
if ( ! isset( $restore['data'][ $pods_key ] ) ) {
return $value;
}
$val = $restore['data'][ $pods_key ];
return $single ? $val : [ $val ];
}, 10, 4 );
// Restauration JS : titre + champs Pods select/pick via PodsDFV (même pattern que les modales)
add_action( 'admin_footer', function () {
$restore = $GLOBALS['thalim_pods_restore'] ?? null;
if ( ! $restore ) {
return;
}
$screen = get_current_screen();
if ( ! $screen || $screen->base !== 'post' ) {
return;
}
$post_id = intval( $restore['post_id'] );
$title = $restore['data']['_title'] ?? '';
// Construire le map fieldName => value pour les champs Pods
$fields = [];
foreach ( $restore['data'] as $key => $val ) {
if ( str_starts_with( $key, 'pods_meta_' ) ) {
$fields[ substr( $key, 10 ) ] = $val;
}
}
?>
<script>
(function ($) {
var postId = <?php echo $post_id; ?>;
var fields = <?php echo wp_json_encode( $fields ); ?>;
var title = <?php echo wp_json_encode( $title ); ?>;
function doRestore() {
// Titre WordPress (non géré par get_post_metadata)
var $titleInput = $('#title');
if ($titleInput.length && !$titleInput.val() && title) {
$titleInput.val(title).trigger('input');
}
// Champs Pods : DOM direct + PodsDFV pour les selects/picks
Object.keys(fields).forEach(function (fieldName) {
var value = fields[fieldName];
var $el = $('[name="pods_meta_' + fieldName + '"]');
if ($el.length) {
$el.val(value).trigger('change');
}
if (window.PodsDFV && postId) {
try {
window.PodsDFV.setFieldValue('post', postId, fieldName, value, 0);
} catch (e) {}
}
});
}
$(window).on('load', function () {
setTimeout(doRestore, 300);
});
}(jQuery));
</script>
<?php
} );
// Afficher le message d'erreur en admin notice
add_action( 'admin_notices', function () {
$restore = $GLOBALS['thalim_pods_restore'] ?? null;
if ( ! $restore ) {
return;
}
$screen = get_current_screen();
if ( ! $screen || $screen->base !== 'post' ) {
return;
}
$msg = esc_html( $restore['data']['_msg'] ?? '' );
if ( $msg ) {
echo '<div class="notice notice-error is-dismissible"><p>' . $msg . '</p></div>';
}
echo '<div class="notice notice-info is-dismissible"><p>Votre contenu a &eacute;t&eacute; restaur&eacute;. V&eacute;rifiez les champs obligatoires avant de republier.</p></div>';
} );