PluginProbe
Metricool – Social media and site statistics / 2.1.1
Metricool – Social media and site statistics v2.1.1
2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.27 trunk
← All changes | app/Features/AdminNotices/AbstractAdminNotice.php +191 -0 2.0.0 → 2.1.1 View file →
@@ -1,0 +1,191 @@
1 +<?php
2 +
3 +declare(strict_types=1);
4 +
5 +namespace Metricool\Features\AdminNotices;
6 +
7 +use Metricool\Support\Helpers\Storages\EnvironmentConfig;
8 +use Metricool\Traits\HasViews;
9 +
10 +abstract class AbstractAdminNotice
11 +{
12 + use HasViews {
13 + render as protected traitRender;
14 + }
15 +
16 + /**
17 + * The unique id of the Notice should be defined in the child class as a
18 + * constant. This is used to identify the notice in the database and actions.
19 + * @var string
20 + */
21 + public const IDENTIFIER = '';
22 +
23 + /**
24 + * The dismiss value in the REST endpoint's action parameter
25 + * @var string
26 + */
27 + public const DISMISS_NOTICE_ACTION = 'dismiss';
28 +
29 + /**
30 + * The snooze value in the REST endpoint's action parameter
31 + * @var string
32 + */
33 + public const SNOOZE_NOTICE_ACTION = 'snooze';
34 +
35 + protected EnvironmentConfig $env;
36 +
37 + public function __construct(EnvironmentConfig $env)
38 + {
39 + if (!defined('static::IDENTIFIER') || empty(static::IDENTIFIER)) {
40 + throw new \InvalidArgumentException('The IDENTIFIER constant must be defined and not empty in the child class.');
41 + }
42 +
43 + $this->env = $env;
44 + }
45 +
46 + /**
47 + * Notice-specific display conditions, use this to check for things like
48 + * required capabilities, specific admin pages, etc.
49 + */
50 + abstract protected function canDisplay(): bool;
51 +
52 + /**
53 + * Returns the view path for the inner content of the notice
54 + */
55 + abstract protected function getContentView(): string;
56 +
57 + /**
58 + * Returns the variables passed to the content view
59 + */
60 + abstract protected function getContentVariables(): array;
61 +
62 + /**
63 + * Returns whether the notice can be permanently dismissed
64 + */
65 + public function isDismissable(): bool
66 + {
67 + return true;
68 + }
69 +
70 + /**
71 + * Returns whether the notice can be snoozed (remind me later)
72 + */
73 + public function isSnoozable(): bool
74 + {
75 + return false;
76 + }
77 +
78 + /**
79 + * Returns the snooze duration in days
80 + */
81 + public function getSnoozeDays(): int
82 + {
83 + return 1;
84 + }
85 +
86 + /**
87 + * Returns the URL for the call-to-action button, or empty string if none
88 + */
89 + public function getCtaUrl(): string
90 + {
91 + return '';
92 + }
93 +
94 + /**
95 + * Returns the label for the call-to-action button, or empty string if none
96 + */
97 + public function getCtaLabel(): string
98 + {
99 + return '';
100 + }
101 +
102 + /**
103 + * Render the notice
104 + */
105 + public function render(): void
106 + {
107 + $this->traitRender('admin/notices/layout', $this->viewData());
108 + }
109 +
110 + /**
111 + * Get the unique identifier
112 + */
113 + final public function getId(): string
114 + {
115 + return static::IDENTIFIER;
116 + }
117 +
118 + /**
119 + * Returns whether the notice should be displayed
120 + */
121 + final public function shouldDisplay(): bool
122 + {
123 + return $this->canDisplay() && !$this->isDismissed() && !$this->isSnoozed();
124 + }
125 +
126 + /**
127 + * Snooze the notice for the configured number of days
128 + */
129 + final public function snooze(): void
130 + {
131 + $snoozedUntil = time() + ($this->getSnoozeDays() * DAY_IN_SECONDS);
132 + update_option('metricool_notice_' . $this->getId() . '_snoozed_until', $snoozedUntil, false);
133 + }
134 +
135 + /**
136 + * Check if the notice has been permanently dismissed
137 + */
138 + final public function isDismissed(): bool
139 + {
140 + return (bool) get_option('metricool_notice_' . $this->getId() . '_dismissed', false);
141 + }
142 +
143 + /**
144 + * Check if the notice is currently snoozed
145 + */
146 + final public function isSnoozed(): bool
147 + {
148 + $snoozedUntil = (int) get_option('metricool_notice_' . $this->getId() . '_snoozed_until', 0);
149 +
150 + if ($snoozedUntil === 0) {
151 + return false;
152 + }
153 +
154 + return time() < $snoozedUntil;
155 + }
156 +
157 + /**
158 + * Permanently dismiss the notice
159 + */
160 + final public function dismiss(): void
161 + {
162 + update_option('metricool_notice_' . $this->getId() . '_dismissed', true, false);
163 + }
164 +
165 + /**
166 + * Get the data passed to the notice layout view
167 + */
168 + protected function viewData(): array
169 + {
170 + $restUrl = rest_url(
171 + $this->env->getString('http.namespace')
172 + . '/'
173 + . $this->env->getString('http.version')
174 + . '/admin-notices/'
175 + . $this->getId()
176 + );
177 +
178 + return [
179 + 'noticeId' => $this->getId(),
180 + 'logoUrl' => $this->env->getUrl('plugin.assets_url') . 'img/mc-logo.svg',
181 + 'restUrl' => $restUrl,
182 + 'isDismissable' => $this->isDismissable(),
183 + 'isSnoozable' => $this->isSnoozable(),
184 + 'ctaUrl' => $this->getCtaUrl(),
185 + 'ctaLabel' => $this->getCtaLabel(),
186 + 'nonce' => wp_create_nonce('metricool_nonce'),
187 + 'wpNonce' => wp_create_nonce('wp_rest'),
188 + 'content' => $this->view($this->getContentView(), $this->getContentVariables()),
189 + ];
190 + }
191 +}