'',
'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 '
Les paramètres ont été mis à jour.
';
}
$options = wp_thumbor_get_options();
?>
WP Thumbor Integration - Réglages
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
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 pour éviter d'inclure la balise ou
$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');