PluginProbe
WP Docs / 2.3.1
WP Docs v2.3.1
2.3.3 2.3.2 trunk 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1
wp-docs / inc / functions-verify.php

functions-verify.php in WP Docs 2.3.1, at inc/functions-verify.php

738 lines 22.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Memphis Documents Verification Functions
4 * Corrected to match your existing statistics counting method
5 */
6
7 add_action('wp_ajax_wp_docs_verify_memphis_docs_start', 'wp_docs_verify_memphis_docs_start');
8 add_action('wp_ajax_wp_docs_verify_memphis_docs_batch', 'wp_docs_verify_memphis_docs_batch');
9 add_action('wp_ajax_wp_docs_verify_memphis_docs_clear', 'wp_docs_verify_memphis_docs_clear');
10
11 /**
12 * Start verification - Build queue from Memphis data
13 */
14 function wp_docs_verify_memphis_docs_start() {
15
16 if (!current_user_can('manage_options')) {
17 wp_send_json_error('Permission denied');
18 }
19
20 if (empty($_POST['nonce']) || !wp_verify_nonce(sanitize_wpdocs_data(wp_unslash($_POST['nonce'])), 'wpdocs_verify_nonce')) {
21 wp_send_json_error('Invalid nonce');
22 }
23
24 global $memphis_folders_id;
25
26 // Clear any existing session
27 delete_option('wpdocs_memphis_verify_session');
28
29 $folders = get_option('mdocs-cats', array());
30 $files = get_option('mdocs-list', array());
31
32 // Get already imported items from your existing options
33 $wpdocs_imported_folder = get_option('wpdocs_imported_folder', array());
34 $wpdocs_imported_files = get_option('wpdocs_imported_files', array());
35
36 $queue = array();
37
38 wp_docs_build_verify_queue($folders, $files, $queue, 0, '');
39
40 $session = array(
41 'queue' => $queue,
42 'stats' => array(
43 'folders_total' => 0,
44 'folders_found' => 0,
45 'folders_missing' => 0,
46 'files_total' => 0,
47 'files_found' => 0,
48 'files_missing' => 0,
49 ),
50 'tree' => array(),
51 'missing_folders' => array(),
52 'missing_files' => array(),
53 'pointer' => 0,
54 'imported_folders' => $wpdocs_imported_folder,
55 'imported_files' => $wpdocs_imported_files
56 );
57
58 update_option('wpdocs_memphis_verify_session', $session);
59
60 wp_send_json_success(array(
61 'total_items' => count($queue)
62 ));
63 }
64
65 /**
66 * Build verification queue recursively
67 */
68 function wp_docs_build_verify_queue($folders, $files, &$queue, $depth = 0, $parent_path = '') {
69
70 if (empty($folders)) {
71 return;
72 }
73
74 foreach ($folders as $folder) {
75
76 $current_path = $parent_path ? $parent_path . ' > ' . $folder['name'] : $folder['name'];
77
78 $queue[] = array(
79 'type' => 'folder',
80 'depth' => $depth,
81 'path' => $current_path,
82 'data' => $folder,
83 );
84
85 // Add files belonging to this folder
86 if (!empty($files)) {
87 foreach ($files as $file) {
88 if (isset($file['cat']) && $file['cat'] == $folder['slug']) {
89 $queue[] = array(
90 'type' => 'file',
91 'depth' => ($depth + 1),
92 'path' => $current_path,
93 'data' => $file,
94 );
95 }
96 }
97 }
98
99 // Process children recursively
100 if (!empty($folder['children'])) {
101 wp_docs_build_verify_queue($folder['children'], $files, $queue, ($depth + 1), $current_path);
102 }
103 }
104 }
105
106 /**
107 * Process verification batch
108 */
109 function wp_docs_verify_memphis_docs_batch() {
110
111 if (!current_user_can('manage_options')) {
112 wp_send_json_error('Permission denied');
113 }
114
115 if (empty($_POST['nonce']) || !wp_verify_nonce(sanitize_wpdocs_data(wp_unslash($_POST['nonce'])), 'wpdocs_verify_nonce')) {
116 wp_send_json_error('Invalid nonce');
117 }
118
119 global $memphis_folders_id;
120
121 $session = get_option('wpdocs_memphis_verify_session', array());
122
123 if (empty($session)) {
124 wp_send_json_error('Session expired. Please restart verification.');
125 }
126
127 $batch_size = 100;
128 $queue = $session['queue'];
129 $pointer = intval($session['pointer']);
130 $end = min($pointer + $batch_size, count($queue));
131
132 for ($i = $pointer; $i < $end; $i++) {
133
134 $item = $queue[$i];
135
136 if ($item['type'] == 'folder') {
137
138 $folder = $item['data'];
139
140 // Build the same slug key used during import
141 $slug_key = $memphis_folders_id . '_' . $folder['slug'];
142
143 // Check using your existing imported folders array FIRST (for speed)
144 $status = in_array($slug_key, $session['imported_folders']) ? 'found' : 'missing';
145
146 // Double-check with database for accuracy
147 $args = array(
148 'post_type' => 'wpdocs_folder',
149 'posts_per_page' => 1,
150 'post_status' => 'any',
151 'fields' => 'ids',
152 'meta_query' => array(
153 array(
154 'key' => '_wpdocs_memphis_slug',
155 'value' => $slug_key,
156 'compare' => '='
157 )
158 )
159 );
160
161 $found_posts = get_posts($args);
162
163 $folder_id = 0; // Initialize folder ID
164
165 if (!empty($found_posts)) {
166 $status = 'found';
167 $folder_id = $found_posts[0]; // Get the WP Docs post ID
168 } else {
169 $status = 'missing';
170 }
171
172 $session['stats']['folders_total']++;
173
174 if ($status == 'found') {
175 $session['stats']['folders_found']++;
176 } else {
177 $session['stats']['folders_missing']++;
178 $session['missing_folders'][] = array(
179 'slug' => $folder['slug'],
180 'name' => $folder['name'],
181 'path' => $item['path'],
182 'parent' => $folder['parent']
183 );
184 }
185
186 $session['tree'][] = array(
187 'type' => 'folder',
188 'name' => stripslashes($folder['name']),
189 'slug' => $folder['slug'],
190 'id' => $folder_id, // ADD THIS LINE - WP Docs folder ID for clickable link
191 'depth' => $item['depth'],
192 'path' => $item['path'],
193 'status' => $status
194 );
195
196 } else {
197
198 $file = $item['data'];
199
200 $session['stats']['files_total']++;
201
202 // METHOD 1: Check using your existing imported_files option
203 $status = in_array($file['id'], $session['imported_files']) ? 'found' : 'missing';
204
205 // First, find the destination folder ID
206 $slug_key = $memphis_folders_id . '_' . $file['cat'];
207 $folder_args = array(
208 'post_type' => 'wpdocs_folder',
209 'posts_per_page' => 1,
210 'post_status' => 'any',
211 'fields' => 'ids',
212 'meta_query' => array(
213 array(
214 'key' => '_wpdocs_memphis_slug',
215 'value' => $slug_key,
216 'compare' => '='
217 )
218 )
219 );
220
221 $folder_posts = get_posts($folder_args);
222 $expected_folder_id = !empty($folder_posts) ? $folder_posts[0] : 0;
223
224 // Search for attachment with OR logic for backward compatibility
225 $file_exists = false;
226
227 if ($expected_folder_id) {
228 $args = array(
229 'post_type' => 'attachment',
230 'posts_per_page' => -1,
231 'post_status' => 'any',
232 'post_parent' => $expected_folder_id,
233 'fields' => 'ids',
234 'meta_query' => array(
235 'relation' => 'OR',
236 array(
237 'key' => '_wpdocs_memphis_media_file',
238 'value' => 'true',
239 'compare' => '='
240 ),
241 array(
242 'key' => '_wpdocs_memphis_file_id',
243 'value' => $file['id'],
244 'compare' => '='
245 )
246 )
247 );
248
249 $found_attachments = get_posts($args);
250
251 if (!empty($found_attachments)) {
252 $file_exists = true;
253 }
254 }
255
256 // Also check globally (in case parent is different) - with OR logic
257 if (!$file_exists) {
258 $args = array(
259 'post_type' => 'attachment',
260 'posts_per_page' => -1,
261 'post_status' => 'any',
262 'fields' => 'ids',
263 'meta_query' => array(
264 'relation' => 'OR',
265 array(
266 'key' => '_wpdocs_memphis_media_file',
267 'value' => 'true',
268 'compare' => '='
269 ),
270 array(
271 'key' => '_wpdocs_memphis_file_id',
272 'value' => $file['id'],
273 'compare' => '='
274 )
275 )
276 );
277
278 $found_attachments = get_posts($args);
279
280 if (!empty($found_attachments)) {
281 // Verify it's the correct file by filename
282 foreach ($found_attachments as $attachment_id) {
283 $attached_file = get_post_meta($attachment_id, '_wp_attached_file', true);
284 $filename = isset($file['filename']) ? $file['filename'] : '';
285
286 if ($attached_file && $filename && strpos($attached_file, $filename) !== false) {
287 $file_exists = true;
288 break;
289 }
290 }
291 }
292 }
293
294 if ($file_exists) {
295 $status = 'found';
296 } else {
297 $status = 'missing';
298 }
299
300 // Update status based on actual file existence
301 if ($status == 'found') {
302 $session['stats']['files_found']++;
303 } else {
304 $session['stats']['files_missing']++;
305 $session['missing_files'][] = array(
306 'id' => $file['id'],
307 'name' => isset($file['name']) && !empty($file['name']) ? $file['name'] : basename($file['filename'], '.pdf'),
308 'filename' => $file['filename'],
309 'cat' => $file['cat'],
310 'path' => $item['path']
311 );
312 }
313
314 $file_name = isset($file['name']) && !empty($file['name'])
315 ? $file['name']
316 : (isset($file['filename']) ? basename($file['filename'], '.pdf') : 'Unknown File');
317
318 $session['tree'][] = array(
319 'type' => 'file',
320 'name' => $file_name,
321 'id' => $file['id'],
322 'depth' => $item['depth'],
323 'path' => $item['path'],
324 'status' => $status
325 );
326 }
327 }
328
329 $session['pointer'] = $end;
330 update_option('wpdocs_memphis_verify_session', $session);
331
332 $completed = ($end >= count($queue));
333
334 // Prepare current item for display
335 $current_item = array();
336 if (isset($queue[$end - 1])) {
337 $current_item = $queue[$end - 1];
338 if ($current_item['type'] == 'folder') {
339 $current_item['display_name'] = $current_item['data']['name'];
340 } else {
341 $current_item['display_name'] = isset($current_item['data']['name']) && !empty($current_item['data']['name'])
342 ? $current_item['data']['name']
343 : basename($current_item['data']['filename'], '.pdf');
344 }
345 }
346
347 wp_send_json_success(array(
348 'completed' => $completed,
349 'processed' => $end,
350 'total' => count($queue),
351 'percent' => (count($queue) ? round(($end / count($queue)) * 100, 2) : 100),
352 'current_item' => $current_item,
353 'stats' => $session['stats'],
354 'tree' => $session['tree']
355 ));
356 }
357
358 /**
359 * Clear verification session
360 */
361 function wp_docs_verify_memphis_docs_clear() {
362
363 if (!current_user_can('manage_options')) {
364 wp_send_json_error('Permission denied');
365 }
366
367 if (empty($_POST['nonce']) || !wp_verify_nonce(sanitize_wpdocs_data(wp_unslash($_POST['nonce'])), 'wpdocs_verify_nonce')) {
368 wp_send_json_error('Invalid nonce');
369 }
370
371 delete_option('wpdocs_memphis_verify_session');
372
373 wp_send_json_success();
374 }
375
376 /**
377 * Missing Items Migration Functions
378 * Add to functions-verify.php
379 */
380
381 add_action('wp_ajax_wp_docs_import_missing_memphis_start', 'wp_docs_import_missing_memphis_start');
382 add_action('wp_ajax_wp_docs_import_missing_memphis_batch', 'wp_docs_import_missing_memphis_batch');
383
384 /**
385 * Start missing items import - Build queue from missing items
386 */
387 function wp_docs_import_missing_memphis_start() {
388
389 if (!current_user_can('manage_options')) {
390 wp_send_json_error('Permission denied');
391 }
392
393 if (empty($_POST['nonce']) || !wp_verify_nonce(sanitize_wpdocs_data(wp_unslash($_POST['nonce'])), 'wpdocs_verify_nonce')) {
394 wp_send_json_error('Invalid nonce');
395 }
396
397 // Get verification session which contains missing items
398 $verify_session = get_option('wpdocs_memphis_verify_session', array());
399
400 if (empty($verify_session)) {
401 wp_send_json_error('No verification session found. Please run verification first.');
402 }
403
404 global $memphis_folders_id;
405
406 // Build import queue from missing items
407 $queue = array();
408 $all_folders = get_option('mdocs-cats', array());
409 $all_files = get_option('mdocs-list', array());
410
411 // First, add all missing folders (need to preserve hierarchy)
412 $missing_folders = $verify_session['missing_folders'];
413
414 // Build a map of all folders by slug for quick lookup
415 $folders_by_slug = array();
416 wp_docs_build_folders_map($all_folders, $folders_by_slug);
417
418 // Sort missing folders by depth (parents first)
419 $missing_folders = wp_docs_sort_folders_by_depth($missing_folders, $folders_by_slug);
420
421 foreach ($missing_folders as $folder) {
422 $queue[] = array(
423 'type' => 'folder',
424 'slug' => $folder['slug'],
425 'name' => $folder['name'],
426 'parent' => $folder['parent'],
427 'path' => $folder['path']
428 );
429 }
430
431 // Add all missing files
432 foreach ($verify_session['missing_files'] as $file) {
433 $queue[] = array(
434 'type' => 'file',
435 'id' => $file['id'],
436 'name' => $file['name'],
437 'filename' => $file['filename'],
438 'cat' => $file['cat'],
439 'path' => $file['path']
440 );
441 }
442
443 $import_session = array(
444 'queue' => $queue,
445 'pointer' => 0,
446 'stats' => array(
447 'folders_total' => count($missing_folders),
448 'folders_imported' => 0,
449 'folders_failed' => 0,
450 'files_total' => count($verify_session['missing_files']),
451 'files_imported' => 0,
452 'files_failed' => 0
453 ),
454 'failed_items' => array()
455 );
456
457 update_option('wpdocs_memphis_import_session', $import_session);
458
459 wp_send_json_success(array(
460 'total_items' => count($queue),
461 'folders_total' => count($missing_folders),
462 'files_total' => count($verify_session['missing_files'])
463 ));
464 }
465
466 /**
467 * Build a map of folders by slug for parent lookup
468 */
469 function wp_docs_build_folders_map($folders, &$map, $parent = '0') {
470 foreach ($folders as $folder) {
471 $map[$folder['slug']] = array(
472 'name' => $folder['name'],
473 'parent' => $folder['parent'],
474 'children' => $folder['children']
475 );
476 if (!empty($folder['children'])) {
477 wp_docs_build_folders_map($folder['children'], $map, $folder['slug']);
478 }
479 }
480 }
481
482 /**
483 * Sort folders by depth (parents before children)
484 */
485 function wp_docs_sort_folders_by_depth($folders, $folders_map) {
486 // Simple approach: order by path length (more slashes = deeper)
487 usort($folders, function($a, $b) {
488 $depth_a = substr_count($a['path'], ' > ');
489 $depth_b = substr_count($b['path'], ' > ');
490 return $depth_a - $depth_b;
491 });
492 return $folders;
493 }
494
495 /**
496 * Process missing items import batch
497 */
498 function wp_docs_import_missing_memphis_batch() {
499
500 if (!current_user_can('manage_options')) {
501 wp_send_json_error('Permission denied');
502 }
503
504 if (empty($_POST['nonce']) || !wp_verify_nonce(sanitize_wpdocs_data(wp_unslash($_POST['nonce'])), 'wpdocs_verify_nonce')) {
505 wp_send_json_error('Invalid nonce');
506 }
507
508 global $memphis_folders_id;
509
510 $session = get_option('wpdocs_memphis_import_session', array());
511
512 if (empty($session)) {
513 wp_send_json_error('Import session expired. Please restart.');
514 }
515
516 $batch_size = 10; // Smaller batch for reliability
517 $queue = $session['queue'];
518 $pointer = intval($session['pointer']);
519 $end = min($pointer + $batch_size, count($queue));
520
521 for ($i = $pointer; $i < $end; $i++) {
522
523 $item = $queue[$i];
524
525 if ($item['type'] == 'folder') {
526 $result = wp_docs_import_single_folder($item);
527 if ($result) {
528 $session['stats']['folders_imported']++;
529 } else {
530 $session['stats']['folders_failed']++;
531 $session['failed_items'][] = $item;
532 }
533 } else {
534 $result = wp_docs_import_single_file($item);
535 if ($result) {
536 $session['stats']['files_imported']++;
537 } else {
538 $session['stats']['files_failed']++;
539 $session['failed_items'][] = $item;
540 }
541 }
542 }
543
544 $session['pointer'] = $end;
545 update_option('wpdocs_memphis_import_session', $session);
546
547 $completed = ($end >= count($queue));
548
549 // Prepare current item for display
550 $current_item = array();
551 if (isset($queue[$end - 1])) {
552 $current_item = $queue[$end - 1];
553 if ($current_item['type'] == 'folder') {
554 $current_item['display_name'] = $current_item['name'];
555 } else {
556 $current_item['display_name'] = $current_item['name'];
557 }
558 }
559
560 wp_send_json_success(array(
561 'completed' => $completed,
562 'processed' => $end,
563 'total' => count($queue),
564 'percent' => (count($queue) ? round(($end / count($queue)) * 100, 2) : 100),
565 'current_item' => $current_item,
566 'stats' => $session['stats']
567 ));
568 }
569
570 /**
571 * Import a single missing folder
572 */
573 function wp_docs_import_single_folder($folder) {
574 global $memphis_folders_id;
575
576 // Check if folder already exists (double-check)
577 $slug_key = $memphis_folders_id . '_' . $folder['slug'];
578 $args = array(
579 'post_type' => 'wpdocs_folder',
580 'posts_per_page' => 1,
581 'post_status' => 'any',
582 'fields' => 'ids',
583 'meta_query' => array(
584 array(
585 'key' => '_wpdocs_memphis_slug',
586 'value' => $slug_key,
587 'compare' => '='
588 )
589 )
590 );
591
592 $existing = get_posts($args);
593 if (!empty($existing)) {
594 return true; // Already exists
595 }
596
597 // Find parent folder ID
598 $parent_id = 0;
599 if ($folder['parent'] != '0') {
600 $parent_slug_key = $memphis_folders_id . '_' . $folder['parent'];
601 $parent_args = array(
602 'post_type' => 'wpdocs_folder',
603 'posts_per_page' => 1,
604 'post_status' => 'any',
605 'fields' => 'ids',
606 'meta_query' => array(
607 array(
608 'key' => '_wpdocs_memphis_slug',
609 'value' => $parent_slug_key,
610 'compare' => '='
611 )
612 )
613 );
614 $parent_posts = get_posts($parent_args);
615 if (!empty($parent_posts)) {
616 $parent_id = $parent_posts[0];
617 } else {
618 // Parent not found - try to find by name as fallback
619 $parent_args = array(
620 'post_type' => 'wpdocs_folder',
621 'posts_per_page' => 1,
622 'post_status' => 'any',
623 'title' => $folder['parent_name'] ?? '',
624 'fields' => 'ids'
625 );
626 $parent_posts = get_posts($parent_args);
627 if (!empty($parent_posts)) {
628 $parent_id = $parent_posts[0];
629 }
630 }
631 }
632
633 // Create the folder
634 $post_data = array(
635 'post_title' => $folder['name'],
636 'post_type' => 'wpdocs_folder',
637 'post_status' => 'hidden',
638 'post_author' => get_current_user_id(),
639 'post_parent' => $parent_id
640 );
641
642 $folder_id = wp_insert_post($post_data);
643
644 if ($folder_id && !is_wp_error($folder_id)) {
645 update_post_meta($folder_id, '_wpdocs_memphis_slug', $slug_key);
646 return true;
647 }
648
649 return false;
650 }
651
652 /**
653 * Import a single missing file
654 */
655 function wp_docs_import_single_file($file) {
656 global $memphis_folders_id;
657
658 $attachment_id = $file['id']; // The attachment already exists in WordPress
659
660 // Check if file already has the Memphis meta key
661 $already_imported = get_post_meta($attachment_id, '_wpdocs_memphis_media_file', true);
662 if ($already_imported) {
663 return true; // Already imported
664 }
665
666 // Find the destination folder
667 $slug_key = $memphis_folders_id . '_' . $file['cat'];
668 $folder_args = array(
669 'post_type' => 'wpdocs_folder',
670 'posts_per_page' => 1,
671 'post_status' => 'any',
672 'fields' => 'ids',
673 'meta_query' => array(
674 array(
675 'key' => '_wpdocs_memphis_slug',
676 'value' => $slug_key,
677 'compare' => '='
678 )
679 )
680 );
681
682 $folder_posts = get_posts($folder_args);
683 if (empty($folder_posts)) {
684 error_log("WP Docs: Cannot find destination folder for file ID: " . $attachment_id);
685 return false;
686 }
687
688 $folder_id = $folder_posts[0];
689
690 // Add Memphis meta keys to existing attachment (matching original migration)
691 update_post_meta($attachment_id, '_wpdocs_memphis_media_file', 'true');
692 update_post_meta($attachment_id, '_wpdocs_memphis_file_id', $attachment_id);
693
694 // Add to folder's items list (matching original migration)
695 $wpdocs_items = get_post_meta($folder_id, 'wpdocs_items', true);
696 $wpdocs_items = is_array($wpdocs_items) ? $wpdocs_items : array();
697
698 if (!in_array($attachment_id, $wpdocs_items)) {
699 $wpdocs_items[] = $attachment_id;
700 update_post_meta($folder_id, 'wpdocs_items', $wpdocs_items);
701 }
702
703 // Also update user-specific items if needed (matching original migration)
704 $current_user = get_current_user_id();
705 $wpdocs_items_by_user = get_post_meta($folder_id, 'wpdocs_items_by_user', true);
706 $wpdocs_items_by_user = is_array($wpdocs_items_by_user) ? $wpdocs_items_by_user : array();
707
708 if (!isset($wpdocs_items_by_user[$current_user])) {
709 $wpdocs_items_by_user[$current_user] = array();
710 }
711
712 if (!in_array($attachment_id, $wpdocs_items_by_user[$current_user])) {
713 $wpdocs_items_by_user[$current_user][] = $attachment_id;
714 update_post_meta($folder_id, 'wpdocs_items_by_user', $wpdocs_items_by_user);
715 }
716
717 return true;
718 }
719
720 /**
721 * Clear import session
722 */
723 add_action('wp_ajax_wp_docs_import_missing_memphis_clear', 'wp_docs_import_missing_memphis_clear');
724
725 function wp_docs_import_missing_memphis_clear() {
726
727 if (!current_user_can('manage_options')) {
728 wp_send_json_error('Permission denied');
729 }
730
731 if (empty($_POST['nonce']) || !wp_verify_nonce(sanitize_wpdocs_data(wp_unslash($_POST['nonce'])), 'wpdocs_verify_nonce')) {
732 wp_send_json_error('Invalid nonce');
733 }
734
735 delete_option('wpdocs_memphis_import_session');
736
737 wp_send_json_success();
738 }