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-auto-index.php

admin-auto-index.php in AL Pack trunk, at templates/admin-auto-index.php

715 lines 36.6 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 $current_tab = 'settings';
14 if (current_user_can('manage_options') && is_admin() && isset($_GET['tab'])) {
15 $tab_value = sanitize_text_field(wp_unslash($_GET['tab']));
16 if (in_array($tab_value, array('settings', 'logs', 'manual'))) {
17 $current_tab = $tab_value;
18 }
19 }
20
21 if (isset($_POST['presslearn_toggle_auto_index']) && isset($_POST['enable'])) {
22 check_admin_referer('presslearn_toggle_auto_index_nonce');
23
24 if (current_user_can('manage_options')) {
25 $enable = sanitize_text_field(wp_unslash($_POST['enable']));
26 if ($enable === 'yes' || $enable === 'no') {
27 update_option('presslearn_auto_index_enabled', $enable);
28 $updated = true;
29 }
30 }
31 }
32
33 if (isset($_POST['save_auto_index_settings'])) {
34 check_admin_referer('presslearn_save_auto_index_settings_nonce');
35
36 if (current_user_can('manage_options')) {
37 if (isset($_POST['indexnow_api_key'])) {
38 $api_key = sanitize_text_field(wp_unslash($_POST['indexnow_api_key']));
39 update_option('presslearn_indexnow_api_key', $api_key);
40
41 if (!empty($api_key)) {
42 $indexnow = presslearn_indexnow();
43 if ($indexnow->validate_api_key($api_key)) {
44 $indexnow->create_api_key_file($api_key);
45 }
46 }
47 }
48
49 $auto_indexing_enabled = isset($_POST['auto_indexing_enabled']) ? 'yes' : 'no';
50 update_option('presslearn_auto_indexing_enabled', $auto_indexing_enabled);
51
52 $index_post_types = isset($_POST['index_post_types']) && is_array($_POST['index_post_types'])
53 ? array_map('sanitize_text_field', array_map('wp_unslash', $_POST['index_post_types']))
54 : array();
55 $valid_post_types = array();
56 $allowed_post_types = array('post', 'page');
57
58 foreach ($index_post_types as $post_type) {
59 if (in_array($post_type, $allowed_post_types)) {
60 $valid_post_types[] = $post_type;
61 }
62 }
63
64 update_option('presslearn_index_post_types', $valid_post_types);
65
66 $settings_updated = true;
67 }
68 }
69
70 $auto_index_enabled = get_option('presslearn_auto_index_enabled', 'no');
71 $indexnow_api_key = get_option('presslearn_indexnow_api_key', '');
72 $auto_indexing_enabled = get_option('presslearn_auto_indexing_enabled', 'yes');
73 $index_post_types = get_option('presslearn_index_post_types', array('post', 'page'));
74 $has_api_key = !empty($indexnow_api_key);
75
76 ?>
77
78 <div class="presslearn-header">
79 <div class="presslearn-header-logo">
80 <img src="<?php echo esc_url(PRESSLEARN_PLUGIN_URL); ?>assets/images/logo.png" alt="PressLearn Logo">
81 <h1>자동 인덱싱</h1>
82 </div>
83 <div class="presslearn-header-status">
84 <?php if ($auto_index_enabled === 'yes'): ?>
85 <div class="presslearn-header-status-item status-activate">
86 <p>기능이 활성화되었습니다.</p>
87 </div>
88 <?php else: ?>
89 <div class="presslearn-header-status-item status-deactivate">
90 <p>기능이 비활성화 상태�
91 니다.</p>
92 </div>
93 <?php endif; ?>
94 </div>
95 </div>
96
97 <div class="wrap">
98
99 <div class="presslearn-breadcrumbs-wrap">
100 <div class="presslearn-breadcrumbs">
101 <span>대시보드</span>
102 <span class="divider">/</span>
103 <span class="active">자동 인덱싱</span>
104 </div>
105 </div>
106
107 <?php if (isset($settings_updated) && $settings_updated): ?>
108 <div class="notice notice-success inline">
109 <p>설정 정보가 성공적으로 저장되었습니다.</p>
110 </div>
111 <?php endif; ?>
112
113 <?php if (isset($updated) && $updated): ?>
114 <div class="notice notice-success inline">
115 <p>자동 인덱싱 기능 설정이 변경되었습니다.</p>
116 </div>
117 <?php endif; ?>
118
119 <?php if (!$has_api_key && $auto_index_enabled === 'yes'): ?>
120 <div class="notice notice-warning inline">
121 <p>IndexNow API 키를 설정해야 인덱싱 기능을 사용할 있습니다.<br/><a href="https://www.bing.com/indexnow" target="_blank">IndexNow API 발급 받기</a></p>
122 </div>
123 <?php endif; ?>
124
125 <div class="presslearn-tabs">
126 <a href="?page=presslearn-auto-index&tab=settings" class="tab-link <?php echo esc_attr($current_tab === 'settings' ? 'active' : ''); ?>">설정</a>
127 <a href="?page=presslearn-auto-index&tab=logs" class="tab-link <?php echo esc_attr($current_tab === 'logs' ? 'active' : ''); ?>">로그</a>
128 <a href="?page=presslearn-auto-index&tab=manual" class="tab-link <?php echo esc_attr($current_tab === 'manual' ? 'active' : ''); ?>">수동 인덱싱</a>
129 </div>
130
131 <?php if ($current_tab === 'settings'): ?>
132
133 <div class="presslearn-card">
134 <div class="presslearn-card-header">
135 <h2>자동 인덱싱</h2>
136 <p>IndexNow 프로토콜을 사용하여 네이버에 자동으로 인덱싱 요청을 보내는 기능�
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="auto-index-toggle-form">
146 <?php wp_nonce_field('presslearn_toggle_auto_index_nonce'); ?>
147 <input type="hidden" name="presslearn_toggle_auto_index" value="1">
148 <input type="hidden" name="enable" id="auto-index-enable-value" value="<?php echo esc_attr($auto_index_enabled === 'yes' ? 'no' : 'yes'); ?>">
149
150 <label class="switch">
151 <input type="checkbox" <?php echo esc_attr($auto_index_enabled === 'yes' ? 'checked' : ''); ?> onchange="document.getElementById('auto-index-enable-value').value = this.checked ? 'yes' : 'no'; document.getElementById('auto-index-toggle-form').submit();">
152 <span class="slider round"></span>
153 </label>
154 </form>
155 </div>
156 </div>
157 <form method="post" action="" id="auto-index-settings-form">
158 <?php wp_nonce_field('presslearn_save_auto_index_settings_nonce'); ?>
159 <input type="hidden" name="save_auto_index_settings" value="1">
160
161 <div class="presslearn-card-body-row">
162 <div class="presslearn-card-body-row-item grid-left">
163 <h3>IndexNow API </h3>
164 </div>
165 <div class="presslearn-card-body-row-item grid-right">
166 <input type="text" name="indexnow_api_key" class="regular-text" value="<?php echo esc_attr($indexnow_api_key); ?>" placeholder="32자리 영숫자 API 키를 �
167 력하세요">
168 </div>
169 </div>
170
171 <div class="presslearn-card-body-row">
172 <div class="presslearn-card-body-row-item grid-left">
173 <h3>자동 인덱싱 활성화</h3>
174 <p style="font-size: 13px; color: #666; margin-top: 5px;">게시글 발행/수정 시 자동으로 인덱싱 요청</p>
175 </div>
176 <div class="presslearn-card-body-row-item grid-right">
177 <label class="switch">
178 <input type="checkbox" name="auto_indexing_enabled" <?php echo esc_attr($auto_indexing_enabled === 'yes' ? 'checked' : ''); ?>>
179 <span class="slider round"></span>
180 </label>
181 </div>
182 </div>
183
184 <div class="presslearn-card-body-row">
185 <div class="presslearn-card-body-row-item grid-left">
186 <h3>인덱싱 대상 콘�
187 �츠</h3>
188 </div>
189 <div class="presslearn-card-body-row-item grid-right">
190 <div class="social-share-options">
191 <label class="social-share-button">
192 <input type="checkbox" name="index_post_types[]" value="post" <?php echo esc_attr(in_array('post', $index_post_types) ? 'checked' : ''); ?>>
193 <span class="social-btn">게시글</span>
194 </label><label class="social-share-button">
195 <input type="checkbox" name="index_post_types[]" value="page" <?php echo esc_attr(in_array('page', $index_post_types) ? 'checked' : ''); ?>>
196 <span class="social-btn">페이지</span>
197 </label>
198 </div>
199 </div>
200 </div>
201 </form>
202 </div>
203 <div class="presslearn-card-footer">
204 <div class="presslearn-card-footer-item grid-left">
205 <span class="tip_button">IndexNow는 요청을 보낼 , 인덱싱 결과를 보장하지 않습니다.</span>
206 </div>
207 <div class="presslearn-card-footer-item grid-right">
208 <button type="submit" class="point-btn" form="auto-index-settings-form">저장하기</button>
209 </div>
210 </div>
211 </div>
212
213 <?php elseif ($current_tab === 'logs'): ?>
214
215 <div class="presslearn-card">
216 <div class="presslearn-card-header">
217 <h2>인덱싱 로그</h2>
218 <p>인덱싱 요청 결과와 상태를 확인할 있습니다.</p>
219 </div>
220 <div class="presslearn-card-body">
221 <div class="presslearn-card-body-row">
222 <div class="presslearn-card-body-row-item" style="flex: 100%;">
223 <?php
224 global $wpdb;
225 $table_name = $wpdb->prefix . 'presslearn_indexing_logs';
226 $logs_per_page = 20;
227 $current_page = isset($_GET['logs_page']) ? max(1, intval($_GET['logs_page'])) : 1;
228 $logs_search = isset($_GET['logs_search']) ? sanitize_text_field($_GET['logs_search']) : '';
229 $offset = ($current_page - 1) * $logs_per_page;
230
231 $logs = array();
232 $total_logs = 0;
233
234 if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name) {
235 $where_clause = '';
236 $params = array();
237
238 if (!empty($logs_search)) {
239 $where_clause = "WHERE post_title LIKE %s OR post_url LIKE %s";
240 $search_term = '%' . $wpdb->esc_like($logs_search) . '%';
241 $params[] = $search_term;
242 $params[] = $search_term;
243 }
244
245 if (!empty($logs_search)) {
246 $total_logs = $wpdb->get_var($wpdb->prepare(
247 "SELECT COUNT(*) FROM $table_name $where_clause",
248 $params
249 ));
250 } else {
251 $total_logs = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
252 }
253
254 if (!empty($logs_search)) {
255 $logs = $wpdb->get_results($wpdb->prepare(
256 "SELECT * FROM $table_name $where_clause ORDER BY indexed_at DESC LIMIT %d OFFSET %d",
257 array_merge($params, array($logs_per_page, $offset))
258 ), ARRAY_A);
259 } else {
260 $logs = $wpdb->get_results($wpdb->prepare(
261 "SELECT * FROM $table_name ORDER BY indexed_at DESC LIMIT %d OFFSET %d",
262 $logs_per_page,
263 $offset
264 ), ARRAY_A);
265 }
266 }
267
268 $max_pages = ceil($total_logs / $logs_per_page);
269 ?>
270
271 <form method="get" action="" style="margin-bottom: 15px;">
272 <input type="hidden" name="page" value="presslearn-auto-index">
273 <input type="hidden" name="tab" value="logs">
274 <div style="display: flex; align-items: center; gap: 10px;">
275 <input type="text" name="logs_search" class="regular-text" placeholder="게시글 제목 또는 URL 검색" style="width: 300px;" value="<?php echo esc_attr($logs_search); ?>">
276 <button type="submit" class="secondary-btn">검색</button>
277 <?php if (!empty($logs_search)): ?>
278 <a href="<?php echo esc_url(add_query_arg(array('page' => 'presslearn-auto-index', 'tab' => 'logs'))); ?>" class="button">전체 보기</a>
279 <?php endif; ?>
280 </div>
281 </form>
282
283 <?php if (empty($logs)): ?>
284 <?php if (!empty($logs_search)): ?>
285 <p style="text-align: center; color: #666; padding: 40px;">'<?php echo esc_html($logs_search); ?>' 검색 결과가 없습니다.</p>
286 <?php else: ?>
287 <p style="text-align: center; color: #666; padding: 40px;">아직 인덱싱 로그가 없습니다.</p>
288 <?php endif; ?>
289 <?php else: ?>
290 <table class="widefat">
291 <thead>
292 <tr>
293 <th>게시글</th>
294 <th>요청 유형</th>
295 <th>응답 코드</th>
296 <th>응답 메시지</th>
297 <th>요청 시간</th>
298 </tr>
299 </thead>
300 <tbody>
301 <?php foreach ($logs as $log): ?>
302 <tr>
303 <td>
304 <strong><?php echo esc_html($log['post_title']); ?></strong><br>
305 <small><a href="<?php echo esc_url($log['post_url']); ?>" target="_blank"><?php echo esc_html($log['post_url']); ?></a></small>
306 </td>
307 <td>
308 <?php if ($log['request_type'] === 'auto'): ?>
309 <span style="background: #E3F2FD; color: #1976D2; padding: 2px 8px; border-radius: 12px; font-size: 11px;">자동</span>
310 <?php elseif ($log['request_type'] === 'manual'): ?>
311 <span style="background: #E8F5E9; color: #388E3C; padding: 2px 8px; border-radius: 12px; font-size: 11px;">수동</span>
312 <?php else: ?>
313 <span style="background: #FFF3E0; color: #F57C00; padding: 2px 8px; border-radius: 12px; font-size: 11px;">일괄</span>
314 <?php endif; ?>
315 </td>
316 <td>
317 <?php
318 $is_success = in_array($log['response_code'], array('200', '202'));
319 $color = $is_success ? '#4CAF50' : '#f44336';
320 ?>
321 <span style="color: <?php echo esc_attr($color); ?>; font-weight: bold;"><?php echo esc_html($log['response_code'] ?: 'N/A'); ?></span>
322 </td>
323 <td><?php echo esc_html($log['response_message'] ?: ''); ?></td>
324 <td><?php echo esc_html(mysql2date('Y-m-d H:i:s', $log['indexed_at'])); ?></td>
325 </tr>
326 <?php endforeach; ?>
327 </tbody>
328 </table>
329
330 <?php if ($max_pages > 1): ?>
331 <div class="tablenav">
332 <div class="tablenav-pages">
333 <span class="displaying-num"> <?php echo esc_html(number_format($total_logs)); ?> 항목</span>
334 <span class="pagination-links">
335 <?php
336 $logs_base_url = add_query_arg(array(
337 'page' => 'presslearn-auto-index',
338 'tab' => 'logs',
339 'logs_search' => $logs_search
340 ));
341 ?>
342 <?php if ($current_page > 1): ?>
343 <a href="<?php echo esc_url(add_query_arg('logs_page', 1, $logs_base_url)); ?>" class="button">처음</a>
344 <a href="<?php echo esc_url(add_query_arg('logs_page', $current_page - 1, $logs_base_url)); ?>" class="button">이전</a>
345 <?php endif; ?>
346
347 <span class="paging-input"><?php echo esc_html($current_page); ?> / <?php echo esc_html($max_pages); ?></span>
348
349 <?php if ($current_page < $max_pages): ?>
350 <a href="<?php echo esc_url(add_query_arg('logs_page', $current_page + 1, $logs_base_url)); ?>" class="button">다음</a>
351 <a href="<?php echo esc_url(add_query_arg('logs_page', $max_pages, $logs_base_url)); ?>" class="button">마지막</a>
352 <?php endif; ?>
353 </span>
354 </div>
355 </div>
356 <?php endif; ?>
357 <?php endif; ?>
358 </div>
359 </div>
360 </div>
361 <div class="presslearn-card-footer">
362 <div class="presslearn-card-footer-item grid-left">
363 <span class="tip_button">응답 코드 200, 202 성공을 의미하며, 실제 인덱싱은 검색 엔진의 판단에 따라 결정됩니다.</span>
364 </div>
365 <div class="presslearn-card-footer-item grid-right">
366 </div>
367 </div>
368 </div>
369
370 <?php elseif ($current_tab === 'manual'): ?>
371
372 <div class="presslearn-card">
373 <div class="presslearn-card-header">
374 <h2>수동 인덱싱</h2>
375 <p>게시글을 수동으로 선택하여 인덱싱 요청을 보낼 있습니다. 인덱싱 상태는 가장 최근 요청 결과를 기준으로 표시됩니다.</p>
376 </div>
377 <div class="presslearn-card-body">
378 <?php if (!$has_api_key): ?>
379 <div class="notice notice-error inline">
380 <p>수동 인덱싱을 사용하려면 먼저 IndexNow API 키를 설정해주세요.</p>
381 </div>
382 <?php else: ?>
383 <div class="presslearn-card-body-row">
384 <div class="presslearn-card-body-row-item" style="flex: 100%;">
385 <?php
386 $posts_per_page = 20;
387 $current_page = isset($_GET['posts_page']) ? max(1, intval($_GET['posts_page'])) : 1;
388 $search_term = isset($_GET['search']) ? sanitize_text_field($_GET['search']) : '';
389
390 $args = array(
391 'post_type' => array('post', 'page'),
392 'post_status' => 'publish',
393 'posts_per_page' => $posts_per_page,
394 'paged' => $current_page,
395 'meta_query' => array(
396 'relation' => 'OR',
397 array(
398 'key' => '_presslearn_exclude_from_index',
399 'value' => 'yes',
400 'compare' => '!='
401 ),
402 array(
403 'key' => '_presslearn_exclude_from_index',
404 'compare' => 'NOT EXISTS'
405 )
406 )
407 );
408
409 if (!empty($search_term)) {
410 $args['s'] = $search_term;
411 }
412
413 $query = new WP_Query($args);
414
415 function get_post_indexing_status($post_id) {
416 global $wpdb;
417 $table_name = $wpdb->prefix . 'presslearn_indexing_logs';
418
419 if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
420 return array(
421 'status' => 'never',
422 'label' => '미요청',
423 'class' => 'never',
424 'last_indexed' => null
425 );
426 }
427
428 $recent_log = $wpdb->get_row($wpdb->prepare(
429 "SELECT response_code, indexed_at, request_type
430 FROM $table_name
431 WHERE post_id = %d
432 ORDER BY indexed_at DESC
433 LIMIT 1",
434 $post_id
435 ));
436
437 if (!$recent_log) {
438 return array(
439 'status' => 'never',
440 'label' => '미요청',
441 'class' => 'never',
442 'last_indexed' => null
443 );
444 }
445
446 $success_codes = array('200', '202');
447 $is_success = in_array($recent_log->response_code, $success_codes);
448
449 if ($is_success) {
450 return array(
451 'status' => 'success',
452 'label' => '성공',
453 'class' => 'success',
454 'last_indexed' => $recent_log->indexed_at
455 );
456 } else {
457 return array(
458 'status' => 'failed',
459 'label' => '실패',
460 'class' => 'failed',
461 'last_indexed' => $recent_log->indexed_at
462 );
463 }
464 }
465 ?>
466
467 <form method="get" action="" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
468 <input type="hidden" name="page" value="presslearn-auto-index">
469 <input type="hidden" name="tab" value="manual">
470 <div style="display: flex; align-items: center; gap: 10px;">
471 <input type="text" name="search" class="regular-text" placeholder="게시글 제목 검색" style="width: 250px;" value="<?php echo esc_attr($search_term); ?>">
472 <button type="submit" class="secondary-btn">검색</button>
473 </div>
474 <div>
475 <button type="button" class="point-btn" id="bulk-index-btn" disabled>선택된 게시글 인덱싱</button>
476 </div>
477 </form>
478
479 <?php if (!$query->have_posts()): ?>
480 <p style="text-align: center; color: #666; padding: 40px;">인덱싱할 게시글이 없습니다.</p>
481 <?php else: ?>
482 <form id="bulk-index-form">
483 <?php wp_nonce_field('presslearn_indexing_nonce', 'bulk_index_nonce'); ?>
484 <table class="widefat">
485 <thead>
486 <tr>
487 <th style="width: 40px;"><input type="checkbox" id="select-all-posts"></th>
488 <th>제목</th>
489 <th>유형</th>
490 <th>작성일</th>
491 <th>인덱싱 상태</th>
492 <th>동작</th>
493 </tr>
494 </thead>
495 <tbody>
496 <?php while ($query->have_posts()): $query->the_post(); ?>
497 <?php
498 $post_id = get_the_ID();
499 $indexing_status = get_post_indexing_status($post_id);
500 ?>
501 <tr>
502 <td><input type="checkbox" class="post-checkbox" name="post_ids[]" value="<?php echo esc_attr($post_id); ?>"></td>
503 <td>
504 <strong><?php echo esc_html(get_the_title()); ?></strong><br>
505 <small><a href="<?php echo esc_url(get_permalink()); ?>" target="_blank"><?php echo esc_html(get_permalink()); ?></a></small>
506 </td>
507 <td>
508 <?php if (get_post_type() === 'post'): ?>
509 <span style="background: #E3F2FD; color: #1976D2; padding: 2px 8px; border-radius: 12px; font-size: 11px;">게시글</span>
510 <?php else: ?>
511 <span style="background: #E8F5E9; color: #388E3C; padding: 2px 8px; border-radius: 12px; font-size: 11px;">페이지</span>
512 <?php endif; ?>
513 </td>
514 <td><?php echo esc_html(get_the_date('Y-m-d H:i:s')); ?></td>
515 <td>
516 <?php
517 if ($indexing_status['class'] === 'success') {
518 $style = 'background: #E8F5E9; color: #2E7D32; padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 500;';
519 } elseif ($indexing_status['class'] === 'failed') {
520 $style = 'background: #FFEBEE; color: #C62828; padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 500;';
521 } else {
522 $style = 'background: #F5F5F5; color: #666; padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 500;';
523 }
524 $tooltip = $indexing_status['last_indexed']
525 ? '마지막 요청: ' . mysql2date('Y-m-d H:i:s', $indexing_status['last_indexed'])
526 : '아직 인덱싱 요청을 하지 않았습니다';
527 ?>
528 <span style="<?php echo esc_attr($style); ?>" title="<?php echo esc_attr($tooltip); ?>"><?php echo esc_html($indexing_status['label']); ?></span>
529 </td>
530 <td>
531 <button type="button" class="point-btn index-single-btn" data-post-id="<?php echo esc_attr($post_id); ?>">인덱싱</button>
532 </td>
533 </tr>
534 <?php endwhile; ?>
535 </tbody>
536 </table>
537 </form>
538
539 <?php if ($query->max_num_pages > 1): ?>
540 <div class="tablenav">
541 <div class="tablenav-pages">
542 <span class="displaying-num"> <?php echo esc_html(number_format($query->found_posts)); ?> 항목</span>
543 <span class="pagination-links">
544 <?php
545 $base_url = add_query_arg(array(
546 'page' => 'presslearn-auto-index',
547 'tab' => 'manual',
548 'search' => $search_term
549 ));
550 ?>
551 <?php if ($current_page > 1): ?>
552 <a href="<?php echo esc_url(add_query_arg('posts_page', 1, $base_url)); ?>" class="button">처음</a>
553 <a href="<?php echo esc_url(add_query_arg('posts_page', $current_page - 1, $base_url)); ?>" class="button">이전</a>
554 <?php endif; ?>
555
556 <span class="paging-input"><?php echo esc_html($current_page); ?> / <?php echo esc_html($query->max_num_pages); ?></span>
557
558 <?php if ($current_page < $query->max_num_pages): ?>
559 <a href="<?php echo esc_url(add_query_arg('posts_page', $current_page + 1, $base_url)); ?>" class="button">다음</a>
560 <a href="<?php echo esc_url(add_query_arg('posts_page', $query->max_num_pages, $base_url)); ?>" class="button">마지막</a>
561 <?php endif; ?>
562 </span>
563 </div>
564 </div>
565 <?php endif; ?>
566 <?php endif; ?>
567 <?php wp_reset_postdata(); ?>
568 </div>
569 </div>
570 <?php endif; ?>
571 </div>
572 <div class="presslearn-card-footer">
573 <div class="presslearn-card-footer-item grid-left">
574 <span class="tip_button"> 번에 최대 50개까지 선택하여 일괄 인덱싱할 있습니다.</span>
575 </div>
576 <div class="presslearn-card-footer-item grid-right">
577 </div>
578 </div>
579 </div>
580
581 <?php endif; ?>
582 </div>
583
584 <script type="text/javascript">
585 document.addEventListener('DOMContentLoaded', function() {
586 const selectAllCheckbox = document.getElementById('select-all-posts');
587 if (selectAllCheckbox) {
588 selectAllCheckbox.addEventListener('change', function() {
589 const checkboxes = document.querySelectorAll('.post-checkbox');
590 checkboxes.forEach(function(checkbox) {
591 checkbox.checked = selectAllCheckbox.checked;
592 });
593 updateBulkIndexButton();
594 });
595 }
596
597 const postCheckboxes = document.querySelectorAll('.post-checkbox');
598 postCheckboxes.forEach(function(checkbox) {
599 checkbox.addEventListener('change', updateBulkIndexButton);
600 });
601
602 const indexButtons = document.querySelectorAll('.index-single-btn');
603 indexButtons.forEach(function(button) {
604 button.addEventListener('click', function() {
605 const postId = this.getAttribute('data-post-id');
606 indexSinglePost(postId, this);
607 });
608 });
609
610 function updateBulkIndexButton() {
611 const checkedBoxes = document.querySelectorAll('.post-checkbox:checked');
612 const bulkButton = document.getElementById('bulk-index-btn');
613 if (bulkButton) {
614 bulkButton.disabled = checkedBoxes.length === 0;
615 bulkButton.textContent = checkedBoxes.length > 0 ? '선택된 ' + checkedBoxes.length + '개 게시글 인덱싱' : '선택된 게시글 인덱싱';
616 }
617 }
618
619 function indexSinglePost(postId, button) {
620 const originalText = button.textContent;
621 button.textContent = '처리중';
622 button.disabled = true;
623
624 const formData = new FormData();
625 formData.append('action', 'presslearn_manual_index');
626 formData.append('nonce', '<?php echo esc_js(wp_create_nonce('presslearn_indexing_nonce')); ?>');
627 formData.append('post_id', postId);
628
629 fetch('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', {
630 method: 'POST',
631 credentials: 'same-origin',
632 body: formData
633 })
634 .then(response => response.json())
635 .then(data => {
636 if (data.success) {
637 alert('인덱싱 요청이 성공적으로 전송되었습니다.');
638 location.reload();
639 } else {
640 alert('인덱싱 요청 실패: ' + (data.data.message || '알 수 없는 오류'));
641 }
642 })
643 .catch(error => {
644 console.error('Error:', error);
645 alert('인덱싱 요청 중 오류가 발생했습니다.');
646 })
647 .finally(function() {
648 button.textContent = originalText;
649 button.disabled = false;
650 });
651 }
652
653 const bulkIndexButton = document.getElementById('bulk-index-btn');
654 if (bulkIndexButton) {
655 bulkIndexButton.addEventListener('click', function() {
656 const checkedBoxes = document.querySelectorAll('.post-checkbox:checked');
657 if (checkedBoxes.length === 0) {
658 alert('인덱싱할 게시글을 선택해주세요.');
659 return;
660 }
661
662 if (checkedBoxes.length > 50) {
663 alert('한 번에 최대 50개까지만 선택할 수 있습니다.');
664 return;
665 }
666
667 if (!confirm(checkedBoxes.length + '개의 게시글을 인덱싱하시겠습니까?')) {
668 return;
669 }
670
671 const postIds = Array.from(checkedBoxes).map(function(checkbox) {
672 return checkbox.value;
673 });
674
675 const originalText = this.textContent;
676 this.textContent = '처리중';
677 this.disabled = true;
678
679 const formData = new FormData();
680 formData.append('action', 'presslearn_bulk_index');
681 formData.append('nonce', '<?php echo esc_js(wp_create_nonce('presslearn_indexing_nonce')); ?>');
682 postIds.forEach(function(postId) {
683 formData.append('post_ids[]', postId);
684 });
685
686 fetch('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', {
687 method: 'POST',
688 credentials: 'same-origin',
689 body: formData
690 })
691 .then(response => response.json())
692 .then(data => {
693 if (data.success) {
694 alert(data.data.message);
695 location.reload();
696 } else {
697 alert('일괄 인덱싱 실패: ' + (data.data.message || '알 수 없는 오류'));
698 }
699 })
700 .catch(error => {
701 console.error('Error:', error);
702 alert('일괄 인덱싱 중 오류가 발생했습니다.');
703 })
704 .finally(() => {
705 this.textContent = originalText;
706 this.disabled = false;
707 });
708 });
709 }
710
711 updateBulkIndexButton();
712 });
713 </script>
714
715