JezK
Edit File: AbstractNotice.php
<?php namespace GeminiLabs\SiteReviews\Notices; use GeminiLabs\SiteReviews\Contracts\PluginContract; use GeminiLabs\SiteReviews\Helper; use GeminiLabs\SiteReviews\Helpers\Arr; use GeminiLabs\SiteReviews\Helpers\Str; use GeminiLabs\SiteReviews\Modules\Html\Builder; use GeminiLabs\SiteReviews\Modules\Sanitizer; abstract class AbstractNotice { public const USER_META_KEY = '_glsr_dismissed_notices'; protected string $key; protected int $priority = 10; protected string $type = ''; // add a supported type here to override the default type public function __construct() { $this->normalizeType(); $this->key = Str::dashCase( Str::removeSuffix((new \ReflectionClass($this))->getShortName(), 'Notice') ); if (!$this->canLoad()) { return; } glsr()->append('notices', [ 'class' => get_class($this), 'monitored' => $this->isMonitored(), 'rendered' => false, 'type' => str_starts_with('notice', $this->type) ? 'notice' : $this->type, ], $this->key); add_action('admin_notices', [$this, 'render'], $this->priority); } public function app(): PluginContract { return glsr(); } public function dismiss(array $args = []): void { if (!$this->isMonitored()) { return; // only track notices that are monitored } $userId = get_current_user_id(); $dismissed = Arr::consolidate(get_user_meta($userId, static::USER_META_KEY, true)); $dismissed[$this->key] = wp_parse_args($args, [ 'timestamp' => current_time('timestamp'), 'version' => $this->deferVersion(), ]); update_user_meta($userId, static::USER_META_KEY, $dismissed); } public function path(): string { return "partials/notices/{$this->key}"; } public function render(): void { if (!$this->canRender()) { return; } $notice = $this->app()->build($this->path(), $this->data()); if ('popup' === $this->type) { $notice = glsr(Builder::class)->div($notice); } echo glsr(Builder::class)->div([ 'class' => $this->classAttr(), 'data-notice' => get_class($this), 'text' => $notice, ]); } protected function canLoad(): bool { if (!$this->hasPermission()) { return false; } if (!$this->isNoticeScreen()) { return false; } if ($this->isDeferred()) { return false; } return true; } protected function canRender(): bool { $notices = glsr()->retrieveAs('array', 'notices'); if ($this->isStandalone()) { $filtered = array_filter($notices, fn ($notice) => 'notice' === ($notice['type'] ?? '')); return 1 === count($filtered); } foreach (['banner', 'popup'] as $type) { if ($type !== $this->type) { continue; } $filtered = array_filter($notices, function ($notice) { if ($this->type !== ($notice['type'] ?? '')) { return false; } return $notice['rendered'] ?? false; }); if (!empty($filtered)) { return false; } $notices[$this->key]['rendered'] = true; glsr()->store('notices', $notices); } return true; } protected function classAttr(): string { $classAttr = [ 'glsr-notice', ]; if ($this->isDismissible()) { $classAttr[] = 'is-dismissible'; } if (in_array($this->type, ['banner', 'popup'])) { $classAttr[] = "glsr-notice-{$this->type}"; } else { $classAttr[] = "notice {$this->type}"; } $classAttr = implode(' ', $classAttr); return glsr(Sanitizer::class)->sanitizeAttrClass($classAttr); } protected function data(): array { return []; } protected function deferInterval(): int { return 0; } protected function deferVersion(): string { return ''; } protected function hasPermission(): bool { return glsr()->hasPermission('notices', $this->key); } protected function isDeferred(): bool { if (!$this->isMonitored()) { return false; } $dismissed = Arr::consolidate(get_user_meta(get_current_user_id(), static::USER_META_KEY, true)); if (empty($dismissed[$this->key])) { return false; } if ($version = glsr(Sanitizer::class)->sanitizeVersion($dismissed[$this->key]['version'] ?? '')) { if (Helper::isGreaterThan($this->deferVersion(), $version)) { return false; } } if ($timestamp = glsr(Sanitizer::class)->sanitizeTimestamp($dismissed[$this->key]['timestamp'] ?? '')) { $deferInterval = $this->deferInterval(); $deferredTimestamp = (int) $timestamp + $deferInterval; if (!empty($deferInterval) && current_time('timestamp') > $deferredTimestamp) { return false; } } return true; } protected function isDismissible(): bool { return true; } protected function isMonitored(): bool { return false; } protected function isNoticeScreen(): bool { $screen = glsr_current_screen(); if (!str_starts_with($screen->post_type, glsr()->post_type)) { return false; } if ('popup' !== $this->type) { return true; } if ('post' === $screen->base) { return false; } if (str_ends_with($screen->base, '-premium')) { return false; } if (!glsr()->filterBool('flyoutmenu/enabled', true)) { return false; } return true; } protected function isStandalone(): bool { return false; } protected function normalizeType(): void { $types = [ 'banner', 'notice', 'notice-error', 'notice-info', 'notice-success', 'notice-warning', 'popup', ]; if (!in_array($this->type, $types)) { $this->type = 'notice'; } } }