Инструкция: Для того чтобы сделать на сайте WordPress динамический watermark для Woocommerce
Dynamic Watermark WordPress Woocommerce
1. В корне сайта создаем пустую папку wm-cache (права 777)
2. В корень сайта добавляем сам файл watermark с названием logo.png (Размер: 1000x1000 px (или больше), PNG с прозрачным фоном, 644)
3. В корне сайта создаем файл watermark.php
<?php
// watermark.php — Динамическое наложение водяного знака
// НАСТРОЙКИ
$watermark_file = __DIR__ . '/logo.png';
$cache_folder = __DIR__ . '/wm-cache';
$opacity = 100; // Ставим 100, так как используем imagecopy (прозрачность берется из файла logo.png)
$margin = 20;
$position = 'center'; // По центру
if (!isset($_GET['src'])) {
http_response_code(400);
die('No image provided');
}
$image_path = urldecode($_GET['src']);
$uploads_dir = 'wp-content/uploads';
if (strpos($image_path, $uploads_dir) === false) {
http_response_code(403);
die('Access denied');
}
$image_path = preg_replace('#^https?://[^/]+#', '', $image_path);
$abs_path = $_SERVER['DOCUMENT_ROOT'] . '/' . $image_path;
if (!file_exists($abs_path)) {
http_response_code(404);
die('Image not found');
}
if (!is_dir($cache_folder)) mkdir($cache_folder, 0755, true);
// Добавил v3, чтобы сбросить старый кэш с черными квадратами
$cache_name = md5($image_path . $opacity . $position . 'v3') . '.jpg';
$cache_path = $cache_folder . '/' . $cache_name;
if (file_exists($cache_path)) {
header('Content-Type: image/jpeg');
header('Cache-Control: public, max-age=31536000');
readfile($cache_path);
exit;
}
if (!extension_loaded('gd')) die('GD Library not installed');
$info = getimagesize($abs_path);
$mime = $info['mime'];
switch ($mime) {
case 'image/jpeg': $source = imagecreatefromjpeg($abs_path); break;
case 'image/png': $source = imagecreatefrompng($abs_path); break;
case 'image/gif': $source = imagecreatefromgif($abs_path); break;
case 'image/webp': $source = imagecreatefromwebp($abs_path); break;
default: die('Unsupported format');
}
// === ВАЖНО: Включаем поддержку альфа-канала ===
imagealphablending($source, true);
imagesavealpha($source, true);
$wm = imagecreatefrompng($watermark_file);
// Сохраняем прозрачность логотипа
imagealphablending($wm, true);
imagesavealpha($wm, true);
$wm_w = imagesx($wm);
$wm_h = imagesy($wm);
$img_w = imagesx($source);
$img_h = imagesy($source);
// Масштабируем, если логотип больше 50% картинки
if ($wm_w > $img_w * 0.5) {
$ratio = ($img_w * 0.5) / $wm_w;
$new_w = $wm_w * $ratio;
$new_h = $wm_h * $ratio;
$wm_resized = imagecreatetruecolor($new_w, $new_h);
imagealphablending($wm_resized, false);
imagesavealpha($wm_resized, true);
$transparent = imagecolorallocatealpha($wm_resized, 0, 0, 0, 127);
imagefill($wm_resized, 0, 0, $transparent);
imagecopyresampled($wm_resized, $wm, 0, 0, 0, 0, $new_w, $new_h, $wm_w, $wm_h);
$wm = $wm_resized;
$wm_w = $new_w;
$wm_h = $new_h;
}
// Координаты (Центр)
$x = ($img_w - $wm_w) / 2;
$y = ($img_h - $wm_h) / 2;
// === НАКЛАДКА (ИСПОЛЬЗУЕМ imagecopy для идеальной прозрачности) ===
// imagecopymerge дает черный фон на прозрачных PNG. imagecopy - нет.
imagecopy($source, $wm, $x, $y, 0, 0, $wm_w, $wm_h);
// ===========================================================
// Сохраняем в кэш
imagejpeg($source, $cache_path, 85);
header('Content-Type: image/jpeg');
header('Cache-Control: public, max-age=31536000');
imagejpeg($source, null, 85);
imagedestroy($source);
imagedestroy($wm);
?>
4. В файл functions.php добавляем код:
add_filter('wp_get_attachment_image_src', 'wm_woo_by_id', 999, 4);
function wm_woo_by_id($image, $attachment_id, $size, $icon) {
if (is_admin() || empty($image) || $icon) return $image;
$url = $image[0];
if (!preg_match('/\.(jpe?g|png|webp)/i', $url)) return $image;
if (strpos($url, '/wp-content/uploads/') === false) return $image;
// Получаем все ID товаров
$product_ids = get_posts([
'post_type' => 'product',
'fields' => 'ids',
'numberposts' => -1,
'post_status' => 'publish'
]);
// Проверяем, используется ли это изображение в товаре
$is_used = false;
foreach ($product_ids as $pid) {
if (get_post_thumbnail_id($pid) == $attachment_id) {
$is_used = true;
break;
}
$gallery = get_post_meta($pid, '_product_image_gallery', true);
if ($gallery && in_array($attachment_id, array_map('intval', explode(',', $gallery)))) {
$is_used = true;
break;
}
}
if (!$is_used) return $image;
// Формируем маскированный URL
$relative = str_replace(home_url(), '', $url);
$relative = str_replace('/wp-content/uploads/', '', $relative);
$image[0] = home_url('/wm-uploads/' . $relative);
return $image;
}
5. В файл .htaccess
Найди в .htaccess строку # BEGIN WordPress и вставь правило маскировки сразу перед ней.
Или вообще в самом начале после RewriteEngine On
# === МАСКИРОВКА ВОДЯНОГО ЗНАКА ===
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^wm-uploads/(.+)$ /watermark.php?src=/wp-content/uploads/$1 [L,QSA]
# =================================
Совет: Для того чтобы сделать отклик страниц быстрее и снизить нагрузку - можете сверстать простенький скрипт (прогрев кеша)
он пройдет по всем товарам и добавит в папку кеша версии с вашим лого
Вариант 2: Можно (лучше) поставить плагин WP Fastest Cache и включить "Предварительная загрузка" - "Автоматическое создание кэша для всего сайта"