PluginProbe
AL Pack / trunk
AL Pack vtrunk
1.3.13 trunk 1.0.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.11 1.3.12
alpack / templates / admin-click-protection.php

admin-click-protection.php in AL Pack trunk, at templates/admin-click-protection.php

468 lines 22.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) {
3 exit;
4 }
5
6 $is_activated = presslearn_plugin()->is_plugin_activated();
7
8 if (!$is_activated) {
9 wp_redirect(admin_url('admin.php?page=presslearn-settings'));
10 exit;
11 }
12
13 if (isset($_POST['presslearn_toggle_click_protection']) && isset($_POST['enable'])) {
14 check_admin_referer('presslearn_toggle_click_protection_nonce');
15
16 if (current_user_can('manage_options')) {
17 $enable = sanitize_text_field(wp_unslash($_POST['enable']));
18 if ($enable === 'yes' || $enable === 'no') {
19 update_option('presslearn_click_protection_enabled', $enable);
20 $updated = true;
21 }
22 }
23 }
24
25 if (current_user_can('manage_options') && is_admin() && isset($_GET['action']) && isset($_GET['enable']) && isset($_GET['feature'])) {
26 if (!isset($_GET['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'presslearn_toggle_click_protection_action')) {
27 wp_die('보안 검증에 실패했습니다.');
28 }
29
30 $action = sanitize_text_field(wp_unslash($_GET['action']));
31 $enable = sanitize_text_field(wp_unslash($_GET['enable']));
32 $feature = sanitize_text_field(wp_unslash($_GET['feature']));
33
34 if ($action === 'toggle' && $feature === 'click_protection' && ($enable === 'yes' || $enable === 'no')) {
35 update_option('presslearn_click_protection_enabled', $enable);
36 $updated = true;
37 }
38 }
39
40 if (isset($_POST['save_click_protection_settings'])) {
41 check_admin_referer('presslearn_save_click_protection_settings_nonce');
42
43 if (current_user_can('manage_options')) {
44 $max_click_count = isset($_POST['max_click_count']) ? intval(wp_unslash($_POST['max_click_count'])) : 10;
45 if ($max_click_count < 1) $max_click_count = 1;
46 if ($max_click_count > 100) $max_click_count = 100;
47
48 $click_time_window = isset($_POST['click_time_window']) ? intval(wp_unslash($_POST['click_time_window'])) : 30;
49 if ($click_time_window < 1) $click_time_window = 1;
50 if ($click_time_window > 1440) $click_time_window = 1440;
51
52 $use_cloudflare = isset($_POST['use_cloudflare']) ? 'yes' : 'no';
53
54 $block_expiry_days = isset($_POST['block_expiry_days']) ? intval(wp_unslash($_POST['block_expiry_days'])) : 30;
55 if ($block_expiry_days < 1) $block_expiry_days = 1;
56 if ($block_expiry_days > 365) $block_expiry_days = 365;
57
58 $modal_title = isset($_POST['modal_title']) ? sanitize_text_field(wp_unslash($_POST['modal_title'])) : '광고 차단 알림';
59
60 $modal_message = isset($_POST['modal_message']) ? sanitize_text_field(wp_unslash($_POST['modal_message'])) : '광고 클릭 제한을 초과하여 광고가 차단되었습니다.';
61
62 $modal_submessage = isset($_POST['modal_submessage']) ? sanitize_text_field(wp_unslash($_POST['modal_submessage'])) : '단시간에 반복적인 광고 클릭은 시스�
63 �에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.';
64
65 $modal_button_text = isset($_POST['modal_button_text']) ? sanitize_text_field(wp_unslash($_POST['modal_button_text'])) : '확인';
66
67 update_option('presslearn_max_click_count', $max_click_count);
68 update_option('presslearn_click_time_window', $click_time_window);
69 update_option('presslearn_click_protection_use_cloudflare', $use_cloudflare);
70 update_option('presslearn_click_protection_block_expiry_days', $block_expiry_days);
71 update_option('presslearn_modal_title', $modal_title);
72 update_option('presslearn_modal_message', $modal_message);
73 update_option('presslearn_modal_submessage', $modal_submessage);
74 update_option('presslearn_modal_button_text', $modal_button_text);
75
76 $settings_updated = true;
77 }
78 }
79
80 $click_protection_enabled = get_option('presslearn_click_protection_enabled', 'no');
81 $max_click_count = get_option('presslearn_max_click_count', 10);
82 $click_time_window = get_option('presslearn_click_time_window', 30);
83 $use_cloudflare = get_option('presslearn_click_protection_use_cloudflare', 'no');
84 $block_expiry_days = get_option('presslearn_click_protection_block_expiry_days', 30);
85
86 $modal_title = get_option('presslearn_modal_title', '광고 차단 알림');
87 $modal_message = get_option('presslearn_modal_message', '광고 클릭 제한을 초과하여 광고가 차단되었습니다.');
88 $modal_submessage = get_option('presslearn_modal_submessage', '단시간에 반복적인 광고 클릭은 시스�
89 �에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.');
90 $modal_button_text = get_option('presslearn_modal_button_text', '확인');
91
92 ?>
93 <div class="presslearn-header">
94 <div class="presslearn-header-logo">
95 <img src="<?php echo esc_url(PRESSLEARN_PLUGIN_URL); ?>assets/images/logo.png" alt="PressLearn Logo">
96 <h1>애드 프로�
97 �터</h1>
98 </div>
99 <div class="presslearn-header-status">
100 <?php if ($click_protection_enabled === 'yes'): ?>
101 <div class="presslearn-header-status-item status-activate">
102 <p>기능이 활성화되었습니다.</p>
103 </div>
104 <?php else: ?>
105 <div class="presslearn-header-status-item status-deactivate">
106 <p>기능이 비활성화 상태�
107 니다.</p>
108 </div>
109 <?php endif; ?>
110 </div>
111 </div>
112
113 <div class="wrap">
114
115 <div class="presslearn-breadcrumbs-wrap">
116 <div class="presslearn-breadcrumbs">
117 <span>대시보드</span>
118 <span class="divider">/</span>
119 <span class="active">애드 프로�
120 �터</span>
121 </div>
122 </div>
123
124 <?php if (isset($settings_updated) && $settings_updated): ?>
125 <div class="notice notice-success inline">
126 <p>설정 정보가 성공적으로 저장되었습니다.</p>
127 </div>
128 <?php endif; ?>
129
130
131 <div class="presslearn-card">
132 <div class="presslearn-card-header">
133 <h2>애드 프로�
134 �터</h2>
135 <p>구글 애드센스 광고를 �
136 의적인 공격으로부터 보호할 수 있는 기능�
137 니다.</p>
138 </div>
139 <div class="presslearn-card-body">
140 <div class="presslearn-card-body-row">
141 <div class="presslearn-card-body-row-item grid-left">
142 <h3>플러그인 기능 활성화</h3>
143 </div>
144 <div class="presslearn-card-body-row-item grid-right">
145 <form method="post" action="" id="click-protection-toggle-form">
146 <?php wp_nonce_field('presslearn_toggle_click_protection_nonce'); ?>
147 <input type="hidden" name="presslearn_toggle_click_protection" value="1">
148 <input type="hidden" name="enable" id="click-protection-enable-value" value="<?php echo esc_attr($click_protection_enabled === 'yes' ? 'no' : 'yes'); ?>">
149
150 <label class="switch">
151 <input type="checkbox" <?php echo esc_attr($click_protection_enabled === 'yes' ? 'checked' : ''); ?> onchange="document.getElementById('click-protection-enable-value').value = this.checked ? 'yes' : 'no'; document.getElementById('click-protection-toggle-form').submit();">
152 <span class="slider round"></span>
153 </label>
154 </form>
155 </div>
156 </div>
157
158 <form method="post" action="" id="click-protection-settings-form">
159 <?php wp_nonce_field('presslearn_save_click_protection_settings_nonce'); ?>
160 <input type="hidden" name="save_click_protection_settings" value="1">
161 <input type="hidden" name="modal_title" value="<?php echo esc_attr($modal_title); ?>">
162 <input type="hidden" name="modal_message" value="<?php echo esc_attr($modal_message); ?>">
163 <input type="hidden" name="modal_submessage" value="<?php echo esc_attr($modal_submessage); ?>">
164 <input type="hidden" name="modal_button_text" value="<?php echo esc_attr($modal_button_text); ?>">
165
166 <div class="presslearn-card-body-row">
167 <div class="presslearn-card-body-row-item grid-left">
168 <h3>최대 허용 클릭 </h3>
169 </div>
170 <div class="presslearn-card-body-row-item grid-right">
171 <input type="number" class="regular-text" name="max_click_count" value="<?php echo esc_attr($max_click_count); ?>" min="1" max="100">
172 </div>
173 </div>
174
175 <div class="presslearn-card-body-row">
176 <div class="presslearn-card-body-row-item grid-left">
177 <h3>클릭 감지 시간()</h3>
178 </div>
179 <div class="presslearn-card-body-row-item grid-right">
180 <input type="number" class="regular-text" name="click_time_window" value="<?php echo esc_attr($click_time_window); ?>" min="1" max="1440">
181 </div>
182 </div>
183
184 <div class="presslearn-card-body-row">
185 <div class="presslearn-card-body-row-item grid-left">
186 <h3>CloudFlare 사용</h3>
187 </div>
188 <div class="presslearn-card-body-row-item grid-right">
189 <label class="switch">
190 <input type="checkbox" name="use_cloudflare" <?php echo esc_attr($use_cloudflare === 'yes' ? 'checked' : ''); ?>>
191 <span class="slider round"></span>
192 </label>
193 </div>
194 </div>
195
196 <div class="presslearn-card-body-row">
197 <div class="presslearn-card-body-row-item grid-left">
198 <h3>허용 IP 설정</h3>
199 </div>
200 <div class="presslearn-card-body-row-item grid-right">
201 <button type="button" id="open-allowed-ip-editor" class="point-btn">설정하기</button>
202 </div>
203 </div>
204
205 <div class="presslearn-card-body-row">
206 <div class="presslearn-card-body-row-item grid-left">
207 <h3>차단 IP 설정</h3>
208 </div>
209 <div class="presslearn-card-body-row-item grid-right">
210 <button type="button" id="open-blocked-ip-editor" class="point-btn">설정하기</button>
211 </div>
212 </div>
213
214 <div class="presslearn-card-body-row">
215 <div class="presslearn-card-body-row-item grid-left">
216 <h3>차단 국가 설정</h3>
217 </div>
218 <div class="presslearn-card-body-row-item grid-right">
219 <button type="button" id="open-blocked-countries-editor" class="point-btn">설정하기</button>
220 </div>
221 </div>
222
223 <div class="presslearn-card-body-row">
224 <div class="presslearn-card-body-row-item grid-left">
225 <h3>차단 IP 해제 주기()</h3>
226 </div>
227 <div class="presslearn-card-body-row-item grid-right">
228 <input type="number" class="regular-text" name="block_expiry_days" value="<?php echo esc_attr($block_expiry_days); ?>" min="1" max="365">
229 </div>
230 </div>
231
232 <div class="presslearn-card-body-row">
233 <div class="presslearn-card-body-row-item grid-left">
234 <h3>차단 모달 설정</h3>
235 </div>
236 <div class="presslearn-card-body-row-item grid-right">
237 <button type="button" id="open-modal-settings" class="point-btn">설정하기</button>
238 </div>
239 </div>
240
241 <div class="presslearn-card-body-row">
242 <div class="presslearn-card-body-row-item grid-left">
243 <h3>차단 로그 확인</h3>
244 </div>
245 <div class="presslearn-card-body-row-item grid-right">
246 <button type="button" id="open-blocked-log-modal" class="point-btn">확인하기</button>
247 </div>
248 </div>
249 </form>
250 </div>
251 <div class="presslearn-card-footer">
252 <div class="presslearn-card-footer-item grid-left">
253 <span class="tip_button">애드 프로�
254 �터는 광고 차단의 무결성을 보장하지 않습니다.</span>
255 </div>
256 <div class="presslearn-card-footer-item grid-right">
257 <button type="submit" class="point-btn" form="click-protection-settings-form">저장하기</button>
258 </div>
259 </div>
260 </div>
261 </div>
262
263 <div id="allowed-ip-modal" class="presslearn-modal" style="display: none;">
264 <div class="presslearn-modal-content">
265 <div class="presslearn-modal-header">
266 <h3>허용 IP 설정</h3>
267 <span class="presslearn-modal-close">&times;</span>
268 </div>
269 <div class="presslearn-modal-body">
270 <div class="ip-add-form">
271 <div class="ip-input-group">
272 <input type="text" id="new-ip-address" placeholder="IP 주소 �
273 (: 192.168.0.1)" class="regular-text">
274 <button type="button" id="add-ip-button" class="point-btn">추가</button>
275 </div>
276 <p class="ip-description">추가한 IP는 클릭 제한에서 제외됩니다.</p>
277 </div>
278
279 <div class="ip-list-container">
280 <table class="widefat ip-list-table">
281 <thead>
282 <tr>
283 <th>IP 주소</th>
284 <th>추가 날짜</th>
285 <th>작�
286 </th>
287 </tr>
288 </thead>
289 <tbody id="allowed-ip-list">
290 </tbody>
291 </table>
292 <div id="no-ips-message" style="text-align: center; padding: 20px; display: none;">
293 <p>등록된 IP가 없습니다. IP를 추가하여 클릭 제한에서 제외하세요.</p>
294 </div>
295 </div>
296 </div>
297 <div class="presslearn-modal-footer">
298 <button type="button" id="close-modal-button" class="secondary-btn">닫기</button>
299 </div>
300 </div>
301 </div>
302
303 <div id="blocked-ip-modal" class="presslearn-modal" style="display: none;">
304 <div class="presslearn-modal-content">
305 <div class="presslearn-modal-header">
306 <h3>차단 IP 설정</h3>
307 <span class="presslearn-modal-close">&times;</span>
308 </div>
309 <div class="presslearn-modal-body">
310 <div class="ip-add-form">
311 <div class="ip-input-group">
312 <input type="text" id="new-blocked-ip" placeholder="차단할 IP 주소 �
313 력 (예: 192.168.0.1)" class="regular-text">
314 <button type="button" id="add-blocked-ip-button" class="point-btn">추가</button>
315 </div>
316 <div style="margin: 10px 0;">
317 <label style="display: flex; align-items: center; gap: 8px;">
318 <input type="checkbox" id="permanent-block-checkbox">
319 <span>영구 차단 (만료일 없음)</span>
320 </label>
321 </div>
322 <p class="ip-description">추가한 IP는 광고 클릭이 완전히 차단됩니다.</p>
323 </div>
324
325 <div class="ip-list-container">
326 <table class="widefat ip-list-table">
327 <thead>
328 <tr>
329 <th>IP 주소</th>
330 <th>차단 날짜</th>
331 <th>작�
332 </th>
333 </tr>
334 </thead>
335 <tbody id="blocked-ip-list">
336 </tbody>
337 </table>
338 <div id="no-blocked-ips-message" style="text-align: center; padding: 20px; display: none;">
339 <p>등록된 차단 IP가 없습니다. �
340 의적인 클릭이 의심되는 IP를 추가하세요.</p>
341 </div>
342 </div>
343 </div>
344 <div class="presslearn-modal-footer">
345 <button type="button" id="close-blocked-modal-button" class="secondary-btn">닫기</button>
346 </div>
347 </div>
348 </div>
349
350 <div id="blocked-countries-editor" class="presslearn-modal" style="display: none;">
351 <div class="presslearn-modal-content">
352 <div class="presslearn-modal-header">
353 <h3>차단 국가 관리</h3>
354 <span class="presslearn-modal-close">&times;</span>
355 </div>
356 <div class="presslearn-modal-body">
357 <div class="ip-add-form" style="display: flex; align-items: center; margin-bottom: 20px;">
358 <div class="country-tag-container" id="blocked-countries-tags"></div>
359 <input type="text" id="blocked-country-input" placeholder="국가를 검색하세요..." class="regular-text" style="flex: 1;">
360 <div id="country-autocomplete" class="country-autocomplete"></div>
361 </div>
362 <p style="margin-top: 10px; color: #666;">
363 <small>차단할 국가를 검색하여 선택하세요. 선택된 국가에서의 모든 접속이 차단됩니다.</small>
364 </p>
365 </div>
366 <div class="presslearn-modal-footer">
367 <button type="button" id="save-blocked-countries" class="point-btn">저장하기</button>
368 <button type="button" id="close-blocked-countries-modal" class="secondary-btn">닫기</button>
369 </div>
370 </div>
371 </div>
372
373 <div id="modal-settings-editor" class="presslearn-modal" style="display: none;">
374 <div class="presslearn-modal-content">
375 <div class="presslearn-modal-header">
376 <h3>차단 모달 설정</h3>
377 <span class="presslearn-modal-close">&times;</span>
378 </div>
379 <div class="presslearn-modal-body">
380 <form id="modal-settings-form">
381 <div class="settings-form-row">
382 <label for="modal_title">모달 제목</label>
383 <input type="text" id="modal_title" name="modal_title" value="<?php echo esc_attr($modal_title); ?>" class="regular-text">
384 </div>
385
386 <div class="settings-form-row">
387 <label for="modal_message">모달 메시지</label>
388 <input type="text" id="modal_message" name="modal_message" value="<?php echo esc_attr($modal_message); ?>" class="regular-text">
389 </div>
390
391 <div class="settings-form-row">
392 <label for="modal_submessage">모달 서브 메시지</label>
393 <input type="text" id="modal_submessage" name="modal_submessage" value="<?php echo esc_attr($modal_submessage); ?>" class="regular-text">
394 </div>
395
396 <div class="settings-form-row">
397 <label for="modal_button_text">모달 버튼 �
398 �스트</label>
399 <input type="text" id="modal_button_text" name="modal_button_text" value="<?php echo esc_attr($modal_button_text); ?>" class="regular-text">
400 </div>
401 </form>
402
403 <div class="modal-preview">
404 <h4>미리보기</h4>
405 <div class="modal-preview-container">
406 <h3 style="color: #d32f2f; margin-top: 0;" id="preview-title"><?php echo esc_html($modal_title); ?></h3>
407 <p style="margin: 10px 0;" id="preview-message"><?php echo esc_html($modal_message); ?></p>
408 <p style="margin: 10px 0; font-size: 13px;" id="preview-submessage"><?php echo esc_html($modal_submessage); ?></p>
409 <button style="background: #d32f2f; color: white; border: none; padding: 8px 16px; border-radius: 4px; margin-top: 10px; cursor: default;" id="preview-button"><?php echo esc_html($modal_button_text); ?></button>
410 </div>
411 </div>
412 </div>
413 <div class="presslearn-modal-footer">
414 <button type="button" id="save-modal-settings" class="point-btn">저장</button>
415 <button type="button" id="close-modal-settings" class="secondary-btn">취소</button>
416 </div>
417 </div>
418 </div>
419
420 <div id="blocked-log-modal" class="presslearn-modal" style="display: none;">
421 <div class="presslearn-modal-content">
422 <div class="presslearn-modal-header">
423 <h3>차단 로그 확인</h3>
424 <span class="presslearn-modal-close">&times;</span>
425 </div>
426 <div class="presslearn-modal-body">
427 <div class="log-filter">
428 <select id="log-filter-period" class="regular-text">
429 <option value="7">최근 7</option>
430 <option value="30" selected>최근 30</option>
431 <option value="90">최근 90</option>
432 <option value="all">전체 기간</option>
433 </select>
434 <button type="button" id="refresh-log" class="point-btn">새로고침</button>
435 </div>
436
437 <div class="log-list-container">
438 <table class="widefat log-list-table">
439 <thead>
440 <tr>
441 <th>IP 주소</th>
442 <th>차단 날짜</th>
443 <th>차단 사유</th>
444 <th>만료 예정일</th>
445 <th>작�
446 </th>
447 </tr>
448 </thead>
449 <tbody id="blocked-log-list">
450 </tbody>
451 </table>
452 <div id="no-blocked-logs-message" style="text-align: center; padding: 20px; display: none;">
453 <p>차단 로그가 없습니다.</p>
454 </div>
455 <div id="log-loading" style="text-align: center; padding: 20px; display: none;">
456 <div class="spinner-container">
457 <span class="spinner is-active"></span>
458 </div>
459 </div>
460 </div>
461 </div>
462 <div class="presslearn-modal-footer">
463 <button type="button" id="close-log-modal-button" class="secondary-btn">닫기</button>
464 </div>
465 </div>
466 </div>
467
468