PluginProbe
Atomic Edge Security – Firewall, Malware Scan and Login Security / 2.2.2
Atomic Edge Security – Firewall, Malware Scan and Login Security v2.2.2
trunk 2.0.0 2.1.0 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 All 29 releases
atomic-edge-security / admin / views / cdn.php

cdn.php in Atomic Edge Security – Firewall, Malware Scan and Login Security 2.2.2, at admin/views/cdn.php

449 lines 16.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CDN Page View
4 *
5 * This page allows users to configure CDN settings for their site.
6 * Uses tabbed interface: General, Minification, Advanced.
7 *
8 * User scenarios:
9 * 1. New user not connected to AtomicEdge - show connection prompt
10 * 2. Connected user without CDN enabled - show how to enable CDN
11 * 3. Connected user with CDN enabled - show tabbed settings
12 * 4. Local dev environment - show dev mode with simulated features
13 *
14 * @package AtomicEdge
15 * @since 2.0.0
16 */
17
18 // Prevent direct access.
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22
23 // Check for dev mode (local environments).
24 $atomicedge_dev_mode = AtomicEdge_Dev_Mode::is_enabled();
25
26 // Get connection status and CDN settings - use effective data for dev mode.
27 $atomicedge_is_connected = $atomicedge_dev_mode ? true : $this->api->is_connected();
28 $atomicedge_site_data = AtomicEdge_Dev_Mode::get_effective_site_data();
29
30 // CDN settings from site data (populated when site connects or refreshes).
31 $atomicedge_cdn_prefix = $atomicedge_site_data['cdn_prefix'] ?? '';
32 $atomicedge_cdn_url = $atomicedge_site_data['cdn_url'] ?? '';
33
34 // Use actual is_cdn_enabled() - checks local switch + CDN URL available.
35 // No dashboard gating - if user has a CDN URL (from constant or dashboard), show settings.
36 $atomicedge_cdn_enabled = AtomicEdge_CDN::is_cdn_enabled();
37 $atomicedge_show_cdn_settings = $atomicedge_cdn_enabled || ! empty( AtomicEdge_CDN::get_cdn_hostname() );
38
39 // Last purge time.
40 $atomicedge_cdn_last_purge = get_option( 'atomicedge_cdn_last_purge', '' );
41
42 // Tab navigation.
43 $current_tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'general';
44 $valid_tabs = array( 'general', 'minification', 'advanced' );
45 if ( ! in_array( $current_tab, $valid_tabs, true ) ) {
46 $current_tab = 'general';
47 }
48
49 // Tab definitions.
50 $tabs = array(
51 'general' => array(
52 'label' => __( 'General', 'atomic-edge-security' ),
53 'icon' => 'dashicons-admin-generic',
54 ),
55 'minification' => array(
56 'label' => __( 'Minification', 'atomic-edge-security' ),
57 'icon' => 'dashicons-editor-code',
58 ),
59 'advanced' => array(
60 'label' => __( 'Advanced', 'atomic-edge-security' ),
61 'icon' => 'dashicons-admin-tools',
62 ),
63 );
64 ?>
65 <div class="wrap atomicedge-wrap">
66 <h1><img src="<?php echo esc_url( ATOMICEDGE_PLUGIN_URL . 'admin/images/logo.svg' ); ?>" alt="<?php esc_attr_e( 'Atomic Edge', 'atomic-edge-security' ); ?>" class="atomicedge-logo" /></h1>
67
68 <div class="atomicedge-cdn">
69 <h2>
70 <span class="dashicons dashicons-cloud" style="font-size: 24px; width: 24px; height: 24px; margin-right: 8px; vertical-align: middle;"></span>
71 <?php esc_html_e( 'CDN Settings', 'atomic-edge-security' ); ?>
72 </h2>
73 <p class="atomicedge-page-description">
74 <?php esc_html_e( 'Content Delivery Network (CDN) caches your static assets on global edge servers for faster page loads.', 'atomic-edge-security' ); ?>
75 </p>
76
77 <?php
78 // Show dev mode notice.
79 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is escaped in the method.
80 echo AtomicEdge_Dev_Mode::get_admin_notice();
81 ?>
82
83 <?php if ( ! $atomicedge_is_connected ) : ?>
84 <!-- Not Connected State -->
85 <div class="atomicedge-card">
86 <div class="atomicedge-notice atomicedge-notice-warning">
87 <span class="dashicons dashicons-warning"></span>
88 <div>
89 <p><strong><?php esc_html_e( 'Not Connected to Atomic Edge', 'atomic-edge-security' ); ?></strong></p>
90 <p><?php esc_html_e( 'Connect your site to Atomic Edge to access CDN features.', 'atomic-edge-security' ); ?></p>
91 <p>
92 <a href="<?php echo esc_url( admin_url( 'admin.php?page=atomicedge-settings' ) ); ?>" class="button button-primary">
93 <?php esc_html_e( 'Go to Settings', 'atomic-edge-security' ); ?>
94 </a>
95 </p>
96 </div>
97 </div>
98 </div>
99
100 <?php elseif ( ! $atomicedge_show_cdn_settings ) : ?>
101 <!-- Connected but CDN Not Enabled on Dashboard -->
102 <div class="atomicedge-card">
103 <h3><?php esc_html_e( 'CDN Status', 'atomic-edge-security' ); ?></h3>
104 <div class="atomicedge-cdn-status-display">
105 <span class="atomicedge-status-badge atomicedge-status-inactive">
106 <span class="atomicedge-status-indicator"></span>
107 <span><?php esc_html_e( 'CDN Not Enabled', 'atomic-edge-security' ); ?></span>
108 </span>
109 </div>
110 <div class="atomicedge-notice atomicedge-notice-info" style="margin-top: 15px;">
111 <span class="dashicons dashicons-info"></span>
112 <div>
113 <p><strong><?php esc_html_e( 'Enable CDN in Your Dashboard', 'atomic-edge-security' ); ?></strong></p>
114 <p><?php esc_html_e( 'CDN is not currently enabled for this site. You can enable it from your Atomic Edge dashboard.', 'atomic-edge-security' ); ?></p>
115 <p style="margin-top: 10px;">
116 <a href="https://dashboard.atomicedge.io" target="_blank" rel="noopener noreferrer" class="button button-primary">
117 <?php esc_html_e( 'Open Dashboard', 'atomic-edge-security' ); ?>
118 <span class="dashicons dashicons-external" style="margin-top: 3px;"></span>
119 </a>
120 <button type="button" id="atomicedge-cdn-refresh" class="button" style="margin-left: 10px;">
121 <span class="dashicons dashicons-update" style="margin-top: 3px;"></span>
122 <?php esc_html_e( 'Refresh Status', 'atomic-edge-security' ); ?>
123 </button>
124 <span id="atomicedge-cdn-refresh-status" class="atomicedge-inline-status"></span>
125 </p>
126 </div>
127 </div>
128 </div>
129
130 <!-- Shift8 CDN Migration Notice -->
131 <div class="atomicedge-card">
132 <h3><?php esc_html_e( 'Migrating from Shift8 CDN?', 'atomic-edge-security' ); ?></h3>
133 <p><?php esc_html_e( 'If you were using the Shift8 CDN plugin, your CDN service will continue to work through Atomic Edge.', 'atomic-edge-security' ); ?></p>
134 <ol>
135 <li><?php esc_html_e( 'Log in to your Atomic Edge dashboard', 'atomic-edge-security' ); ?></li>
136 <li><?php esc_html_e( 'Enable CDN for your site in the site settings', 'atomic-edge-security' ); ?></li>
137 <li><?php esc_html_e( 'Return here and click "Refresh Status"', 'atomic-edge-security' ); ?></li>
138 </ol>
139 </div>
140
141 <?php else : ?>
142 <!-- CDN Enabled - Show Tabbed Settings -->
143
144 <!-- CDN Status Header Card -->
145 <div class="atomicedge-card" style="margin-bottom: 20px;">
146 <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
147 <div style="display: flex; align-items: center; gap: 15px;">
148 <span class="atomicedge-status-badge atomicedge-status-active" style="font-size: 14px; padding: 8px 12px;">
149 <span class="atomicedge-status-indicator"></span>
150 <span><?php esc_html_e( 'CDN Active', 'atomic-edge-security' ); ?></span>
151 </span>
152 <?php if ( ! empty( $atomicedge_cdn_url ) ) : ?>
153 <code style="font-size: 13px;"><?php echo esc_html( $atomicedge_cdn_url ); ?></code>
154 <?php endif; ?>
155 </div>
156 <div style="display: flex; gap: 10px; align-items: center;">
157 <button type="button" id="atomicedge-cdn-refresh" class="button">
158 <span class="dashicons dashicons-update" style="margin-top: 3px;"></span>
159 <?php esc_html_e( 'Refresh', 'atomic-edge-security' ); ?>
160 </button>
161 <button type="button" id="atomicedge-purge-cdn" class="button button-primary">
162 <span class="dashicons dashicons-trash" style="margin-top: 3px;"></span>
163 <?php esc_html_e( 'Purge Cache', 'atomic-edge-security' ); ?>
164 </button>
165 <span id="atomicedge-cdn-refresh-status" class="atomicedge-inline-status"></span>
166 <span id="atomicedge-purge-status" class="atomicedge-inline-status"></span>
167 </div>
168 </div>
169 <?php if ( ! empty( $atomicedge_cdn_last_purge ) ) : ?>
170 <p style="margin: 10px 0 0; font-size: 12px; color: #646970;">
171 <?php esc_html_e( 'Last cache purge:', 'atomic-edge-security' ); ?> <?php echo esc_html( $atomicedge_cdn_last_purge ); ?>
172 </p>
173 <?php endif; ?>
174 </div>
175
176 <!-- Tab Navigation -->
177 <nav class="nav-tab-wrapper wp-clearfix" style="margin-bottom: 0;">
178 <?php foreach ( $tabs as $tab_id => $tab ) : ?>
179 <a href="<?php echo esc_url( add_query_arg( 'tab', $tab_id, admin_url( 'admin.php?page=atomicedge-cdn' ) ) ); ?>"
180 class="nav-tab <?php echo $current_tab === $tab_id ? 'nav-tab-active' : ''; ?>">
181 <span class="dashicons <?php echo esc_attr( $tab['icon'] ); ?>" style="font-size: 16px; width: 16px; height: 16px; vertical-align: text-bottom; margin-right: 5px;"></span>
182 <?php echo esc_html( $tab['label'] ); ?>
183 </a>
184 <?php endforeach; ?>
185 </nav>
186
187 <!-- Tab Content -->
188 <div class="atomicedge-cdn-tab-content">
189 <form id="atomicedge-cdn-settings-form" method="post" action="">
190 <?php wp_nonce_field( 'atomicedge_cdn_settings', 'atomicedge_cdn_nonce' ); ?>
191 <input type="hidden" name="atomicedge_cdn_tab" value="<?php echo esc_attr( $current_tab ); ?>">
192
193 <?php
194 switch ( $current_tab ) {
195 case 'minification':
196 include ATOMICEDGE_PLUGIN_DIR . 'admin/views/partials/cdn-minification-tab.php';
197 break;
198 case 'advanced':
199 include ATOMICEDGE_PLUGIN_DIR . 'admin/views/partials/cdn-advanced-tab.php';
200 break;
201 case 'general':
202 default:
203 include ATOMICEDGE_PLUGIN_DIR . 'admin/views/partials/cdn-general-tab.php';
204 break;
205 }
206 ?>
207
208 <div class="atomicedge-card" style="margin-top: 20px; border-top: 1px solid #c3c4c7;">
209 <p class="submit" style="margin: 0; padding: 15px 0 0;">
210 <button type="submit" name="atomicedge_save_cdn_settings" class="button button-primary button-large">
211 <?php esc_html_e( 'Save CDN Settings', 'atomic-edge-security' ); ?>
212 </button>
213 <span id="atomicedge-cdn-settings-status" class="atomicedge-inline-status"></span>
214 </p>
215 </div>
216 </form>
217 </div>
218
219 <?php endif; ?>
220 </div>
221 </div>
222
223 <script type="text/javascript">
224 (function($) {
225 'use strict';
226
227 $(document).ready(function() {
228 // Debug: Check if atomicedgeAdmin is available.
229 if (typeof atomicedgeAdmin === 'undefined') {
230 console.error('AtomicEdge: atomicedgeAdmin is not defined. Scripts may not be loaded correctly.');
231 return;
232 }
233
234 // Copy to clipboard.
235 $('.atomicedge-copy-btn').on('click', function(e) {
236 e.preventDefault();
237 var targetSelector = $(this).data('copy-target');
238 var textToCopy = $(targetSelector).text();
239
240 if (navigator.clipboard && navigator.clipboard.writeText) {
241 navigator.clipboard.writeText(textToCopy).then(function() {
242 showCopySuccess(e.currentTarget);
243 });
244 } else {
245 var $temp = $('<textarea>');
246 $('body').append($temp);
247 $temp.val(textToCopy).select();
248 document.execCommand('copy');
249 $temp.remove();
250 showCopySuccess(e.currentTarget);
251 }
252 });
253
254 function showCopySuccess(button) {
255 var $btn = $(button);
256 $btn.find('.dashicons').removeClass('dashicons-clipboard').addClass('dashicons-yes');
257 setTimeout(function() {
258 $btn.find('.dashicons').removeClass('dashicons-yes').addClass('dashicons-clipboard');
259 }, 2000);
260 }
261
262 // Refresh CDN status.
263 $('#atomicedge-cdn-refresh').on('click', function(e) {
264 e.preventDefault();
265 var $button = $(this);
266 var $status = $('#atomicedge-cdn-refresh-status');
267
268 $button.prop('disabled', true).find('.dashicons').addClass('atomicedge-spinning');
269 $status.removeClass('atomicedge-status-success atomicedge-status-error').text('<?php echo esc_js( __( 'Refreshing...', 'atomic-edge-security' ) ); ?>');
270
271 $.ajax({
272 url: atomicedgeAdmin.ajaxUrl,
273 type: 'POST',
274 timeout: 30000,
275 data: {
276 action: 'atomicedge_refresh_cdn_status',
277 nonce: atomicedgeAdmin.nonce
278 },
279 success: function(response) {
280 if (response.success) {
281 $status.addClass('atomicedge-status-success').text(response.data.message || '<?php echo esc_js( __( 'Status refreshed!', 'atomic-edge-security' ) ); ?>');
282 setTimeout(function() {
283 location.reload();
284 }, 500);
285 } else {
286 var errorMsg = response.data && response.data.message ? response.data.message : '<?php echo esc_js( __( 'Failed to refresh status.', 'atomic-edge-security' ) ); ?>';
287 $status.addClass('atomicedge-status-error').text(errorMsg);
288 $button.prop('disabled', false).find('.dashicons').removeClass('atomicedge-spinning');
289 }
290 },
291 error: function(xhr, status) {
292 var errorMsg = '<?php echo esc_js( __( 'Connection failed.', 'atomic-edge-security' ) ); ?>';
293 if (status === 'timeout') {
294 errorMsg = '<?php echo esc_js( __( 'Request timed out.', 'atomic-edge-security' ) ); ?>';
295 }
296 $status.addClass('atomicedge-status-error').text(errorMsg);
297 $button.prop('disabled', false).find('.dashicons').removeClass('atomicedge-spinning');
298 }
299 });
300 });
301
302 // Purge CDN cache.
303 $('#atomicedge-purge-cdn').on('click', function(e) {
304 e.preventDefault();
305
306 if (!confirm('<?php echo esc_js( __( 'Are you sure you want to purge the CDN cache?', 'atomic-edge-security' ) ); ?>')) {
307 return;
308 }
309
310 var $button = $(this);
311 var $status = $('#atomicedge-purge-status');
312
313 $button.prop('disabled', true);
314 $status.removeClass('atomicedge-status-success atomicedge-status-error').text('<?php echo esc_js( __( 'Purging...', 'atomic-edge-security' ) ); ?>');
315
316 $.ajax({
317 url: atomicedgeAdmin.ajaxUrl,
318 type: 'POST',
319 data: {
320 action: 'atomicedge_purge_cdn_cache',
321 nonce: atomicedgeAdmin.nonce
322 },
323 success: function(response) {
324 if (response.success) {
325 $status.addClass('atomicedge-status-success').text(response.data.message || '<?php echo esc_js( __( 'Cache purged!', 'atomic-edge-security' ) ); ?>');
326 } else {
327 $status.addClass('atomicedge-status-error').text(response.data ? response.data.message : '<?php echo esc_js( __( 'Failed to purge cache.', 'atomic-edge-security' ) ); ?>');
328 $button.prop('disabled', false);
329 }
330 },
331 error: function() {
332 $status.addClass('atomicedge-status-error').text('<?php echo esc_js( __( 'Connection failed.', 'atomic-edge-security' ) ); ?>');
333 $button.prop('disabled', false);
334 }
335 });
336 });
337
338 // CDN Settings form AJAX submission.
339 $('#atomicedge-cdn-settings-form').on('submit', function(e) {
340 e.preventDefault();
341
342 var $form = $(this);
343 var $status = $('#atomicedge-cdn-settings-status');
344 var $submitBtn = $form.find('button[type="submit"]');
345
346 $submitBtn.prop('disabled', true);
347 $status.removeClass('atomicedge-status-success atomicedge-status-error').text('<?php echo esc_js( __( 'Saving...', 'atomic-edge-security' ) ); ?>');
348
349 $.ajax({
350 url: atomicedgeAdmin.ajaxUrl,
351 type: 'POST',
352 data: {
353 action: 'atomicedge_save_cdn_settings',
354 nonce: atomicedgeAdmin.nonce,
355 formData: $form.serialize()
356 },
357 success: function(response) {
358 if (response.success) {
359 $status.addClass('atomicedge-status-success').text(response.data.message || '<?php echo esc_js( __( 'Settings saved!', 'atomic-edge-security' ) ); ?>');
360 } else {
361 $status.addClass('atomicedge-status-error').text(response.data ? response.data.message : '<?php echo esc_js( __( 'Failed to save settings.', 'atomic-edge-security' ) ); ?>');
362 }
363 },
364 error: function() {
365 $status.addClass('atomicedge-status-error').text('<?php echo esc_js( __( 'Connection failed.', 'atomic-edge-security' ) ); ?>');
366 },
367 complete: function() {
368 $submitBtn.prop('disabled', false);
369 setTimeout(function() {
370 $status.text('');
371 }, 3000);
372 }
373 });
374 });
375 });
376 })(jQuery);
377 </script>
378
379 <style type="text/css">
380 /* Tab Navigation */
381 .atomicedge-cdn .nav-tab-wrapper {
382 border-bottom: 1px solid #c3c4c7;
383 }
384 .atomicedge-cdn .nav-tab {
385 display: inline-flex;
386 align-items: center;
387 margin-left: 0;
388 margin-right: 5px;
389 }
390 .atomicedge-cdn .nav-tab-active {
391 background: #fff;
392 border-bottom-color: #fff;
393 }
394
395 /* Tab Content */
396 .atomicedge-cdn-tab-content {
397 background: #fff;
398 border: 1px solid #c3c4c7;
399 border-top: none;
400 padding: 0;
401 }
402 .atomicedge-cdn-tab-content .atomicedge-card {
403 border: none;
404 border-radius: 0;
405 box-shadow: none;
406 margin: 0;
407 padding: 20px;
408 border-bottom: 1px solid #f0f0f1;
409 }
410 .atomicedge-cdn-tab-content .atomicedge-card:last-child {
411 border-bottom: none;
412 }
413
414 /* Inline status messages */
415 .atomicedge-inline-status {
416 margin-left: 10px;
417 font-style: italic;
418 }
419 .atomicedge-inline-status.atomicedge-status-success {
420 color: #00a32a;
421 }
422 .atomicedge-inline-status.atomicedge-status-error {
423 color: #d63638;
424 }
425
426 /* Spinning animation for refresh */
427 .atomicedge-spinning {
428 animation: atomicedge-spin 1s linear infinite;
429 }
430 @keyframes atomicedge-spin {
431 from { transform: rotate(0deg); }
432 to { transform: rotate(360deg); }
433 }
434
435 /* Status table */
436 .atomicedge-status-table th {
437 width: 150px;
438 padding: 10px 10px 10px 0;
439 }
440 .atomicedge-status-table td {
441 padding: 10px 0;
442 }
443
444 /* Status display for non-enabled state */
445 .atomicedge-cdn-status-display {
446 margin: 10px 0;
447 }
448 </style>
449