Adjust watermark permissions and transparency
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-19 13:45:43 +01:00
parent fbff2afa3e
commit d4ab9a3a20
15 changed files with 325 additions and 54 deletions

View File

@@ -13,7 +13,8 @@ trait PresentsPackages
$packageArray = $package->toArray();
$features = $packageArray['features'] ?? [];
$features = $this->normaliseFeatures($features);
$watermarkPolicy = $package->watermark_allowed === false ? 'none' : 'basic';
$watermarkRemovalAllowed = in_array('no_watermark', $features, true) || in_array('watermark_removal', $features, true);
$watermarkPolicy = $watermarkRemovalAllowed ? 'none' : 'basic';
$locale = app()->getLocale();
$name = $this->resolveTranslation($package->name_translations ?? null, $package->name ?? '', $locale);

View File

@@ -178,10 +178,13 @@ class ImageHelper
$y = max(0, min($srcH - $targetH, $y + $offsetY));
$opacity = max(0.0, min(1.0, (float) ($config['opacity'] ?? 0.25)));
$mergeOpacity = (int) round($opacity * 100); // imagecopymerge uses 0-100
if ($opacity < 1.0) {
self::applyOpacity($resized, $opacity);
}
imagealphablending($src, true);
imagecopymerge($src, $resized, $x, $y, 0, 0, $targetW, $targetH, $mergeOpacity);
imagecopy($src, $resized, $x, $y, 0, 0, $targetW, $targetH);
imagedestroy($resized);
// Overwrite original (respect mime: always JPEG for compatibility)
@@ -210,4 +213,34 @@ class ImageHelper
return $applied ? $destPath : null;
}
/**
* @param \GdImage|resource $image
*/
private static function applyOpacity($image, float $opacity): void
{
$width = imagesx($image);
$height = imagesy($image);
if ($width <= 0 || $height <= 0) {
return;
}
imagealphablending($image, false);
imagesavealpha($image, true);
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {
$rgba = imagecolorat($image, $x, $y);
$alpha = ($rgba >> 24) & 0x7F;
$red = ($rgba >> 16) & 0xFF;
$green = ($rgba >> 8) & 0xFF;
$blue = $rgba & 0xFF;
$adjustedAlpha = (int) round(127 - (127 - $alpha) * $opacity);
$color = imagecolorallocatealpha($image, $red, $green, $blue, max(0, min(127, $adjustedAlpha)));
imagesetpixel($image, $x, $y, $color);
}
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Support;
use App\Models\Event;
use App\Models\Package;
use Illuminate\Support\Arr;
class WatermarkConfigResolver
@@ -29,7 +30,21 @@ class WatermarkConfigResolver
{
$event->loadMissing('eventPackage.package');
return $event->eventPackage?->package?->watermark_allowed === false ? 'none' : 'basic';
return self::determineRemovalAllowed($event) ? 'none' : 'basic';
}
public static function determineRemovalAllowed(Event $event): bool
{
$event->loadMissing('eventPackage.package', 'eventPackages.package');
$package = $event->eventPackage?->package;
if (! $package && $event->relationLoaded('eventPackages')) {
$package = $event->eventPackages->first()?->package;
}
return self::packageHasFeature($package, 'no_watermark')
|| self::packageHasFeature($package, 'watermark_removal');
}
/**
@@ -39,13 +54,6 @@ class WatermarkConfigResolver
{
$policy = self::determinePolicy($event);
if ($policy === 'none') {
return [
'type' => 'none',
'policy' => $policy,
];
}
$baseSetting = null;
if (class_exists(\App\Models\WatermarkSetting::class) && \Illuminate\Support\Facades\Schema::hasTable('watermark_settings')) {
@@ -65,8 +73,15 @@ class WatermarkConfigResolver
'offset_y' => $baseSetting?->offset_y ?? config('watermark.base.offset_y', 0),
];
$event->loadMissing('eventPackage.package', 'tenant');
$event->loadMissing('eventPackage.package', 'eventPackages.package', 'tenant');
$package = $event->eventPackage?->package;
if (! $package && $event->relationLoaded('eventPackages')) {
$package = $event->eventPackages->first()?->package;
}
$brandingAllowed = self::determineBrandingAllowed($event);
$watermarkAllowed = $package?->watermark_allowed !== false;
$removalAllowed = self::determineRemovalAllowed($event);
$eventWatermark = Arr::get($event->settings, 'watermark', []);
$tenantWatermark = Arr::get($event->tenant?->settings, 'watermark', []);
$serveOriginals = (bool) Arr::get($event->settings, 'watermark_serve_originals', false);
@@ -75,7 +90,11 @@ class WatermarkConfigResolver
? ($eventWatermark['mode'] ?? $tenantWatermark['mode'] ?? 'base')
: 'base';
if ($mode === 'off' && $policy === 'basic') {
if ($mode === 'custom' && (! $brandingAllowed || ! $watermarkAllowed)) {
$mode = 'base';
}
if ($mode === 'off' && ! $removalAllowed) {
$mode = 'base';
}
@@ -111,4 +130,30 @@ class WatermarkConfigResolver
'serve_originals' => $serveOriginals,
];
}
private static function packageHasFeature(?Package $package, string $feature): bool
{
if (! $package) {
return false;
}
$features = $package->features ?? [];
if (is_string($features)) {
$decoded = json_decode($features, true);
if (json_last_error() === JSON_ERROR_NONE) {
$features = $decoded;
}
}
if (! is_array($features)) {
return false;
}
if (array_is_list($features)) {
return in_array($feature, $features, true);
}
return isset($features[$feature]) && (bool) $features[$feature];
}
}