first commit
This commit is contained in:
305
wp-thumbor.php
Normal file
305
wp-thumbor.php
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
Plugin Name: WP Thumbor Integration
|
||||||
|
Description: Intègre Thumbor dans WordPress en transformant les URLs des images sur le front-end. L'URL de Thumbor, les filtres et la clé secrète sont configurables. Les images sont redimensionnées si une taille est spécifiée dans le nom du fichier ou dans les attributs HTML. La transformation est désactivée dans certains cas (ex. Optimize More) pour éviter les erreurs getimagesize().
|
||||||
|
Version: 1.3
|
||||||
|
Author: MrRaph_
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) {
|
||||||
|
exit; // Sécurisation
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère les options du plugin avec des valeurs par défaut.
|
||||||
|
*/
|
||||||
|
function wp_thumbor_get_options() {
|
||||||
|
$defaults = array(
|
||||||
|
'thumbor_base_url' => '',
|
||||||
|
'thumbor_filters' => '',
|
||||||
|
'thumbor_secret_key' => '',
|
||||||
|
);
|
||||||
|
$options = get_option('wp_thumbor_options', $defaults);
|
||||||
|
return wp_parse_args($options, $defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si la transformation Thumbor doit être désactivée pour l'appelant.
|
||||||
|
* Par exemple, si l'appel provient du plugin Optimize More (pour éviter des getimagesize sur une URL Thumbor).
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function wp_thumbor_should_skip_transform() {
|
||||||
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
|
||||||
|
foreach ($trace as $frame) {
|
||||||
|
if (isset($frame['file']) && stripos($frame['file'], 'optimize-more') !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ajoute un menu de réglages dans l'administration de WordPress.
|
||||||
|
*/
|
||||||
|
function wp_thumbor_admin_menu() {
|
||||||
|
add_options_page(
|
||||||
|
'Réglages WP Thumbor Integration',
|
||||||
|
'WP Thumbor Integration',
|
||||||
|
'manage_options',
|
||||||
|
'wp-thumbor-integration',
|
||||||
|
'wp_thumbor_settings_page'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
add_action('admin_menu', 'wp_thumbor_admin_menu');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affiche la page de réglages du plugin dans l'administration.
|
||||||
|
*/
|
||||||
|
function wp_thumbor_settings_page() {
|
||||||
|
if (!current_user_can('manage_options')) {
|
||||||
|
wp_die(__('Vous n\'avez pas l\'autorisation d\'accéder à cette page.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sauvegarde des réglages lors de la soumission du formulaire.
|
||||||
|
if (isset($_POST['wp_thumbor_nonce']) && wp_verify_nonce($_POST['wp_thumbor_nonce'], 'wp_thumbor_save_settings')) {
|
||||||
|
$options = array();
|
||||||
|
$options['thumbor_base_url'] = isset($_POST['thumbor_base_url']) ? esc_url_raw(trim($_POST['thumbor_base_url'])) : '';
|
||||||
|
$options['thumbor_filters'] = isset($_POST['thumbor_filters']) ? sanitize_text_field(trim($_POST['thumbor_filters'])) : '';
|
||||||
|
$options['thumbor_secret_key'] = isset($_POST['thumbor_secret_key']) ? sanitize_text_field(trim($_POST['thumbor_secret_key'])) : '';
|
||||||
|
update_option('wp_thumbor_options', $options);
|
||||||
|
echo '<div class="updated"><p>Les paramètres ont été mis à jour.</p></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = wp_thumbor_get_options();
|
||||||
|
?>
|
||||||
|
<div class="wrap">
|
||||||
|
<h1>WP Thumbor Integration - Réglages</h1>
|
||||||
|
<form method="post" action="">
|
||||||
|
<?php wp_nonce_field('wp_thumbor_save_settings', 'wp_thumbor_nonce'); ?>
|
||||||
|
<table class="form-table">
|
||||||
|
<tr valign="top">
|
||||||
|
<th scope="row">Thumbor Base URL</th>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="thumbor_base_url" value="<?php echo esc_attr($options['thumbor_base_url']); ?>" class="regular-text" placeholder="http://thumbor.example.com" />
|
||||||
|
<p class="description">Entrez l'URL de base de votre serveur Thumbor (sans barre oblique finale).</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr valign="top">
|
||||||
|
<th scope="row">Filtres Thumbor</th>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="thumbor_filters" value="<?php echo esc_attr($options['thumbor_filters']); ?>" class="regular-text" placeholder="ex: quality(85),contrast(10)" />
|
||||||
|
<p class="description">Entrez la liste des filtres à appliquer, séparés par des virgules, sans le préfixe "filters:" ni le suffixe ":/".</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr valign="top">
|
||||||
|
<th scope="row">Clé secrète Thumbor</th>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="thumbor_secret_key" value="<?php echo esc_attr($options['thumbor_secret_key']); ?>" class="regular-text" placeholder="Votre clé secrète" />
|
||||||
|
<p class="description">Entrez la clé secrète pour signer les URLs Thumbor. Laissez vide pour utiliser l'endpoint "unsafe".</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<?php submit_button(); ?>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extrait les dimensions d'une image à partir de son URL (ex. "image-200x300.jpg").
|
||||||
|
*
|
||||||
|
* @param string $url L'URL de l'image.
|
||||||
|
* @return array|false Tableau avec 'width' et 'height' ou false si aucun pattern n'est trouvé.
|
||||||
|
*/
|
||||||
|
function wp_thumbor_extract_dimensions_from_url($url) {
|
||||||
|
if (preg_match('/-([0-9]+)x([0-9]+)(?=\.(jpg|jpeg|png|gif|webp)$)/i', $url, $matches)) {
|
||||||
|
return array('width' => intval($matches[1]), 'height' => intval($matches[2]));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforme l'URL d'une image en ajoutant l'endpoint Thumbor (signé si clé secrète renseignée),
|
||||||
|
* les options de redimensionnement et les filtres configurés.
|
||||||
|
*
|
||||||
|
* Le format généré est :
|
||||||
|
* {thumbor_base_url}/{endpoint}/[width]x[height]/[filters:...]/{url}
|
||||||
|
*
|
||||||
|
* Si aucune dimension n'est précisée, la partie redimensionnement est omise.
|
||||||
|
*
|
||||||
|
* @param string $url L'URL originale de l'image.
|
||||||
|
* @param int|null $width La largeur souhaitée (provenant éventuellement des attributs HTML).
|
||||||
|
* @param int|null $height La hauteur souhaitée.
|
||||||
|
* @return string L'URL transformée.
|
||||||
|
*/
|
||||||
|
function wp_thumbor_transform_url($url, $width = null, $height = null) {
|
||||||
|
// Ne pas transformer dans l'administration
|
||||||
|
if (is_admin()) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
// Si l'appel provient d'un plugin tiers (ex. Optimize More), on retourne l'URL d'origine
|
||||||
|
if (wp_thumbor_should_skip_transform()) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = wp_thumbor_get_options();
|
||||||
|
$thumbor_base_url = isset($options['thumbor_base_url']) ? rtrim($options['thumbor_base_url'], '/') : '';
|
||||||
|
|
||||||
|
if (empty($thumbor_base_url)) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Évite une double transformation
|
||||||
|
if (strpos($url, $thumbor_base_url) === 0) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si aucune dimension n'est fournie via les attributs, tenter d'extraire depuis le nom du fichier
|
||||||
|
if (empty($width) && empty($height)) {
|
||||||
|
$dimensions = wp_thumbor_extract_dimensions_from_url($url);
|
||||||
|
if ($dimensions) {
|
||||||
|
$width = $dimensions['width'];
|
||||||
|
$height = $dimensions['height'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Préparation de la partie redimensionnement
|
||||||
|
if ($width || $height) {
|
||||||
|
$w = $width ? $width : 0;
|
||||||
|
$h = $height ? $height : 0;
|
||||||
|
$resize = $w . 'x' . $h . '/';
|
||||||
|
} else {
|
||||||
|
$resize = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Préparation de la partie filtres à partir des réglages
|
||||||
|
$thumbor_filters = isset($options['thumbor_filters']) ? trim($options['thumbor_filters']) : '';
|
||||||
|
if (!empty($thumbor_filters)) {
|
||||||
|
// Correction apportée ici : utiliser "/" au lieu de ":/" après les filtres.
|
||||||
|
$filterPart = 'filters:' . $thumbor_filters . '/';
|
||||||
|
} else {
|
||||||
|
$filterPart = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construction de la chaîne d'options à signer
|
||||||
|
$path_to_sign = $resize . $filterPart . $url;
|
||||||
|
|
||||||
|
// Détermine l'endpoint : si une clé secrète est renseignée, on signe, sinon on utilise "unsafe"
|
||||||
|
if (!empty($options['thumbor_secret_key'])) {
|
||||||
|
// Calcul du HMAC-SHA1 en mode binaire
|
||||||
|
$hmac = hash_hmac('sha1', $path_to_sign, $options['thumbor_secret_key'], true);
|
||||||
|
// Encodage en base64 en mode URL-safe (remplacement + -> - et / -> _)
|
||||||
|
$encoded_signature = strtr(base64_encode($hmac), '+/', '-_');
|
||||||
|
// L'endpoint sécurisé est le code signé
|
||||||
|
$endpoint = $encoded_signature;
|
||||||
|
} else {
|
||||||
|
$endpoint = 'unsafe';
|
||||||
|
}
|
||||||
|
|
||||||
|
$transformed_url = $thumbor_base_url . '/' . $endpoint . '/' . $path_to_sign;
|
||||||
|
return $transformed_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filtre l'URL d'une pièce jointe image pour y intégrer Thumbor.
|
||||||
|
*/
|
||||||
|
function wp_thumbor_filter_attachment_url($url, $post_id) {
|
||||||
|
// Si l'appel provient d'un plugin tiers (ex. Optimize More), on retourne l'URL d'origine.
|
||||||
|
if (wp_thumbor_should_skip_transform()) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mime = get_post_mime_type($post_id);
|
||||||
|
if (strpos($mime, 'image/') === 0) {
|
||||||
|
return wp_thumbor_transform_url($url);
|
||||||
|
}
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
//add_filter('wp_get_attachment_url', 'wp_thumbor_filter_attachment_url', 10, 2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parcourt le contenu HTML d'un article et modifie les attributs src, data-src, srcset et data-srcset
|
||||||
|
* des balises <img> en y intégrant les paramètres de redimensionnement (issus des attributs width/height)
|
||||||
|
* et les filtres Thumbor.
|
||||||
|
*/
|
||||||
|
function wp_thumbor_filter_content_images($content) {
|
||||||
|
// Ne pas transformer dans l'administration
|
||||||
|
if (is_admin()) {
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
$dom = new DOMDocument();
|
||||||
|
// Conversion pour éviter les problèmes d'encodage
|
||||||
|
$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
|
||||||
|
$images = $dom->getElementsByTagName('img');
|
||||||
|
foreach ($images as $img) {
|
||||||
|
// Récupération de la largeur et hauteur si présentes
|
||||||
|
$width = $img->getAttribute('width');
|
||||||
|
$height = $img->getAttribute('height');
|
||||||
|
$width = $width ? intval($width) : null;
|
||||||
|
$height = $height ? intval($height) : null;
|
||||||
|
|
||||||
|
// Transformation de l'attribut "src" si c'est une URL absolue
|
||||||
|
if ($img->hasAttribute('src') && preg_match('/^https?:\/\//', $img->getAttribute('src'))) {
|
||||||
|
$new_src = wp_thumbor_transform_url($img->getAttribute('src'), $width, $height);
|
||||||
|
$img->setAttribute('src', $new_src);
|
||||||
|
}
|
||||||
|
// Transformation de "data-src" pour le lazyload
|
||||||
|
if ($img->hasAttribute('data-src') && preg_match('/^https?:\/\//', $img->getAttribute('data-src'))) {
|
||||||
|
$new_data_src = wp_thumbor_transform_url($img->getAttribute('data-src'), $width, $height);
|
||||||
|
$img->setAttribute('data-src', $new_data_src);
|
||||||
|
}
|
||||||
|
// Traitement de l'attribut "srcset"
|
||||||
|
if ($img->hasAttribute('srcset')) {
|
||||||
|
$srcset = $img->getAttribute('srcset');
|
||||||
|
$newSrcset = array();
|
||||||
|
// Chaque élément est séparé par une virgule
|
||||||
|
$srcsetItems = explode(',', $srcset);
|
||||||
|
foreach ($srcsetItems as $item) {
|
||||||
|
$parts = preg_split('/\s+/', trim($item));
|
||||||
|
if (!empty($parts[0]) && preg_match('/^https?:\/\//', $parts[0])) {
|
||||||
|
$newURL = wp_thumbor_transform_url($parts[0]);
|
||||||
|
// Conserver le descripteur (ex: "1707w") si présent
|
||||||
|
$newSrcset[] = isset($parts[1]) ? $newURL . ' ' . $parts[1] : $newURL;
|
||||||
|
} else {
|
||||||
|
$newSrcset[] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$img->setAttribute('srcset', implode(', ', $newSrcset));
|
||||||
|
}
|
||||||
|
// Traitement de l'attribut "data-srcset"
|
||||||
|
if ($img->hasAttribute('data-srcset')) {
|
||||||
|
$srcset = $img->getAttribute('data-srcset');
|
||||||
|
$newSrcset = array();
|
||||||
|
$srcsetItems = explode(',', $srcset);
|
||||||
|
foreach ($srcsetItems as $item) {
|
||||||
|
$parts = preg_split('/\s+/', trim($item));
|
||||||
|
if (!empty($parts[0]) && preg_match('/^https?:\/\//', $parts[0])) {
|
||||||
|
$newURL = wp_thumbor_transform_url($parts[0]);
|
||||||
|
$newSrcset[] = isset($parts[1]) ? $newURL . ' ' . $parts[1] : $newURL;
|
||||||
|
} else {
|
||||||
|
$newSrcset[] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$img->setAttribute('data-srcset', implode(', ', $newSrcset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// On récupère le contenu du <body> pour éviter d'inclure la balise <html> ou <body>
|
||||||
|
$body = $dom->getElementsByTagName('body')->item(0);
|
||||||
|
$new_content = '';
|
||||||
|
foreach ($body->childNodes as $child) {
|
||||||
|
$new_content .= $dom->saveHTML($child);
|
||||||
|
}
|
||||||
|
return $new_content;
|
||||||
|
}
|
||||||
|
add_filter('the_content', 'wp_thumbor_filter_content_images');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialisation du plugin (chargement des traductions, etc.).
|
||||||
|
*/
|
||||||
|
function wp_thumbor_init() {
|
||||||
|
load_plugin_textdomain('wp-thumbor-integration', false, dirname(plugin_basename(__FILE__)) . '/languages/');
|
||||||
|
}
|
||||||
|
add_action('plugins_loaded', 'wp_thumbor_init');
|
||||||
|
|
||||||
Reference in New Issue
Block a user