PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.3
Booktics – Appointment Booking Calendar for Service Businesses v1.0.3
1.0.29 1.0.28 1.0.27 1.0.26 1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 All 31 releases
booktics / trunk / vendor / arraytics / plugin-notice-sdk / src / Banner.php

Banner.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.3, at trunk/vendor/arraytics/plugin-notice-sdk/src/Banner.php

359 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Arraytics\PluginNotice;
4
5 /**
6 * Class Banner
7 *
8 * Displays remote banners and notices fetched from an external API.
9 *
10 * @package Arraytics\PluginNotice
11 */
12 class Banner
13 {
14 /**
15 * Plugin version (set from main plugin).
16 *
17 * @var string
18 */
19 protected $version = '1.0.0'; // default fallback
20
21 /**
22 * Singleton instance.
23 *
24 * @var static
25 */
26 private static $instance;
27
28 /**
29 * API data response.
30 *
31 * @var array|object
32 */
33 protected $data;
34
35 /**
36 * Last API check timestamp.
37 *
38 * @var int
39 */
40 protected $last_check = 0;
41
42 /**
43 * Time interval between API checks (default: 6 hours).
44 *
45 * @var int
46 */
47 protected $check_interval = 3600 * 6;
48
49 /**
50 * Allowed screen IDs for banners.
51 *
52 * @var array
53 */
54 protected $plugin_screens = [];
55
56 /**
57 * Text domain (used for caching keys).
58 *
59 * @var string
60 */
61 protected $text_domain;
62
63 /**
64 * Comma-separated filter string (e.g., active plugin slugs).
65 *
66 * @var string|null
67 */
68 protected $filter_string = null;
69
70 /**
71 * Parsed filter values as an array.
72 *
73 * @var array
74 */
75 protected $filter_array = [];
76
77 /**
78 * Remote API base URL.
79 *
80 * @var string
81 */
82 protected $api_url;
83
84 /**
85 * Set the plugin version dynamically.
86 *
87 * @param string $version
88 * @return $this
89 */
90 public function set_version($version)
91 {
92 $this->version = $version;
93 return $this;
94 }
95
96 /**
97 * Get plugin version.
98 *
99 * @return string
100 */
101 public function get_version()
102 {
103 return $this->version;
104 }
105
106 /**
107 * Get file path of this script.
108 *
109 * @return string
110 */
111 public function get_script_location()
112 {
113 return __FILE__;
114 }
115
116 /**
117 * Entry point to start the banner system.
118 *
119 * @return void
120 */
121 public function call()
122 {
123 add_action('admin_head', [$this, 'display_content']);
124 }
125
126 /**
127 * Render banners if applicable.
128 *
129 * @return void
130 */
131 public function display_content()
132 {
133 $this->get_data();
134 if (!empty($this->data->error) || empty($this->data)) {
135 return;
136 }
137
138 foreach ($this->data as $content) {
139 if (!empty($this->filter_array) && $this->in_blacklist($content, $this->filter_array)) {
140 continue;
141 }
142
143 if ($content->start <= time() && time() <= $content->end) {
144 $screen = get_current_screen();
145
146 if ($this->is_correct_screen_to_show($content->screen, $screen->id)) {
147 $inline_css = !empty($content->data->style_css)
148 ? ' style="' . $content->data->style_css . '"'
149 : '';
150
151 $banner_id = !empty($content->data->unique_key)
152 ? $content->data->unique_key
153 : $content->id;
154
155 $instance = Notice::instance($this->text_domain, $banner_id)
156 ->set_dismiss('global', 3600 * 24 * 15);
157
158 if ($content->type === 'banner') {
159 $this->render_banner($content, $instance, $inline_css);
160 }
161
162 if ($content->type === 'notice') {
163 $this->render_notice($content, $instance, $inline_css);
164 }
165 }
166 }
167 }
168 }
169
170 /**
171 * Render notice type content.
172 *
173 * @param object $content
174 * @param object $instance
175 * @param string $inline_css
176 * @return void
177 */
178 private function render_notice($content, $instance, $inline_css)
179 {
180 $instance->set_message($content->data->notice_body);
181
182 if (!empty($content->data->notice_image)) {
183 $instance->set_logo($content->data->notice_image);
184 }
185
186 if (!empty($content->data->button_text)) {
187 $instance->set_button([
188 'default_class' => 'button',
189 'class' => 'button-secondary button-small',
190 'text' => $content->data->button_text,
191 'url' => $content->data->button_link,
192 ]);
193 }
194
195 $instance->call();
196 }
197
198 /**
199 * Render banner type content.
200 *
201 * @param object $content
202 * @param object $instance
203 * @param string $inline_css
204 * @return void
205 */
206 private function render_banner($content, $instance, $inline_css)
207 {
208 $html = sprintf(
209 '<a target="_blank"%s class="plugin-notice-href" href="%s"><img style="display: block;margin: 0 auto;" src="%s" /></a>',
210 $inline_css,
211 esc_url($content->data->banner_link),
212 esc_url($content->data->banner_image)
213 );
214
215 $instance->set_gutter(false)->set_html($html)->call();
216 }
217
218 /**
219 * Get data from cache or fetch from remote if outdated.
220 *
221 * @return void
222 */
223 private function get_data()
224 {
225 $this->data = get_option($this->text_domain . '__banner_data') ?: [];
226 $this->last_check = get_option($this->text_domain . '__banner_last_check') ?: 0;
227
228 if (($this->last_check + $this->check_interval) < time()) {
229 $response = wp_remote_get(
230 $this->api_url . '/cache/' . $this->text_domain . '.json?nocache=' . time(),
231 ['timeout' => 10, 'httpversion' => '1.1']
232 );
233
234 if (!is_wp_error($response) && !empty($response['body'])) {
235 $decoded = json_decode($response['body']);
236 if (!empty($decoded)) {
237 $this->data = $decoded;
238 update_option($this->text_domain . '__banner_data', $this->data);
239 update_option($this->text_domain . '__banner_last_check', time());
240 }
241 }
242 }
243 }
244
245 /**
246 * Check if content should not be shown due to blacklist.
247 *
248 * @param object $conf
249 * @param array $list
250 * @return bool
251 */
252 private function in_blacklist($conf, $list)
253 {
254 $match = isset($conf->data->blacklist) ? $conf->data->blacklist : '';
255 if (empty($match)) {
256 return false;
257 }
258
259 $match_arr = array_map('trim', explode(',', $match));
260 return !empty(array_intersect($list, $match_arr));
261 }
262
263 /**
264 * Determine if the screen is valid to show content.
265 *
266 * @param string $expected_screen
267 * @param string $current_screen_id
268 * @return bool
269 */
270 public function is_correct_screen_to_show($expected_screen, $current_screen_id)
271 {
272 if (in_array($expected_screen, ['all_page', $current_screen_id], true)) {
273 return true;
274 }
275
276 if ($expected_screen === 'plugin_page') {
277 return in_array($current_screen_id, $this->plugin_screens, true);
278 }
279
280 return false;
281 }
282
283 /**
284 * Enable test mode (set check interval to 1 sec).
285 *
286 * @param bool $is_test
287 * @return $this
288 */
289 public function is_test($is_test = false)
290 {
291 if ($is_test) {
292 $this->check_interval = 1;
293 }
294
295 return $this;
296 }
297
298 /**
299 * Set the text domain (used for option key).
300 *
301 * @param string $text_domain
302 * @return $this
303 */
304 public function set_text_domain($text_domain)
305 {
306 $this->text_domain = $text_domain;
307 return $this;
308 }
309
310 /**
311 * Set the filter string and convert it to array.
312 *
313 * @param string $filter_string
314 * @return $this
315 */
316 public function set_filter($filter_string)
317 {
318 $this->filter_string = $filter_string;
319 $this->filter_array = array_map('trim', explode(',', $filter_string));
320 return $this;
321 }
322
323 /**
324 * Set the API URL to fetch banners from.
325 *
326 * @param string $url
327 * @return $this
328 */
329 public function set_api_url($url)
330 {
331 $this->api_url = $url;
332 return $this;
333 }
334
335 /**
336 * Set allowed plugin screen(s) for showing the banner.
337 *
338 * @param string|array $screen
339 * @return $this
340 */
341 public function set_plugin_screens($screen)
342 {
343 $this->plugin_screens = (array) $screen;
344 return $this;
345 }
346
347 /**
348 * Get singleton instance and set text domain.
349 *
350 * @param string $text_domain
351 * @return static
352 */
353 public static function instance($text_domain = '')
354 {
355 self::$instance = new static();
356 return self::$instance->set_text_domain($text_domain);
357 }
358 }
359