REDROOM
PHP 8.0.30
Path:
Logout
Edit File
Size: 11.91 KB
Close
/home/certprox/zang.certproxywizard.com/wp/wp-content/plugins/category-sync-exporter/category-sync-exporter.php
Text
Base64
<?php /** * Plugin Name: Category Sync — Exporter (OLD SITE) * Description: Exposes a secure REST API endpoint so the new site can pull categories + post assignments. Install on OLD site only. * Version: 1.0 * Author: Migration Tool */ if (!defined('ABSPATH')) exit; class CategorySyncExporter { private $option_key = 'cat_sync_secret_key'; public function __construct() { add_action('rest_api_init', [$this, 'register_routes']); add_action('admin_menu', [$this, 'add_menu']); add_action('admin_init', [$this, 'handle_key_generation']); add_action('admin_enqueue_scripts', [$this, 'enqueue_styles']); } public function enqueue_styles($hook) { if ($hook !== 'toplevel_page_cat-sync-exporter') return; wp_enqueue_style('google-fonts-exporter', 'https://fonts.googleapis.com/css2?family=Syne:wght@400;700;800&family=DM+Mono:wght@400;500&display=swap', [], null); } public function add_menu() { add_menu_page( 'Category Sync Exporter', '📤 Cat Sync Exporter', 'manage_options', 'cat-sync-exporter', [$this, 'render_page'], 'dashicons-database-export', 80 ); } public function handle_key_generation() { if (isset($_POST['cat_sync_generate_key']) && check_admin_referer('cat_sync_generate')) { $key = 'cse_' . bin2hex(random_bytes(24)); update_option($this->option_key, $key); add_action('admin_notices', function() { echo '<div class="notice notice-success"><p>New secret key generated!</p></div>'; }); } } public function register_routes() { register_rest_route('cat-sync/v1', '/export', [ 'methods' => 'GET', 'callback' => [$this, 'export_data'], 'permission_callback' => [$this, 'verify_key'], ]); } public function verify_key($request) { $stored_key = get_option($this->option_key, ''); $provided = $request->get_header('X-Cat-Sync-Key') ?: $request->get_param('key'); return !empty($stored_key) && hash_equals($stored_key, (string) $provided); } public function export_data() { $categories = get_terms([ 'taxonomy' => 'category', 'hide_empty' => false, ]); $cat_data = []; foreach ($categories as $cat) { $cat_data[] = [ 'term_id' => $cat->term_id, 'name' => $cat->name, 'slug' => $cat->slug, 'description' => $cat->description, 'count' => $cat->count, ]; } // Get all posts with their categories $posts = get_posts([ 'numberposts' => -1, 'post_status' => ['publish', 'draft', 'private'], 'fields' => 'ids', ]); $post_category_map = []; foreach ($posts as $post_id) { $post_cats = wp_get_post_categories($post_id, ['fields' => 'slugs']); if (!empty($post_cats)) { $post_title = get_the_title($post_id); $post_slug = get_post_field('post_name', $post_id); $post_category_map[] = [ 'post_id' => $post_id, 'post_title' => $post_title, 'post_slug' => $post_slug, 'categories' => $post_cats, ]; } } return rest_ensure_response([ 'success' => true, 'site_url' => get_site_url(), 'exported_at' => current_time('mysql'), 'categories' => $cat_data, 'post_category_map' => $post_category_map, 'totals' => [ 'categories' => count($cat_data), 'posts' => count($post_category_map), ], ]); } public function render_page() { $secret_key = get_option($this->option_key, ''); $api_url = get_rest_url(null, 'cat-sync/v1/export'); ?> <style> * { box-sizing: border-box; margin: 0; padding: 0; } #cat-sync-exporter-wrap { font-family: 'Syne', sans-serif; background: #0a0a0f; min-height: 100vh; padding: 40px; color: #e8e8f0; } .cse-header { display: flex; align-items: center; gap: 16px; margin-bottom: 40px; } .cse-badge { background: linear-gradient(135deg, #ff6b35, #f7c59f); color: #0a0a0f; font-size: 11px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; padding: 4px 12px; border-radius: 20px; } .cse-header h1 { font-size: 32px; font-weight: 800; background: linear-gradient(90deg, #ff6b35, #f7c59f); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .cse-subtitle { color: #666; font-size: 14px; margin-top: 4px; font-family: 'DM Mono', monospace; } .cse-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; max-width: 1000px; } .cse-card { background: #12121a; border: 1px solid #1e1e2e; border-radius: 16px; padding: 28px; } .cse-card h2 { font-size: 16px; font-weight: 700; color: #ff6b35; margin-bottom: 16px; text-transform: uppercase; letter-spacing: 1px; } .cse-key-box { background: #0a0a0f; border: 1px solid #2a2a3a; border-radius: 10px; padding: 14px 16px; font-family: 'DM Mono', monospace; font-size: 13px; color: #f7c59f; word-break: break-all; line-height: 1.6; margin-bottom: 16px; } .cse-key-box.empty { color: #444; font-style: italic; } .cse-url-box { background: #0a0a0f; border: 1px solid #2a2a3a; border-radius: 10px; padding: 14px 16px; font-family: 'DM Mono', monospace; font-size: 12px; color: #8888cc; word-break: break-all; line-height: 1.6; margin-bottom: 16px; } .cse-btn { display: inline-block; padding: 10px 20px; border-radius: 8px; font-family: 'Syne', sans-serif; font-size: 13px; font-weight: 700; cursor: pointer; border: none; transition: opacity 0.2s; text-decoration: none; } .cse-btn:hover { opacity: 0.85; } .cse-btn-primary { background: linear-gradient(135deg, #ff6b35, #f7c59f); color: #0a0a0f; } .cse-btn-copy { background: #1e1e2e; color: #8888cc; border: 1px solid #2a2a3a; margin-left: 8px; } .cse-steps { counter-reset: steps; list-style: none; } .cse-steps li { counter-increment: steps; display: flex; gap: 14px; align-items: flex-start; margin-bottom: 16px; font-size: 14px; color: #aaa; line-height: 1.5; } .cse-steps li::before { content: counter(steps); background: #ff6b35; color: #0a0a0f; font-weight: 800; font-size: 11px; min-width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-top: 1px; } .cse-steps li strong { color: #e8e8f0; } .cse-stat { display: flex; justify-content: space-between; align-items: center; padding: 10px 0; border-bottom: 1px solid #1e1e2e; font-size: 14px; } .cse-stat:last-child { border-bottom: none; } .cse-stat-val { font-family: 'DM Mono', monospace; color: #ff6b35; font-weight: 700; font-size: 18px; } .cse-full { grid-column: span 2; } </style> <div id="cat-sync-exporter-wrap"> <div class="cse-header"> <div> <span class="cse-badge">Old Site</span> <h1>Category Sync — Exporter</h1> <p class="cse-subtitle">Exposes your categories via a secure API for the new site to consume</p> </div> </div> <div class="cse-grid"> <!-- Stats --> <div class="cse-card"> <h2>📊 Current Stats</h2> <?php $all_cats = get_terms(['taxonomy' => 'category', 'hide_empty' => false]); $all_posts = wp_count_posts(); ?> <div class="cse-stat"> <span>Total Categories</span> <span class="cse-stat-val"><?= count($all_cats) ?></span> </div> <div class="cse-stat"> <span>Published Posts</span> <span class="cse-stat-val"><?= $all_posts->publish ?></span> </div> <div class="cse-stat"> <span>API Status</span> <span class="cse-stat-val" style="color:<?= $secret_key ? '#4ade80' : '#f87171' ?>"><?= $secret_key ? '🟢 Ready' : '🔴 No Key' ?></span> </div> </div> <!-- Key Generation --> <div class="cse-card"> <h2>🔑 Secret Key</h2> <?php if ($secret_key): ?> <div class="cse-key-box"><?= esc_html($secret_key) ?></div> <button class="cse-btn cse-btn-copy" onclick="navigator.clipboard.writeText('<?= esc_js($secret_key) ?>');this.textContent='Copied!'">📋 Copy Key</button> <?php else: ?> <div class="cse-key-box empty">No key generated yet. Generate one below.</div> <?php endif; ?> <br><br> <form method="post"> <?php wp_nonce_field('cat_sync_generate'); ?> <button type="submit" name="cat_sync_generate_key" class="cse-btn cse-btn-primary"> <?= $secret_key ? '🔄 Regenerate Key' : '⚡ Generate Secret Key' ?> </button> </form> </div> <!-- API Endpoint --> <div class="cse-card cse-full"> <h2>🌐 API Endpoint (copy to new site)</h2> <div class="cse-url-box"><?= esc_html($api_url) ?></div> <button class="cse-btn cse-btn-copy" onclick="navigator.clipboard.writeText('<?= esc_js($api_url) ?>');this.textContent='Copied!'">📋 Copy URL</button> <br><br> <h2 style="margin-top:8px;">📋 How to Use</h2> <ul class="cse-steps" style="margin-top:16px;"> <li><span><strong>Generate a secret key</strong> above — copy it</span></li> <li><span>Copy the <strong>API Endpoint URL</strong> above</span></li> <li><span>Go to your <strong>new site</strong> → install the <strong>Category Sync Importer</strong> plugin</span></li> <li><span>Paste the URL + Key into the importer and click <strong>Run Sync</strong></span></li> <li><span>All done! Posts will be auto-reassigned to correct categories 🎉</span></li> </ul> </div> </div> </div> <?php } } new CategorySyncExporter();
Save
Close
Exit & Reset
Text mode: syntax highlighting auto-detects file type.
Directory Contents
Dirs: 0 × Files: 1
Delete Selected
Select All
Select None
Sort:
Name
Size
Modified
Enable drag-to-move
Name
Size
Perms
Modified
Actions
category-sync-exporter.php
11.91 KB
lrw-r--r--
2026-04-06 06:24:31
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Zip Selected
If ZipArchive is unavailable, a
.tar
will be created (no compression).