From e2c0d3d0fc24fb3c5dd5fde4415a25d4dc4ab89b Mon Sep 17 00:00:00 2001 From: alorig <220087330+alorig@users.noreply.github.com> Date: Sat, 22 Nov 2025 20:29:49 +0500 Subject: [PATCH] fd --- igy8-wp-plugin/admin/assets/css/admin.css | 627 ----- igy8-wp-plugin/admin/assets/js/admin.js | 188 -- igy8-wp-plugin/admin/assets/js/post-editor.js | 200 -- igy8-wp-plugin/admin/class-admin-columns.php | 306 --- igy8-wp-plugin/admin/class-admin.php | 621 ----- .../admin/class-post-meta-boxes.php | 469 ---- igy8-wp-plugin/admin/settings.php | 771 ------ igy8-wp-plugin/data/link-graph.php | 192 -- igy8-wp-plugin/data/semantic-mapping.php | 225 -- igy8-wp-plugin/data/site-collection.php | 588 ----- igy8-wp-plugin/data/woocommerce.php | 226 -- igy8-wp-plugin/docs/AUTHENTICATION-AUDIT.md | 114 - igy8-wp-plugin/docs/README.md | 396 --- igy8-wp-plugin/docs/SYNC-DATA-FLOW-DIAGRAM.md | 356 --- .../docs/WORDPRESS-PLUGIN-INTEGRATION.md | 2135 ----------------- igy8-wp-plugin/igny8-bridge.php | 184 -- igy8-wp-plugin/includes/class-igny8-api.php | 486 ---- .../includes/class-igny8-link-queue.php | 202 -- .../includes/class-igny8-rest-api.php | 444 ---- igy8-wp-plugin/includes/class-igny8-site.php | 118 - .../includes/class-igny8-webhook-logs.php | 147 -- .../includes/class-igny8-webhooks.php | 381 --- igy8-wp-plugin/includes/functions.php | 828 ------- igy8-wp-plugin/languages/igny8-bridge.pot | 100 - igy8-wp-plugin/sync/hooks.php | 42 - igy8-wp-plugin/sync/igny8-to-wp.php | 807 ------- igy8-wp-plugin/sync/post-sync.php | 363 --- igy8-wp-plugin/sync/taxonomy-sync.php | 425 ---- .../tests/test-api-authentication.php | 116 - igy8-wp-plugin/tests/test-revoke-api-key.php | 28 - igy8-wp-plugin/tests/test-site-metadata.php | 36 - igy8-wp-plugin/tests/test-sync-structure.php | 163 -- igy8-wp-plugin/uninstall.php | 53 - 33 files changed, 12337 deletions(-) delete mode 100644 igy8-wp-plugin/admin/assets/css/admin.css delete mode 100644 igy8-wp-plugin/admin/assets/js/admin.js delete mode 100644 igy8-wp-plugin/admin/assets/js/post-editor.js delete mode 100644 igy8-wp-plugin/admin/class-admin-columns.php delete mode 100644 igy8-wp-plugin/admin/class-admin.php delete mode 100644 igy8-wp-plugin/admin/class-post-meta-boxes.php delete mode 100644 igy8-wp-plugin/admin/settings.php delete mode 100644 igy8-wp-plugin/data/link-graph.php delete mode 100644 igy8-wp-plugin/data/semantic-mapping.php delete mode 100644 igy8-wp-plugin/data/site-collection.php delete mode 100644 igy8-wp-plugin/data/woocommerce.php delete mode 100644 igy8-wp-plugin/docs/AUTHENTICATION-AUDIT.md delete mode 100644 igy8-wp-plugin/docs/README.md delete mode 100644 igy8-wp-plugin/docs/SYNC-DATA-FLOW-DIAGRAM.md delete mode 100644 igy8-wp-plugin/docs/WORDPRESS-PLUGIN-INTEGRATION.md delete mode 100644 igy8-wp-plugin/igny8-bridge.php delete mode 100644 igy8-wp-plugin/includes/class-igny8-api.php delete mode 100644 igy8-wp-plugin/includes/class-igny8-link-queue.php delete mode 100644 igy8-wp-plugin/includes/class-igny8-rest-api.php delete mode 100644 igy8-wp-plugin/includes/class-igny8-site.php delete mode 100644 igy8-wp-plugin/includes/class-igny8-webhook-logs.php delete mode 100644 igy8-wp-plugin/includes/class-igny8-webhooks.php delete mode 100644 igy8-wp-plugin/includes/functions.php delete mode 100644 igy8-wp-plugin/languages/igny8-bridge.pot delete mode 100644 igy8-wp-plugin/sync/hooks.php delete mode 100644 igy8-wp-plugin/sync/igny8-to-wp.php delete mode 100644 igy8-wp-plugin/sync/post-sync.php delete mode 100644 igy8-wp-plugin/sync/taxonomy-sync.php delete mode 100644 igy8-wp-plugin/tests/test-api-authentication.php delete mode 100644 igy8-wp-plugin/tests/test-revoke-api-key.php delete mode 100644 igy8-wp-plugin/tests/test-site-metadata.php delete mode 100644 igy8-wp-plugin/tests/test-sync-structure.php delete mode 100644 igy8-wp-plugin/uninstall.php diff --git a/igy8-wp-plugin/admin/assets/css/admin.css b/igy8-wp-plugin/admin/assets/css/admin.css deleted file mode 100644 index 3ab514a8..00000000 --- a/igy8-wp-plugin/admin/assets/css/admin.css +++ /dev/null @@ -1,627 +0,0 @@ -/** - * Admin Styles - IGNY8 Bridge - * Updated with IGNY8 brand colors and modern UI - * - * @package Igny8Bridge - */ - -/* ============================================ - IGNY8 Brand Colors - ============================================ */ -:root { - --igny8-primary: #3B82F6; - --igny8-primary-hover: #2563EB; - --igny8-success: #10B981; - --igny8-warning: #F59E0B; - --igny8-error: #EF4444; - --igny8-purple: #8B5CF6; - --igny8-gray: #6B7280; - --igny8-light-gray: #F3F4F6; -} - -/* ============================================ - Container & Layout - ============================================ */ - -.igny8-settings-container { - max-width: 1400px; -} - -.igny8-settings-card { - background: #fff; - border: 1px solid #E5E7EB; - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); - padding: 24px; - margin: 24px 0; - border-radius: 8px; -} - -.igny8-settings-card h2 { - margin-top: 0; - padding-bottom: 12px; - border-bottom: 2px solid var(--igny8-light-gray); - color: #111827; - font-size: 20px; - font-weight: 600; -} - -/* ============================================ - Toggle Switch - ============================================ */ - -.igny8-toggle-wrapper { - display: flex; - align-items: center; - gap: 12px; -} - -.igny8-toggle-input { - position: relative; - width: 48px; - height: 24px; - -webkit-appearance: none; - appearance: none; - background: var(--igny8-gray); - outline: none; - border-radius: 24px; - cursor: pointer; - transition: 0.3s; -} - -.igny8-toggle-input:checked { - background: var(--igny8-success); -} - -.igny8-toggle-input::before { - content: ''; - position: absolute; - width: 20px; - height: 20px; - border-radius: 50%; - top: 2px; - left: 2px; - background: #fff; - transition: 0.3s; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); -} - -.igny8-toggle-input:checked::before { - left: 26px; -} - -/* ============================================ - Sync Operations Grid - ============================================ */ - -.igny8-sync-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 20px; - margin-top: 20px; -} - -.igny8-sync-card { - background: #fff; - border: 2px solid #E5E7EB; - border-radius: 12px; - padding: 24px; - transition: all 0.3s ease; -} - -.igny8-sync-card:hover { - border-color: var(--igny8-primary); - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); - transform: translateY(-2px); -} - -.igny8-sync-card-highlight { - border-color: var(--igny8-primary); - background: linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%); -} - -.igny8-sync-icon { - width: 48px; - height: 48px; - background: var(--igny8-primary); - border-radius: 10px; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 16px; - color: white; -} - -.igny8-sync-card h3 { - margin: 0 0 8px 0; - font-size: 16px; - font-weight: 600; - color: #111827; -} - -.igny8-sync-description { - font-size: 14px; - color: #6B7280; - line-height: 1.5; - margin-bottom: 12px; -} - -.igny8-sync-meta { - font-size: 12px; - color: #9CA3AF; - margin-bottom: 16px; -} - -.igny8-sync-time { - display: inline-flex; - align-items: center; - gap: 4px; -} - -.igny8-sync-button { - width: 100%; - height: 40px; - background: var(--igny8-primary) !important; - border-color: var(--igny8-primary) !important; - color: white !important; - font-weight: 500 !important; - border-radius: 8px !important; - transition: all 0.2s ease !important; -} - -.igny8-sync-button:hover:not(:disabled) { - background: var(--igny8-primary-hover) !important; - border-color: var(--igny8-primary-hover) !important; - transform: translateY(-1px); - box-shadow: 0 4px 6px -1px rgba(59, 130, 246, 0.3); -} - -.igny8-sync-button:disabled { - opacity: 0.5 !important; - cursor: not-allowed !important; -} - -.button-loading { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; -} - -/* ============================================ - Statistics Cards - ============================================ */ - -.igny8-stats-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - gap: 20px; - margin-top: 20px; -} - -.igny8-stat-card { - background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%); - border: 1px solid #E5E7EB; - border-radius: 12px; - padding: 20px; - display: flex; - align-items: flex-start; - gap: 16px; - transition: all 0.3s ease; -} - -.igny8-stat-card:hover { - box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); - transform: translateY(-2px); -} - -.igny8-stat-icon { - width: 48px; - height: 48px; - border-radius: 10px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.igny8-stat-content { - flex: 1; -} - -.igny8-stat-label { - font-size: 12px; - color: #6B7280; - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 4px; - font-weight: 500; -} - -.igny8-stat-value { - font-size: 28px; - font-weight: 700; - color: #111827; - line-height: 1.2; - margin-bottom: 4px; -} - -.igny8-stat-meta { - font-size: 12px; - color: #9CA3AF; -} - -/* ============================================ - Semantic Summary - ============================================ */ - -.igny8-semantic-summary { - margin-top: 24px; - padding: 20px; - background: linear-gradient(135deg, #F3E8FF 0%, #E9D5FF 100%); - border-radius: 12px; - border: 1px solid #D8B4FE; -} - -.igny8-semantic-summary h3 { - margin: 0 0 16px 0; - font-size: 16px; - font-weight: 600; - color: #6B21A8; -} - -.igny8-semantic-stats { - display: flex; - gap: 32px; - flex-wrap: wrap; -} - -.igny8-semantic-stat { - display: flex; - flex-direction: column; - gap: 4px; -} - -.igny8-semantic-stat .value { - font-size: 24px; - font-weight: 700; - color: #7C3AED; -} - -.igny8-semantic-stat .label { - font-size: 12px; - color: #8B5CF6; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -/* ============================================ - Status Indicators - ============================================ */ - -.igny8-status-connected { - color: var(--igny8-success); - font-weight: 600; -} - -.igny8-status-disconnected { - color: var(--igny8-error); - font-weight: 600; -} -/* ============================================ - API Connection Form - ============================================ */ - -.igny8-api-connection-form { - background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%); - border: 2px solid #E5E7EB; - border-radius: 12px; - padding: 32px; - margin: 0 0 24px 0; -} - -.igny8-api-form-group { - margin-bottom: 20px; -} - -.igny8-api-form-group label { - display: block; - margin-bottom: 8px; - font-weight: 600; - color: #111827; - font-size: 14px; -} - -.igny8-api-form-group input[type="text"], -.igny8-api-form-group input[type="password"] { - width: 100%; - padding: 12px 14px; - border: 1px solid #D1D5DB; - border-radius: 8px; - font-size: 14px; - transition: all 0.2s ease; - font-family: 'Courier New', monospace; - background-color: #fff; -} - -.igny8-api-form-group input[type="text"]:focus, -.igny8-api-form-group input[type="password"]:focus { - outline: none; - border-color: var(--igny8-primary); - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); -} - -.igny8-api-form-group input[type="text"]:disabled { - background-color: #F3F4F6; - color: #9CA3AF; - cursor: not-allowed; -} - -.igny8-api-form-description { - font-size: 13px; - color: #6B7280; - margin-top: 6px; - line-height: 1.5; -} - -.igny8-api-form-description a { - color: var(--igny8-primary); - text-decoration: none; - font-weight: 500; -} - -.igny8-api-form-description a:hover { - text-decoration: underline; -} - -.igny8-connection-actions { - display: flex; - gap: 12px; - flex-wrap: wrap; - margin-top: 24px; -} - -.igny8-connection-actions .button { - border-radius: 8px; - padding: 10px 20px; - font-weight: 500; - border: none; - cursor: pointer; - transition: all 0.2s ease; - height: auto; -} - -.igny8-connection-actions .button-primary { - background: var(--igny8-primary) !important; - color: white !important; -} - -.igny8-connection-actions .button-primary:hover { - background: var(--igny8-primary-hover) !important; - transform: translateY(-1px); - box-shadow: 0 4px 6px -1px rgba(59, 130, 246, 0.3); -} - -.igny8-connection-actions .button-secondary { - background: #E5E7EB !important; - color: #111827 !important; -} - -.igny8-connection-actions .button-secondary:hover { - background: #D1D5DB !important; -} - -.igny8-connection-status-display { - padding: 20px; - background: linear-gradient(135deg, #F9FAFB 0%, #F3F4F6 100%); - border: 1px solid #E5E7EB; - border-radius: 12px; - margin-bottom: 20px; -} - -.igny8-connection-status-display .igny8-status-label { - font-size: 12px; - text-transform: uppercase; - letter-spacing: 0.05em; - color: #6B7280; - margin-bottom: 8px; - font-weight: 500; -} - -.igny8-connection-status-display .igny8-status-value { - font-size: 20px; - font-weight: 700; - display: flex; - align-items: center; - gap: 8px; -} - -.igny8-status-indicator { - width: 12px; - height: 12px; - border-radius: 50%; - display: inline-block; -} - -.igny8-status-indicator.connected { - background-color: var(--igny8-success); -} - -.igny8-status-indicator.disconnected { - background-color: var(--igny8-gray); -} - -.igny8-api-key-display { - display: flex; - align-items: center; - gap: 12px; - padding: 12px; - background-color: #F3F4F6; - border-radius: 8px; - word-break: break-all; -} - -.igny8-api-key-mask { - font-family: 'Courier New', monospace; - color: #6B7280; - font-size: 14px; -} - -/* ============================================ - Diagnostics - ============================================ */ - -.igny8-diagnostics-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); - gap: 16px; - margin-top: 20px; -} - -.igny8-diagnostic-item { - padding: 16px; - background: linear-gradient(135deg, #F9FAFB 0%, #F3F4F6 100%); - border: 1px solid #E5E7EB; - border-radius: 8px; - transition: all 0.2s ease; -} - -.igny8-diagnostic-item:hover { - border-color: var(--igny8-primary); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); -} - -.igny8-diagnostic-label { - font-size: 11px; - text-transform: uppercase; - letter-spacing: 0.05em; - color: #6B7280; - margin-bottom: 8px; - font-weight: 500; -} - -.igny8-diagnostic-value { - font-size: 16px; - font-weight: 600; - color: #111827; -} - -.igny8-diagnostic-item .description { - margin: 6px 0 0; - color: #9CA3AF; - font-size: 12px; -} - -/* ============================================ - Sync Status Messages - ============================================ */ - -.igny8-sync-status { - margin-top: 20px; - padding: 16px; - border-radius: 8px; - display: none; - font-size: 14px; -} - -.igny8-sync-status.igny8-sync-status-success { - background-color: #D1FAE5; - border: 1px solid #6EE7B7; - color: #065F46; - display: block; -} - -.igny8-sync-status.igny8-sync-status-error { - background-color: #FEE2E2; - border: 1px solid #FCA5A5; - color: #991B1B; - display: block; -} - -.igny8-sync-status.igny8-sync-status-loading { - background-color: #DBEAFE; - border: 1px solid #93C5FD; - color: #1E40AF; - display: block; -} - -/* ============================================ - Loading States - ============================================ */ - -.igny8-loading { - opacity: 0.6; - pointer-events: none; -} - -@keyframes igny8-spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} - -/* ============================================ - Messages & Notifications - ============================================ */ - -.igny8-message { - padding: 16px; - margin: 15px 0; - border-left: 4px solid; - background: #fff; - border-radius: 4px; -} - -.igny8-message.igny8-message-success { - border-color: var(--igny8-success); - background-color: #F0FDF4; - color: #065F46; -} - -.igny8-message.igny8-message-error { - border-color: var(--igny8-error); - background-color: #FEF2F2; - color: #991B1B; -} - -.igny8-message.igny8-message-info { - border-color: var(--igny8-primary); - background-color: #EFF6FF; - color: #1E40AF; -} - -.igny8-message.igny8-message-warning { - border-color: var(--igny8-warning); - background-color: #FFFBEB; - color: #92400E; -} - -/* ============================================ - Responsive - ============================================ */ - -@media (max-width: 782px) { - .igny8-sync-grid { - grid-template-columns: 1fr; - } - - .igny8-stats-grid { - grid-template-columns: 1fr; - } - - .igny8-diagnostics-grid { - grid-template-columns: 1fr; - } -} - -@media (max-width: 600px) { - .igny8-settings-card { - padding: 16px; - } - - .igny8-sync-card { - padding: 16px; - } - - .igny8-stat-card { - flex-direction: column; - } -} diff --git a/igy8-wp-plugin/admin/assets/js/admin.js b/igy8-wp-plugin/admin/assets/js/admin.js deleted file mode 100644 index fe4fe4f7..00000000 --- a/igy8-wp-plugin/admin/assets/js/admin.js +++ /dev/null @@ -1,188 +0,0 @@ -/** - * Admin JavaScript - * - * @package Igny8Bridge - */ - -(function($) { - 'use strict'; - - $(document).ready(function() { - // Test connection button - $('#igny8-test-connection').on('click', function() { - var $button = $(this); - var $result = $('#igny8-test-result'); - - $button.prop('disabled', true).addClass('igny8-loading'); - $result.html('Testing...'); - - $.ajax({ - url: igny8Admin.ajaxUrl, - type: 'POST', - data: { - action: 'igny8_test_connection', - nonce: igny8Admin.nonce - }, - success: function(response) { - if (response.success) { - $result.html('✓ ' + (response.data.message || 'Connection successful') + ''); - } else { - var errorMsg = response.data.message || 'Connection failed'; - var httpStatus = response.data.http_status || ''; - var fullMsg = errorMsg; - if (httpStatus) { - fullMsg += ' (HTTP ' + httpStatus + ')'; - } - $result.html('✗ ' + fullMsg + ''); - - // Log full error to console for debugging - console.error('IGNY8 Connection Test Failed:', response.data); - } - }, - error: function(xhr, status, error) { - $result.html('✗ Request failed: ' + error + ''); - console.error('IGNY8 AJAX Error:', xhr, status, error); - }, - complete: function() { - $button.prop('disabled', false).removeClass('igny8-loading'); - } - }); - }); - - // Sync posts to IGNY8 - $('#igny8-sync-posts').on('click', function() { - igny8TriggerSync('igny8_sync_posts', 'Syncing posts to IGNY8...'); - }); - - // Sync taxonomies - $('#igny8-sync-taxonomies').on('click', function() { - igny8TriggerSync('igny8_sync_taxonomies', 'Syncing taxonomies...'); - }); - - // Sync from IGNY8 - $('#igny8-sync-from-igny8').on('click', function() { - igny8TriggerSync('igny8_sync_from_igny8', 'Syncing from IGNY8...'); - }); - - // Collect and send site data - $('#igny8-collect-site-data').on('click', function() { - igny8TriggerSync('igny8_collect_site_data', 'Collecting and sending site data...'); - }); - - // Load sync statistics - igny8LoadStats(); - - // Handle row action links - $(document).on('click', '.igny8-action-link', function(e) { - e.preventDefault(); - - var $link = $(this); - var postId = $link.data('post-id'); - var action = $link.data('action'); - - if (!postId) { - return; - } - - if (!confirm('Are you sure you want to ' + (action === 'send' ? 'send' : 'update') + ' this post to IGNY8?')) { - return; - } - - $link.text('Processing...').prop('disabled', true); - - $.ajax({ - url: igny8Admin.ajaxUrl, - type: 'POST', - data: { - action: 'igny8_send_to_igny8', - post_id: postId, - action_type: action, - nonce: igny8Admin.nonce - }, - success: function(response) { - if (response.success) { - alert(response.data.message || 'Success!'); - location.reload(); - } else { - alert(response.data.message || 'Failed to send to IGNY8'); - $link.text(action === 'send' ? 'Send to IGNY8' : 'Update in IGNY8').prop('disabled', false); - } - }, - error: function() { - alert('Request failed'); - $link.text(action === 'send' ? 'Send to IGNY8' : 'Update in IGNY8').prop('disabled', false); - } - }); - }); - }); - - /** - * Trigger sync operation - */ - function igny8TriggerSync(action, message) { - var $status = $('#igny8-sync-status'); - var $button = $('#' + action.replace('igny8_', 'igny8-')); - - $status.removeClass('igny8-sync-status-success igny8-sync-status-error') - .addClass('igny8-sync-status-loading') - .html('' + message); - - $button.prop('disabled', true).addClass('igny8-loading'); - - $.ajax({ - url: igny8Admin.ajaxUrl, - type: 'POST', - data: { - action: action, - nonce: igny8Admin.nonce - }, - success: function(response) { - if (response.success) { - $status.removeClass('igny8-sync-status-loading') - .addClass('igny8-sync-status-success') - .html('✓ ' + (response.data.message || 'Operation completed successfully')); - - // Reload stats - igny8LoadStats(); - } else { - $status.removeClass('igny8-sync-status-loading') - .addClass('igny8-sync-status-error') - .html('✗ ' + (response.data.message || 'Operation failed')); - } - }, - error: function() { - $status.removeClass('igny8-sync-status-loading') - .addClass('igny8-sync-status-error') - .html('✗ Request failed'); - }, - complete: function() { - $button.prop('disabled', false).removeClass('igny8-loading'); - } - }); - } - - /** - * Load sync statistics - */ - function igny8LoadStats() { - $.ajax({ - url: igny8Admin.ajaxUrl, - type: 'POST', - data: { - action: 'igny8_get_stats', - nonce: igny8Admin.nonce - }, - success: function(response) { - if (response.success && response.data) { - if (response.data.synced_posts !== undefined) { - $('#igny8-stat-posts').text(response.data.synced_posts); - } - if (response.data.last_sync) { - $('#igny8-stat-last-sync').text(response.data.last_sync); - } - } - } - }); - } -})(jQuery); - diff --git a/igy8-wp-plugin/admin/assets/js/post-editor.js b/igy8-wp-plugin/admin/assets/js/post-editor.js deleted file mode 100644 index 2be154c1..00000000 --- a/igy8-wp-plugin/admin/assets/js/post-editor.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Post Editor JavaScript - * - * Handles AJAX interactions for Planner and Optimizer meta boxes - * - * @package Igny8Bridge - */ - -(function($) { - 'use strict'; - - $(document).ready(function() { - // Fetch Planner Brief - $('#igny8-fetch-brief').on('click', function() { - var $button = $(this); - var $message = $('#igny8-planner-brief-message'); - var postId = $button.data('post-id'); - var taskId = $button.data('task-id'); - - $button.prop('disabled', true).text('Fetching...'); - $message.hide().removeClass('notice-success notice-error'); - - $.ajax({ - url: igny8PostEditor.ajaxUrl, - type: 'POST', - data: { - action: 'igny8_fetch_planner_brief', - nonce: igny8PostEditor.nonce, - post_id: postId, - task_id: taskId - }, - success: function(response) { - if (response.success) { - $message.addClass('notice notice-success inline') - .html('
' + response.data.message + '
') - .show(); - - // Reload page to show updated brief - setTimeout(function() { - location.reload(); - }, 1000); - } else { - $message.addClass('notice notice-error inline') - .html('' + (response.data.message || 'Failed to fetch brief') + '
') - .show(); - $button.prop('disabled', false).text('Fetch Brief'); - } - }, - error: function() { - $message.addClass('notice notice-error inline') - .html('Request failed
') - .show(); - $button.prop('disabled', false).text('Fetch Brief'); - } - }); - }); - - // Refresh Planner Task - $('#igny8-refresh-task').on('click', function() { - var $button = $(this); - var $message = $('#igny8-planner-brief-message'); - var postId = $button.data('post-id'); - var taskId = $button.data('task-id'); - - if (!confirm('Are you sure you want to request a refresh of this task from IGNY8 Planner?')) { - return; - } - - $button.prop('disabled', true).text('Requesting...'); - $message.hide().removeClass('notice-success notice-error'); - - $.ajax({ - url: igny8PostEditor.ajaxUrl, - type: 'POST', - data: { - action: 'igny8_refresh_planner_task', - nonce: igny8PostEditor.nonce, - post_id: postId, - task_id: taskId - }, - success: function(response) { - if (response.success) { - $message.addClass('notice notice-success inline') - .html('' + response.data.message + '
') - .show(); - } else { - $message.addClass('notice notice-error inline') - .html('' + (response.data.message || 'Failed to request refresh') + '
') - .show(); - } - $button.prop('disabled', false).text('Request Refresh'); - }, - error: function() { - $message.addClass('notice notice-error inline') - .html('Request failed
') - .show(); - $button.prop('disabled', false).text('Request Refresh'); - } - }); - }); - - // Create Optimizer Job - $('#igny8-create-optimizer-job').on('click', function() { - var $button = $(this); - var $message = $('#igny8-optimizer-message'); - var postId = $button.data('post-id'); - var taskId = $button.data('task-id'); - - if (!confirm('Create a new optimizer job for this post?')) { - return; - } - - $button.prop('disabled', true).text('Creating...'); - $message.hide().removeClass('notice-success notice-error'); - - $.ajax({ - url: igny8PostEditor.ajaxUrl, - type: 'POST', - data: { - action: 'igny8_create_optimizer_job', - nonce: igny8PostEditor.nonce, - post_id: postId, - task_id: taskId, - job_type: 'audit', - priority: 'normal' - }, - success: function(response) { - if (response.success) { - $message.addClass('notice notice-success inline') - .html('' + response.data.message + '
') - .show(); - - // Reload page to show updated status - setTimeout(function() { - location.reload(); - }, 1000); - } else { - $message.addClass('notice notice-error inline') - .html('' + (response.data.message || 'Failed to create job') + '
') - .show(); - $button.prop('disabled', false).text('Request Optimization'); - } - }, - error: function() { - $message.addClass('notice notice-error inline') - .html('Request failed
') - .show(); - $button.prop('disabled', false).text('Request Optimization'); - } - }); - }); - - // Check Optimizer Status - $('#igny8-check-optimizer-status').on('click', function() { - var $button = $(this); - var $message = $('#igny8-optimizer-message'); - var postId = $button.data('post-id'); - var jobId = $button.data('job-id'); - - $button.prop('disabled', true).text('Checking...'); - $message.hide().removeClass('notice-success notice-error'); - - $.ajax({ - url: igny8PostEditor.ajaxUrl, - type: 'POST', - data: { - action: 'igny8_get_optimizer_status', - nonce: igny8PostEditor.nonce, - post_id: postId, - job_id: jobId - }, - success: function(response) { - if (response.success) { - $message.addClass('notice notice-success inline') - .html('Status: ' + response.data.status + '
') - .show(); - - // Reload page to show updated status - setTimeout(function() { - location.reload(); - }, 1000); - } else { - $message.addClass('notice notice-error inline') - .html('' + (response.data.message || 'Failed to get status') + '
') - .show(); - } - $button.prop('disabled', false).text('Check Status'); - }, - error: function() { - $message.addClass('notice notice-error inline') - .html('Request failed
') - .show(); - $button.prop('disabled', false).text('Check Status'); - } - }); - }); - }); - -})(jQuery); - diff --git a/igy8-wp-plugin/admin/class-admin-columns.php b/igy8-wp-plugin/admin/class-admin-columns.php deleted file mode 100644 index 06916a8b..00000000 --- a/igy8-wp-plugin/admin/class-admin-columns.php +++ /dev/null @@ -1,306 +0,0 @@ -'; - echo esc_html($taxonomy); - echo ''; - } else { - echo '—'; - } - } - - /** - * Render attribute column - * - * @param int $post_id Post ID - */ - private function render_attribute_column($post_id) { - $attribute = get_post_meta($post_id, '_igny8_attribute_id', true); - - if ($attribute) { - echo ''; - echo esc_html($attribute); - echo ''; - } else { - echo '—'; - } - } - - /** - * Add custom columns - * - * @param array $columns Existing columns - * @return array Modified columns - */ - public function add_columns($columns) { - $new_columns = array(); - - foreach ($columns as $key => $value) { - $new_columns[$key] = $value; - - if ($key === 'title') { - $new_columns['igny8_taxonomy'] = __('Taxonomy', 'igny8-bridge'); - $new_columns['igny8_attribute'] = __('Attribute', 'igny8-bridge'); - } - } - - return $new_columns; - } - - /** - * Render column content - * - * @param string $column_name Column name - * @param int $post_id Post ID - */ - public function render_column_content($column_name, $post_id) { - switch ($column_name) { - case 'igny8_taxonomy': - $this->render_taxonomy_column($post_id); - break; - - case 'igny8_attribute': - $this->render_attribute_column($post_id); - break; - } - } - - /** - * Make columns sortable - * - * @param array $columns Sortable columns - * @return array Modified columns - */ - public function make_columns_sortable($columns) { - $columns['igny8_source'] = 'igny8_source'; - return $columns; - } - - /** - * Add row actions - * - * @param array $actions Existing actions - * @param WP_Post $post Post object - * @return array Modified actions - */ - public function add_row_actions($actions, $post) { - // Only add for published posts - if ($post->post_status !== 'publish') { - return $actions; - } - - // Check if already synced to IGNY8 - $task_id = get_post_meta($post->ID, '_igny8_task_id', true); - - if ($task_id) { - // Already synced - show update action - $actions['igny8_update'] = sprintf( - '%s', - '#', - $post->ID, - __('Update in IGNY8', 'igny8-bridge') - ); - } else { - // Not synced - show send action - $actions['igny8_send'] = sprintf( - '%s', - '#', - $post->ID, - __('Send to IGNY8', 'igny8-bridge') - ); - } - - return $actions; - } - - /** - * Send post to IGNY8 (AJAX handler) - */ - public static function send_to_igny8() { - check_ajax_referer('igny8_admin_nonce', 'nonce'); - - if (!current_user_can('edit_posts')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; - $action = isset($_POST['action_type']) ? sanitize_text_field($_POST['action_type']) : 'send'; - - if (!$post_id) { - wp_send_json_error(array('message' => 'Invalid post ID')); - } - - $post = get_post($post_id); - if (!$post) { - wp_send_json_error(array('message' => 'Post not found')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $api = new Igny8API(); - - if (!$api->is_authenticated()) { - wp_send_json_error(array('message' => 'Not authenticated with IGNY8')); - } - - $site_id = get_option('igny8_site_id'); - if (!$site_id) { - wp_send_json_error(array('message' => 'Site ID not set')); - } - - // Prepare post data for IGNY8 - $post_data = array( - 'title' => $post->post_title, - 'content' => $post->post_content, - 'excerpt' => $post->post_excerpt, - 'status' => $post->post_status === 'publish' ? 'completed' : 'draft', - 'post_type' => $post->post_type, - 'url' => get_permalink($post_id), - 'wordpress_post_id' => $post_id - ); - - // Get categories - $categories = wp_get_post_categories($post_id, array('fields' => 'names')); - if (!empty($categories)) { - $post_data['categories'] = $categories; - } - - // Get tags - $tags = wp_get_post_tags($post_id, array('fields' => 'names')); - if (!empty($tags)) { - $post_data['tags'] = $tags; - } - - // Get featured image - $featured_image_id = get_post_thumbnail_id($post_id); - if ($featured_image_id) { - $post_data['featured_image'] = wp_get_attachment_image_url($featured_image_id, 'full'); - } - - // Get sectors and clusters - $sectors = wp_get_post_terms($post_id, 'igny8_sectors', array('fields' => 'ids')); - $clusters = wp_get_post_terms($post_id, 'igny8_clusters', array('fields' => 'ids')); - - if (!empty($sectors)) { - // Get IGNY8 sector IDs from term meta - $igny8_sector_ids = array(); - foreach ($sectors as $term_id) { - $igny8_sector_id = get_term_meta($term_id, '_igny8_sector_id', true); - if ($igny8_sector_id) { - $igny8_sector_ids[] = $igny8_sector_id; - } - } - if (!empty($igny8_sector_ids)) { - $post_data['sector_id'] = $igny8_sector_ids[0]; // Use first sector - } - } - - if (!empty($clusters)) { - // Get IGNY8 cluster IDs from term meta - $igny8_cluster_ids = array(); - foreach ($clusters as $term_id) { - $igny8_cluster_id = get_term_meta($term_id, '_igny8_cluster_id', true); - if ($igny8_cluster_id) { - $igny8_cluster_ids[] = $igny8_cluster_id; - } - } - if (!empty($igny8_cluster_ids)) { - $post_data['cluster_id'] = $igny8_cluster_ids[0]; // Use first cluster - } - } - - // Check if post already has task ID - $existing_task_id = get_post_meta($post_id, '_igny8_task_id', true); - - if ($existing_task_id && $action === 'update') { - // Update existing task - $response = $api->put("/writer/tasks/{$existing_task_id}/", $post_data); - } else { - // Create new task - $response = $api->post("/writer/tasks/", $post_data); - } - - if ($response['success']) { - $task_id = $response['data']['id'] ?? $existing_task_id; - - // Store task ID - update_post_meta($post_id, '_igny8_task_id', $task_id); - update_post_meta($post_id, '_igny8_last_synced', current_time('mysql')); - - wp_send_json_success(array( - 'message' => $action === 'update' ? 'Post updated in IGNY8' : 'Post sent to IGNY8', - 'task_id' => $task_id - )); - } else { - wp_send_json_error(array( - 'message' => 'Failed to send to IGNY8: ' . ($response['error'] ?? 'Unknown error') - )); - } - } -} - -// Initialize -new Igny8AdminColumns(); - -// Register AJAX handler -add_action('wp_ajax_igny8_send_to_igny8', array('Igny8AdminColumns', 'send_to_igny8')); - diff --git a/igy8-wp-plugin/admin/class-admin.php b/igy8-wp-plugin/admin/class-admin.php deleted file mode 100644 index c3dde542..00000000 --- a/igy8-wp-plugin/admin/class-admin.php +++ /dev/null @@ -1,621 +0,0 @@ - 'boolean', - 'sanitize_callback' => array($this, 'sanitize_boolean'), - 'default' => 1 - )); - - register_setting('igny8_bridge_connection', 'igny8_connection_enabled', array( - 'type' => 'boolean', - 'sanitize_callback' => array($this, 'sanitize_boolean'), - 'default' => 1 - )); - - register_setting('igny8_bridge_controls', 'igny8_enabled_post_types', array( - 'type' => 'array', - 'sanitize_callback' => array($this, 'sanitize_post_types'), - 'default' => array_keys(igny8_get_supported_post_types()) - )); - - register_setting('igny8_bridge_controls', 'igny8_enabled_taxonomies', array( - 'type' => 'array', - 'sanitize_callback' => array($this, 'sanitize_taxonomies'), - 'default' => array('category', 'post_tag', 'product_cat', 'igny8_sectors', 'igny8_clusters') - )); - - register_setting('igny8_bridge_controls', 'igny8_enable_woocommerce', array( - 'type' => 'boolean', - 'sanitize_callback' => array($this, 'sanitize_boolean'), - 'default' => class_exists('WooCommerce') ? 1 : 0 - )); - - register_setting('igny8_bridge_controls', 'igny8_control_mode', array( - 'type' => 'string', - 'sanitize_callback' => array($this, 'sanitize_control_mode'), - 'default' => 'mirror' - )); - - register_setting('igny8_bridge_controls', 'igny8_enabled_modules', array( - 'type' => 'array', - 'sanitize_callback' => array($this, 'sanitize_modules'), - 'default' => array_keys(igny8_get_available_modules()) - )); - } - - /** - * Enqueue admin scripts and styles - * - * @param string $hook Current admin page hook - */ - public function enqueue_scripts($hook) { - // Enqueue on settings page - if ($hook === 'settings_page_igny8-settings') { - wp_enqueue_style( - 'igny8-admin-style', - IGNY8_BRIDGE_PLUGIN_URL . 'admin/assets/css/admin.css', - array(), - IGNY8_BRIDGE_VERSION - ); - - wp_enqueue_script( - 'igny8-admin-script', - IGNY8_BRIDGE_PLUGIN_URL . 'admin/assets/js/admin.js', - array('jquery'), - IGNY8_BRIDGE_VERSION, - true - ); - - wp_localize_script('igny8-admin-script', 'igny8Admin', array( - 'ajaxUrl' => admin_url('admin-ajax.php'), - 'nonce' => wp_create_nonce('igny8_admin_nonce'), - )); - } - - // Enqueue on post/page/product list pages - if (strpos($hook, 'edit.php') !== false) { - $screen = get_current_screen(); - if ($screen && in_array($screen->post_type, array('post', 'page', 'product', ''))) { - wp_enqueue_style( - 'igny8-admin-style', - IGNY8_BRIDGE_PLUGIN_URL . 'admin/assets/css/admin.css', - array(), - IGNY8_BRIDGE_VERSION - ); - - wp_enqueue_script( - 'igny8-admin-script', - IGNY8_BRIDGE_PLUGIN_URL . 'admin/assets/js/admin.js', - array('jquery'), - IGNY8_BRIDGE_VERSION, - true - ); - - wp_localize_script('igny8-admin-script', 'igny8Admin', array( - 'ajaxUrl' => admin_url('admin-ajax.php'), - 'nonce' => wp_create_nonce('igny8_admin_nonce'), - )); - } - } - } - - /** - * Render settings page - */ - public function render_settings_page() { - // Handle form submission (use wp_verify_nonce to avoid wp_die on failure) - if (isset($_POST['igny8_connect'])) { - if (empty($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'igny8_settings_nonce')) { - add_settings_error( - 'igny8_settings', - 'igny8_nonce', - __('Security check failed. Please refresh the page and try again.', 'igny8-bridge'), - 'error' - ); - } else { - $this->handle_connection(); - } - } - - // Handle revoke API key (use wp_verify_nonce) - if (isset($_POST['igny8_revoke_api_key'])) { - if (empty($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'igny8_revoke_api_key')) { - add_settings_error( - 'igny8_settings', - 'igny8_nonce_revoke', - __('Security check failed. Could not revoke API key.', 'igny8-bridge'), - 'error' - ); - } else { - self::revoke_api_key(); - add_settings_error( - 'igny8_settings', - 'igny8_api_key_revoked', - __('API key revoked and removed from this site.', 'igny8-bridge'), - 'updated' - ); - } - } - - // Webhook secret regeneration removed - using API key only - - // Include settings template - include IGNY8_BRIDGE_PLUGIN_DIR . 'admin/settings.php'; - } - - /** - * Handle API connection - API key only - * Calls /v1/integration/integrations/test-connection/ endpoint - */ - private function handle_connection() { - $api_key = sanitize_text_field($_POST['igny8_api_key'] ?? ''); - $site_id = sanitize_text_field($_POST['igny8_site_id'] ?? ''); - - // API key is required - if (empty($api_key)) { - add_settings_error( - 'igny8_settings', - 'igny8_error', - __('API key is required to connect to IGNY8.', 'igny8-bridge'), - 'error' - ); - return; - } - - // Site ID is required - if (empty($site_id)) { - add_settings_error( - 'igny8_settings', - 'igny8_error', - __('Site ID is required. Create a site in IGNY8 app first.', 'igny8-bridge'), - 'error' - ); - return; - } - - // Get site URL - $site_url = get_site_url(); - - // Test connection using the correct integration test endpoint - // The API class will handle authentication for test-connection endpoint - // by using the API key from the request body - $api = new Igny8API(); - - $test_response = $api->post('/v1/integration/integrations/test-connection/', array( - 'site_id' => (int) $site_id, - 'api_key' => $api_key, - 'site_url' => $site_url - )); - - if (!$test_response['success']) { - $error_message = $test_response['error'] ?? 'Unknown error'; - - // Provide more user-friendly message for throttling errors - if (isset($test_response['http_status']) && $test_response['http_status'] === 429) { - $error_message = __('Rate limit exceeded. The plugin will automatically retry, but if this persists, please wait a moment and try again.', 'igny8-bridge'); - } - - add_settings_error( - 'igny8_settings', - 'igny8_error', - sprintf( - __('Failed to connect to IGNY8 API: %s', 'igny8-bridge'), - $error_message - ), - 'error' - ); - return; - } - - // Store API key securely - if (function_exists('igny8_store_secure_option')) { - igny8_store_secure_option('igny8_api_key', $api_key); - igny8_store_secure_option('igny8_access_token', $api_key); - } else { - update_option('igny8_api_key', $api_key); - update_option('igny8_access_token', $api_key); - } - - // Store site ID - update_option('igny8_site_id', sanitize_text_field($site_id)); - - add_settings_error( - 'igny8_settings', - 'igny8_connected', - __('Successfully connected to IGNY8 API. Site registered.', 'igny8-bridge'), - 'updated' - ); - - // Sync site structure to backend (post types, taxonomies, etc.) - igny8_sync_site_structure_to_backend(); - } - - /** - * Revoke stored API key (secure delete) - * - * Public so tests can call it directly. - */ - public static function revoke_api_key() { - if (function_exists('igny8_delete_secure_option')) { - igny8_delete_secure_option('igny8_api_key'); - igny8_delete_secure_option('igny8_access_token'); - igny8_delete_secure_option('igny8_refresh_token'); - } else { - delete_option('igny8_api_key'); - delete_option('igny8_access_token'); - delete_option('igny8_refresh_token'); - } - - // Also clear token-issued timestamps - delete_option('igny8_token_refreshed_at'); - delete_option('igny8_access_token_issued'); - } - - /** - * Test API connection (AJAX handler) - */ - public static function test_connection() { - check_ajax_referer('igny8_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations to test.')); - } - - $api = new Igny8API(); - - if (!$api->is_authenticated()) { - wp_send_json_error(array('message' => 'Not authenticated')); - } - - // Get site ID - $site_id = get_option('igny8_site_id'); - if (empty($site_id)) { - wp_send_json_error(array('message' => 'Site ID not configured. Connect to IGNY8 first.')); - } - - // Test connection using the integration test endpoint - $api_key = function_exists('igny8_get_secure_option') ? igny8_get_secure_option('igny8_api_key') : get_option('igny8_api_key'); - - $test_response = $api->post('/v1/integration/integrations/test-connection/', array( - 'site_id' => (int) $site_id, - 'api_key' => $api_key, - 'site_url' => get_site_url() - )); - - if ($test_response['success']) { - $checked_at = current_time('timestamp'); - update_option('igny8_last_api_health_check', $checked_at); - wp_send_json_success(array( - 'message' => __('Connection successful! IGNY8 API is responsive.', 'igny8-bridge'), - 'checked_at' => $checked_at - )); - return; - } - - // Connection failed - $error_message = $test_response['error'] ?? 'Unknown error'; - wp_send_json_error(array( - 'message' => __('Connection failed: ', 'igny8-bridge') . $error_message, - 'http_status' => $test_response['http_status'] ?? 0, - )); - } - - /** - * Sync posts to IGNY8 (AJAX handler) - */ - public static function sync_posts() { - check_ajax_referer('igny8_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $result = igny8_batch_sync_post_statuses(); - - wp_send_json_success(array( - 'message' => sprintf('Synced %d posts, %d failed', $result['synced'], $result['failed']), - 'data' => $result - )); - } - - /** - * Sync taxonomies (AJAX handler) - */ - public static function sync_taxonomies() { - check_ajax_referer('igny8_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $api = new Igny8API(); - if (!$api->is_authenticated()) { - wp_send_json_error(array('message' => 'Not authenticated')); - } - - // Sync sectors and clusters from IGNY8 - $sectors_result = igny8_sync_igny8_sectors_to_wp(); - $clusters_result = igny8_sync_igny8_clusters_to_wp(); - - wp_send_json_success(array( - 'message' => sprintf('Synced %d sectors, %d clusters', - $sectors_result['synced'] ?? 0, - $clusters_result['synced'] ?? 0 - ), - 'data' => array( - 'sectors' => $sectors_result, - 'clusters' => $clusters_result - ) - )); - } - - /** - * Sync from IGNY8 (AJAX handler) - */ - public static function sync_from_igny8() { - check_ajax_referer('igny8_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $result = igny8_sync_igny8_tasks_to_wp(); - - if ($result['success']) { - wp_send_json_success(array( - 'message' => sprintf('Created %d posts, updated %d posts', - $result['created'], - $result['updated'] - ), - 'data' => $result - )); - } else { - wp_send_json_error(array( - 'message' => $result['error'] ?? 'Sync failed' - )); - } - } - - /** - * Collect and send site data (AJAX handler) - */ - public static function collect_site_data() { - check_ajax_referer('igny8_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $site_id = get_option('igny8_site_id'); - if (!$site_id) { - wp_send_json_error(array('message' => 'Site ID not set')); - } - - $result = igny8_send_site_data_to_igny8($site_id); - - if ($result) { - wp_send_json_success(array( - 'message' => 'Site data collected and sent successfully', - 'data' => $result - )); - } else { - wp_send_json_error(array('message' => 'Failed to send site data')); - } - } - - /** - * Get sync statistics (AJAX handler) - */ - public static function get_stats() { - check_ajax_referer('igny8_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - global $wpdb; - - // Count synced posts - $synced_posts = $wpdb->get_var(" - SELECT COUNT(DISTINCT post_id) - FROM {$wpdb->postmeta} - WHERE meta_key = '_igny8_task_id' - "); - - // Get last sync time - $last_sync = get_option('igny8_last_site_sync', 0); - $last_sync_formatted = $last_sync ? date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $last_sync) : 'Never'; - - wp_send_json_success(array( - 'synced_posts' => intval($synced_posts), - 'last_sync' => $last_sync_formatted - )); - } - - /** - * Sanitize post types option - * - * @param mixed $value Raw value - * @return array - */ - public function sanitize_post_types($value) { - $supported = array_keys(igny8_get_supported_post_types()); - - if (!is_array($value)) { - return $supported; - } - - $clean = array(); - foreach ($value as $post_type) { - $post_type = sanitize_key($post_type); - if (in_array($post_type, $supported, true)) { - $clean[] = $post_type; - } - } - - return !empty($clean) ? $clean : $supported; - } - - /** - * Sanitize taxonomies option - * - * @param mixed $value Raw value - * @return array - */ - public function sanitize_taxonomies($value) { - $supported = array_keys(igny8_get_supported_taxonomies()); - - if (!is_array($value)) { - return array('category', 'post_tag', 'product_cat', 'igny8_sectors', 'igny8_clusters'); - } - - $clean = array(); - foreach ($value as $taxonomy) { - $taxonomy = sanitize_key($taxonomy); - if (in_array($taxonomy, $supported, true)) { - $clean[] = $taxonomy; - } - } - - // Return defaults if nothing selected - return !empty($clean) ? $clean : array('category', 'post_tag'); - } - - /** - * Sanitize boolean option - * - * @param mixed $value Raw value - * @return int - */ - public function sanitize_boolean($value) { - return $value ? 1 : 0; - } - - /** - * Sanitize control mode - * - * @param mixed $value Raw value - * @return string - */ - public function sanitize_control_mode($value) { - $value = is_string($value) ? strtolower($value) : 'mirror'; - return in_array($value, array('mirror', 'hybrid'), true) ? $value : 'mirror'; - } - - /** - * Sanitize module toggles - * - * @param mixed $value Raw value - * @return array - */ - public function sanitize_modules($value) { - $supported = array_keys(igny8_get_available_modules()); - - if (!is_array($value)) { - return $supported; - } - - $clean = array(); - foreach ($value as $module) { - $module = sanitize_key($module); - if (in_array($module, $supported, true)) { - $clean[] = $module; - } - } - - return !empty($clean) ? $clean : $supported; - } -} - -// Register AJAX handlers -add_action('wp_ajax_igny8_test_connection', array('Igny8Admin', 'test_connection')); -add_action('wp_ajax_igny8_sync_posts', array('Igny8Admin', 'sync_posts')); -add_action('wp_ajax_igny8_sync_taxonomies', array('Igny8Admin', 'sync_taxonomies')); -add_action('wp_ajax_igny8_sync_from_igny8', array('Igny8Admin', 'sync_from_igny8')); -add_action('wp_ajax_igny8_collect_site_data', array('Igny8Admin', 'collect_site_data')); -add_action('wp_ajax_igny8_get_stats', array('Igny8Admin', 'get_stats')); - diff --git a/igy8-wp-plugin/admin/class-post-meta-boxes.php b/igy8-wp-plugin/admin/class-post-meta-boxes.php deleted file mode 100644 index d0d6ebcb..00000000 --- a/igy8-wp-plugin/admin/class-post-meta-boxes.php +++ /dev/null @@ -1,469 +0,0 @@ - admin_url('admin-ajax.php'), - 'nonce' => wp_create_nonce('igny8_post_editor_nonce'), - )); - } - - /** - * Render Planner Brief meta box - */ - public function render_planner_brief_box($post) { - $task_id = get_post_meta($post->ID, '_igny8_task_id', true); - $brief = get_post_meta($post->ID, '_igny8_task_brief', true); - $brief_cached_at = get_post_meta($post->ID, '_igny8_brief_cached_at', true); - $cluster_id = get_post_meta($post->ID, '_igny8_cluster_id', true); - - if (!$task_id && !$cluster_id) { - echo ''; - _e('This post is not linked to an IGNY8 task or cluster.', 'igny8-bridge'); - echo '
'; - return; - } - - wp_nonce_field('igny8_post_editor_nonce', 'igny8_post_editor_nonce'); - ?> -- -
- -- -
- -- - - - - -
- - - ID, '_igny8_task_id', true); - $optimizer_job_id = get_post_meta($post->ID, '_igny8_optimizer_job_id', true); - $optimizer_status = get_post_meta($post->ID, '_igny8_optimizer_status', true); - - if (!$task_id) { - echo ''; - _e('This post is not linked to an IGNY8 task.', 'igny8-bridge'); - echo '
'; - return; - } - - wp_nonce_field('igny8_post_editor_nonce', 'igny8_post_editor_nonce'); - ?> -- - -
- - -- - - - -
- - -- -
-- -
- -- -
- - - 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; - $task_id = isset($_POST['task_id']) ? intval($_POST['task_id']) : 0; - - if (!$post_id || !$task_id) { - wp_send_json_error(array('message' => 'Invalid post ID or task ID')); - } - - $api = new Igny8API(); - - if (!$api->is_authenticated()) { - wp_send_json_error(array('message' => 'Not authenticated')); - } - - // Try to fetch from Planner first - $response = $api->get("/planner/tasks/{$task_id}/brief/"); - - if (!$response['success']) { - // Fallback to Writer brief - $response = $api->get("/writer/tasks/{$task_id}/brief/"); - } - - if ($response['success'] && !empty($response['data'])) { - update_post_meta($post_id, '_igny8_task_brief', $response['data']); - update_post_meta($post_id, '_igny8_brief_cached_at', current_time('mysql')); - - wp_send_json_success(array( - 'message' => 'Brief fetched successfully', - 'brief' => $response['data'] - )); - } else { - wp_send_json_error(array( - 'message' => 'Failed to fetch brief: ' . ($response['error'] ?? 'Unknown error') - )); - } - } - - /** - * Refresh Planner task (AJAX handler) - */ - public static function refresh_planner_task() { - check_ajax_referer('igny8_post_editor_nonce', 'nonce'); - - if (!current_user_can('edit_posts')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; - $task_id = isset($_POST['task_id']) ? intval($_POST['task_id']) : 0; - - if (!$post_id || !$task_id) { - wp_send_json_error(array('message' => 'Invalid post ID or task ID')); - } - - $api = new Igny8API(); - - if (!$api->is_authenticated()) { - wp_send_json_error(array('message' => 'Not authenticated')); - } - - $response = $api->post("/planner/tasks/{$task_id}/refresh/", array( - 'wordpress_post_id' => $post_id, - 'reason' => 'reoptimize', - 'notes' => 'Requested refresh from WordPress editor' - )); - - if ($response['success']) { - wp_send_json_success(array( - 'message' => 'Refresh requested successfully', - 'data' => $response['data'] - )); - } else { - wp_send_json_error(array( - 'message' => 'Failed to request refresh: ' . ($response['error'] ?? 'Unknown error') - )); - } - } - - /** - * Create Optimizer job (AJAX handler) - */ - public static function create_optimizer_job() { - check_ajax_referer('igny8_post_editor_nonce', 'nonce'); - - if (!current_user_can('edit_posts')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; - $task_id = isset($_POST['task_id']) ? intval($_POST['task_id']) : 0; - $job_type = isset($_POST['job_type']) ? sanitize_text_field($_POST['job_type']) : 'audit'; - $priority = isset($_POST['priority']) ? sanitize_text_field($_POST['priority']) : 'normal'; - - if (!$post_id || !$task_id) { - wp_send_json_error(array('message' => 'Invalid post ID or task ID')); - } - - $api = new Igny8API(); - - if (!$api->is_authenticated()) { - wp_send_json_error(array('message' => 'Not authenticated')); - } - - $response = $api->post("/optimizer/jobs/", array( - 'post_id' => $post_id, - 'task_id' => $task_id, - 'job_type' => $job_type, - 'priority' => $priority - )); - - if ($response['success'] && !empty($response['data'])) { - $job_id = $response['data']['id'] ?? $response['data']['job_id'] ?? null; - - if ($job_id) { - update_post_meta($post_id, '_igny8_optimizer_job_id', $job_id); - update_post_meta($post_id, '_igny8_optimizer_status', $response['data']['status'] ?? 'pending'); - update_post_meta($post_id, '_igny8_optimizer_job_created_at', current_time('mysql')); - } - - wp_send_json_success(array( - 'message' => 'Optimizer job created successfully', - 'job_id' => $job_id, - 'data' => $response['data'] - )); - } else { - wp_send_json_error(array( - 'message' => 'Failed to create optimizer job: ' . ($response['error'] ?? 'Unknown error') - )); - } - } - - /** - * Get Optimizer job status (AJAX handler) - */ - public static function get_optimizer_status() { - check_ajax_referer('igny8_post_editor_nonce', 'nonce'); - - if (!current_user_can('edit_posts')) { - wp_send_json_error(array('message' => 'Unauthorized')); - } - - if (!igny8_is_connection_enabled()) { - wp_send_json_error(array('message' => 'Connection is disabled. Enable sync operations first.')); - } - - $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; - $job_id = isset($_POST['job_id']) ? intval($_POST['job_id']) : 0; - - if (!$post_id || !$job_id) { - wp_send_json_error(array('message' => 'Invalid post ID or job ID')); - } - - $api = new Igny8API(); - - if (!$api->is_authenticated()) { - wp_send_json_error(array('message' => 'Not authenticated')); - } - - $response = $api->get("/optimizer/jobs/{$job_id}/"); - - if ($response['success'] && !empty($response['data'])) { - $status = $response['data']['status'] ?? 'unknown'; - update_post_meta($post_id, '_igny8_optimizer_status', $status); - - if (!empty($response['data']['score_changes'])) { - update_post_meta($post_id, '_igny8_optimizer_score_changes', $response['data']['score_changes']); - } - - if (!empty($response['data']['recommendations'])) { - update_post_meta($post_id, '_igny8_optimizer_recommendations', $response['data']['recommendations']); - } - - wp_send_json_success(array( - 'message' => 'Status retrieved successfully', - 'status' => $status, - 'data' => $response['data'] - )); - } else { - wp_send_json_error(array( - 'message' => 'Failed to get status: ' . ($response['error'] ?? 'Unknown error') - )); - } - } -} - -// Initialize -new Igny8PostMetaBoxes(); - diff --git a/igy8-wp-plugin/admin/settings.php b/igy8-wp-plugin/admin/settings.php deleted file mode 100644 index cf791246..00000000 --- a/igy8-wp-plugin/admin/settings.php +++ /dev/null @@ -1,771 +0,0 @@ - 10)); - $two_way_sync = (int) get_option('igny8_enable_two_way_sync', 1); - -?> - -
-
-
-
-
- : - -
- -- -
-- -
-- -
-- -
-- -
-- -
-- -
-- -
-- - - -
-- -
-- -
-| - |
-
-
- - - - |
-
|---|---|
| - |
-
-
-
- - - - |
-
- -
-- -
-
-
-
-
- publish, - $page_count->publish, - $product_count ? sprintf(', %d products', $product_count->publish) : '' - ); ?> -
- - -- -
- - -- -
- - -- -
- - -