Initial commit: igny8 project

This commit is contained in:
igny8
2025-11-09 10:27:02 +00:00
commit 60b8188111
27265 changed files with 4360521 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,135 @@
<?php
/**
* ==========================
* 🔐 IGNY8 FILE RULE HEADER
* ==========================
* @file : init.php
* @location : /core/admin/init.php
* @type : Function Library
* @scope : Global
* @allowed : Admin initialization, settings registration, asset enqueuing
* @reusability : Globally Reusable
* @notes : WordPress admin initialization and settings management
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* ------------------------------------------------------------------------
* ADMIN INITIALIZATION BOOTSTRAP
* ------------------------------------------------------------------------
*/
add_action('admin_init', 'igny8_register_settings');
/**
* ------------------------------------------------------------------------
* SETTINGS REGISTRATION
* ------------------------------------------------------------------------
*/
function igny8_register_settings() {
$groups = igny8_get_settings_config();
foreach ($groups as $group => $settings) {
foreach ($settings as $name => $config) {
register_setting($group, $name, $config);
}
}
}
/**
* Settings Configuration (grouped)
*/
function igny8_get_settings_config() {
return [
'igny8_table_settings' => [
'igny8_records_per_page' => [
'type' => 'integer',
'default' => 20,
'sanitize_callback' => 'absint'
]
],
'igny8_ai_integration_settings' => [
'igny8_ai_cluster_building' => ['type' => 'string', 'default' => 'enabled', 'sanitize_callback' => 'sanitize_text_field'],
'igny8_ai_content_ideas' => ['type' => 'string', 'default' => 'enabled', 'sanitize_callback' => 'sanitize_text_field'],
'igny8_ai_auto_mapping' => ['type' => 'string', 'default' => 'enabled', 'sanitize_callback' => 'sanitize_text_field']
],
'igny8_api_settings' => [
'igny8_api_key' => ['type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_text_field'],
'igny8_runware_api_key' => ['type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_text_field'],
'igny8_model' => ['type' => 'string', 'default' => 'gpt-4.1', 'sanitize_callback' => 'sanitize_text_field'],
'igny8_image_service' => ['type' => 'string', 'default' => 'openai', 'sanitize_callback' => 'sanitize_text_field'],
'igny8_image_model' => ['type' => 'string', 'default' => 'dall-e-3', 'sanitize_callback' => 'sanitize_text_field'],
'igny8_runware_model' => ['type' => 'string', 'default' => 'runware:97@1', 'sanitize_callback' => 'sanitize_text_field']
],
'igny8_personalize_settings_group' => [
'igny8_content_engine_global_status' => ['sanitize_callback' => 'igny8_sanitize_checkbox_setting'],
'igny8_content_engine_enabled_post_types' => ['sanitize_callback' => 'igny8_sanitize_array_setting'],
'igny8_content_engine_insertion_position' => ['sanitize_callback' => 'sanitize_text_field'],
'igny8_content_engine_display_mode' => ['sanitize_callback' => 'sanitize_text_field'],
'igny8_content_engine_teaser_text' => ['sanitize_callback' => 'sanitize_textarea_field'],
'igny8_content_engine_save_variations' => ['sanitize_callback' => 'intval'],
'igny8_content_engine_field_mode' => ['sanitize_callback' => 'sanitize_text_field'],
'igny8_content_engine_detection_prompt' => ['sanitize_callback' => 'sanitize_textarea_field'],
'igny8_content_engine_context_source' => ['sanitize_callback' => 'sanitize_textarea_field'],
'igny8_content_engine_include_page_context' => ['sanitize_callback' => 'intval'],
'igny8_content_engine_content_length' => ['sanitize_callback' => 'sanitize_text_field'],
'igny8_content_engine_rewrite_prompt' => ['sanitize_callback' => 'sanitize_textarea_field'],
'igny8_content_engine_fixed_fields_config' => ['sanitize_callback' => 'igny8_sanitize_fields_config']
]
];
}
/**
* ------------------------------------------------------------------------
* SANITIZATION HELPERS
* ------------------------------------------------------------------------
*/
function igny8_sanitize_checkbox_setting($raw) {
return isset($_POST['igny8_content_engine_global_status']) ? 'enabled' : 'disabled';
}
function igny8_sanitize_array_setting($raw) {
return is_array($raw) ? array_map('sanitize_text_field', $raw) : [];
}
function igny8_sanitize_fields_config($raw) {
if (!is_array($raw)) return [];
$sanitized = [];
foreach ($raw as $index => $field) {
$sanitized[$index] = [
'label' => sanitize_text_field($field['label'] ?? ''),
'type' => sanitize_text_field($field['type'] ?? 'text'),
'options' => sanitize_text_field($field['options'] ?? '')
];
}
return $sanitized;
}
// MOVED TO: igny8.php - Admin assets enqueuing moved to main plugin file
// ---------------------------------------------------------------------
// WORDPRESS FEATURE REGISTRATION
// ---------------------------------------------------------------------
function igny8_init_wordpress_features() {
// Initialize module manager
add_action('init', 'igny8_module_manager');
// Register taxonomies
add_action('init', 'igny8_register_taxonomies');
// Register post meta once
add_action('init', function() {
if (!get_option('igny8_post_meta_registered')) {
igny8_register_post_meta();
update_option('igny8_post_meta_registered', true);
}
});
}
//Initialize WordPress features
igny8_init_wordpress_features();

View File

@@ -0,0 +1,356 @@
<?php
/**
* ==========================
* 🔐 IGNY8 FILE RULE HEADER
* ==========================
* @file : menu.php
* @location : /core/admin/menu.php
* @type : Admin Menu Handler
* @scope : Global
* @allowed : WordPress admin menu registration, navigation helpers, layout functions
* @reusability : Globally Reusable
* @notes : Registers admin menus and provides breadcrumb/submenu rendering functions
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* Render breadcrumb navigation
*/
function igny8_render_breadcrumb() {
$current_page = $_GET['page'] ?? '';
$sm = $_GET['sm'] ?? '';
$breadcrumb = '<nav class="igny8-breadcrumb-nav">';
$breadcrumb .= '<span class="igny8-breadcrumb-item"><a href="' . admin_url('admin.php?page=igny8-home') . '">Igny8 Home</a></span>';
if ($current_page === 'igny8-planner') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item"><a href="' . admin_url('admin.php?page=igny8-planner') . '">Planner</a></span>';
if ($sm === 'keywords') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Keywords</span>';
} elseif ($sm === 'clusters') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Clusters</span>';
} elseif ($sm === 'ideas') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Ideas</span>';
} elseif ($sm === 'mapping') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Mapping</span>';
}
} elseif ($current_page === 'igny8-writer') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item"><a href="' . admin_url('admin.php?page=igny8-writer') . '">Writer</a></span>';
if ($sm === 'drafts') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Drafts</span>';
} elseif ($sm === 'templates') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Templates</span>';
}
} elseif ($current_page === 'igny8-optimizer') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item"><a href="' . admin_url('admin.php?page=igny8-optimizer') . '">Optimizer</a></span>';
if ($sm === 'audits') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Audits</span>';
} elseif ($sm === 'suggestions') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Suggestions</span>';
}
} elseif ($current_page === 'igny8-linker') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item"><a href="' . admin_url('admin.php?page=igny8-linker') . '">Linker</a></span>';
if ($sm === 'backlinks') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Backlinks</span>';
} elseif ($sm === 'campaigns') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Campaigns</span>';
}
} elseif ($current_page === 'igny8-personalize') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item"><a href="' . admin_url('admin.php?page=igny8-personalize') . '">Personalize</a></span>';
if ($sm === 'settings') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Settings</span>';
} elseif ($sm === 'content-generation') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Content Generation</span>';
} elseif ($sm === 'rewrites') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Rewrites</span>';
} elseif ($sm === 'front-end') {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Front-end</span>';
}
} elseif (strpos($current_page, 'igny8-analytics') !== false) {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Analytics</span>';
} elseif (strpos($current_page, 'igny8-schedules') !== false) {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Schedules</span>';
} elseif (strpos($current_page, 'igny8-settings') !== false) {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Settings</span>';
} elseif (strpos($current_page, 'igny8-help') !== false) {
$breadcrumb .= '<span class="igny8-breadcrumb-separator"></span>';
$breadcrumb .= '<span class="igny8-breadcrumb-item active">Help</span>';
}
$breadcrumb .= '</nav>';
return $breadcrumb;
}
/**
* Render submenu navigation
*/
function igny8_render_submenu() {
$current_page = $_GET['page'] ?? '';
$sm = $_GET['sm'] ?? '';
$submenu = '';
if ($current_page === 'igny8-planner') {
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-planner&sm=home') . '" class="igny8-btn igny8-btn-sm igny8-btn-success igny8-btn-submenu' . ($sm === 'home' || $sm === '' ? ' active' : '') . '">Dashboard</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-planner&sm=keywords') . '" class="igny8-btn igny8-btn-sm igny8-btn-success igny8-btn-submenu' . ($sm === 'keywords' ? ' active' : '') . '">Keywords</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-planner&sm=clusters') . '" class="igny8-btn igny8-btn-sm igny8-btn-success igny8-btn-submenu' . ($sm === 'clusters' ? ' active' : '') . '">Clusters</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-planner&sm=ideas') . '" class="igny8-btn igny8-btn-sm igny8-btn-success igny8-btn-submenu' . ($sm === 'ideas' ? ' active' : '') . '">Ideas</a>';
} elseif ($current_page === 'igny8-writer') {
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-writer&sm=home') . '" class="igny8-btn igny8-btn-sm igny8-btn-primary igny8-btn-submenu' . ($sm === 'home' || $sm === '' ? ' active' : '') . '">Dashboard</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-writer&sm=tasks') . '" class="igny8-btn igny8-btn-sm igny8-btn-primary igny8-btn-submenu' . ($sm === 'tasks' ? ' active' : '') . '">Tasks</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-writer&sm=drafts') . '" class="igny8-btn igny8-btn-sm igny8-btn-primary igny8-btn-submenu' . ($sm === 'drafts' ? ' active' : '') . '">Drafts</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-writer&sm=published') . '" class="igny8-btn igny8-btn-sm igny8-btn-primary igny8-btn-submenu' . ($sm === 'published' ? ' active' : '') . '">Published</a>';
} elseif ($current_page === 'igny8-thinker') {
$sp = $_GET['sp'] ?? 'main';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-thinker&sp=main') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'main' ? ' active' : '') . '">Dashboard</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-thinker&sp=prompts') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'prompts' ? ' active' : '') . '">Prompts</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-thinker&sp=profile') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'profile' ? ' active' : '') . '">Profile</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-thinker&sp=strategies') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'strategies' ? ' active' : '') . '">Strategies</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-thinker&sp=image-testing') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'image-testing' ? ' active' : '') . '">Image Testing</a>';
} elseif ($current_page === 'igny8-optimizer') {
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-optimizer') . '" class="igny8-btn igny8-btn-sm igny8-btn-warning igny8-btn-submenu' . ($sm === '' ? ' active' : '') . '">Dashboard</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-optimizer&sm=audits') . '" class="igny8-btn igny8-btn-sm igny8-btn-warning igny8-btn-submenu' . ($sm === 'audits' ? ' active' : '') . '">Audits</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-optimizer&sm=suggestions') . '" class="igny8-btn igny8-btn-sm igny8-btn-warning igny8-btn-submenu' . ($sm === 'suggestions' ? ' active' : '') . '">Suggestions</a>';
} elseif ($current_page === 'igny8-linker') {
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-linker') . '" class="igny8-btn igny8-btn-sm igny8-btn-info igny8-btn-submenu' . ($sm === '' ? ' active' : '') . '">Dashboard</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-linker&sm=backlinks') . '" class="igny8-btn igny8-btn-sm igny8-btn-info igny8-btn-submenu' . ($sm === 'backlinks' ? ' active' : '') . '">Backlinks</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-linker&sm=campaigns') . '" class="igny8-btn igny8-btn-sm igny8-btn-info igny8-btn-submenu' . ($sm === 'campaigns' ? ' active' : '') . '">Campaigns</a>';
} elseif ($current_page === 'igny8-personalize') {
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-personalize') . '" class="igny8-btn igny8-btn-sm igny8-btn-secondary igny8-btn-submenu' . ($sm === '' ? ' active' : '') . '">Dashboard</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-personalize&sm=settings') . '" class="igny8-btn igny8-btn-sm igny8-btn-secondary igny8-btn-submenu' . ($sm === 'settings' ? ' active' : '') . '">Settings</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-personalize&sm=content-generation') . '" class="igny8-btn igny8-btn-sm igny8-btn-secondary igny8-btn-submenu' . ($sm === 'content-generation' ? ' active' : '') . '">Content Generation</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-personalize&sm=rewrites') . '" class="igny8-btn igny8-btn-sm igny8-btn-secondary igny8-btn-submenu' . ($sm === 'rewrites' ? ' active' : '') . '">Rewrites</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-personalize&sm=front-end') . '" class="igny8-btn igny8-btn-sm igny8-btn-secondary igny8-btn-submenu' . ($sm === 'front-end' ? ' active' : '') . '">Front-end</a>';
} elseif ($current_page === 'igny8-settings') {
$sp = $_GET['sp'] ?? 'general';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-settings&sp=general') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'general' ? ' active' : '') . '">Settings</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-settings&sp=status') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'status' ? ' active' : '') . '">Status</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-settings&sp=integration') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'integration' ? ' active' : '') . '">Integration</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-settings&sp=import-export') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'import-export' ? ' active' : '') . '">Import/Export</a>';
} elseif ($current_page === 'igny8-help') {
$sp = $_GET['sp'] ?? 'help';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-help&sp=help') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'help' ? ' active' : '') . '">Help & Support</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-help&sp=docs') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'docs' ? ' active' : '') . '">Documentation</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-help&sp=system-testing') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'system-testing' ? ' active' : '') . '">System Testing</a>';
$submenu .= '<a href="' . admin_url('admin.php?page=igny8-help&sp=function-testing') . '" class="igny8-btn igny8-btn-sm igny8-btn-outline igny8-btn-submenu' . ($sp === 'function-testing' ? ' active' : '') . '">Function Testing</a>';
}
return $submenu;
}
/**
* Register admin menu pages
*/
function igny8_register_admin_menu() {
// Ensure module manager is available
if (!function_exists('igny8_is_module_enabled')) {
return;
}
// Main menu page
add_menu_page(
'Igny8 AI SEO', // Page title
'Igny8 AI SEO', // Menu title
'manage_options', // Capability
'igny8-home', // Menu slug
'igny8_home_page', // Callback function
'dashicons-chart-line', // Icon
30 // Position
);
// Home page
add_submenu_page(
'igny8-home', // Parent slug
'Dashboard', // Page title
'Dashboard', // Menu title
'manage_options', // Capability
'igny8-home', // Menu slug
'igny8_home_page' // Callback function
);
// Module submenus (only if enabled)
if (igny8_is_module_enabled('planner')) {
add_submenu_page(
'igny8-home',
'Content Planner',
'Planner',
'manage_options',
'igny8-planner',
'igny8_planner_page'
);
}
if (igny8_is_module_enabled('writer')) {
add_submenu_page(
'igny8-home',
'Content Writer',
'Writer',
'manage_options',
'igny8-writer',
'igny8_writer_page'
);
}
if (igny8_is_module_enabled('thinker')) {
add_submenu_page(
'igny8-home',
'AI Thinker',
'Thinker',
'manage_options',
'igny8-thinker',
'igny8_thinker_page'
);
// Prompts subpage under Thinker
add_submenu_page(
'igny8-thinker',
'AI Prompts',
'Prompts',
'manage_options',
'igny8-thinker&sp=prompts',
'igny8_thinker_page'
);
}
if (igny8_is_module_enabled('schedules')) {
add_submenu_page(
'igny8-home',
'Smart Automation Schedules',
'Schedules',
'manage_options',
'igny8-schedules',
'igny8_schedules_page'
);
}
// Analytics before Settings (only if enabled)
if (igny8_is_module_enabled('analytics')) {
add_submenu_page(
'igny8-home',
'Analytics',
'Analytics',
'manage_options',
'igny8-analytics',
'igny8_analytics_page'
);
}
// Cron Health page
// Settings page
add_submenu_page(
'igny8-home',
'Settings',
'Settings',
'manage_options',
'igny8-settings',
'igny8_settings_page'
);
// Help page
add_submenu_page(
'igny8-home',
'Help',
'Help',
'manage_options',
'igny8-help',
'igny8_help_page'
);
// Documentation subpage under Help
add_submenu_page(
'igny8-help',
'Documentation',
'Documentation',
'manage_options',
'igny8-help&sp=docs',
'igny8_help_page'
);
// System Testing subpage under Help
add_submenu_page(
'igny8-help',
'System Testing',
'System Testing',
'manage_options',
'igny8-help&sp=system-testing',
'igny8_help_page'
);
// Function Testing subpage under Help
add_submenu_page(
'igny8-help',
'Function Testing',
'Function Testing',
'manage_options',
'igny8-help&sp=function-testing',
'igny8_help_page'
);
}
// Static page wrapper functions - each page handles its own layout
function igny8_home_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/home.php';
}
function igny8_planner_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/planner/planner.php';
}
function igny8_writer_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/writer/writer.php';
}
function igny8_thinker_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/thinker/thinker.php';
}
function igny8_settings_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/settings/general-settings.php';
}
function igny8_analytics_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/analytics/analytics.php';
}
function igny8_schedules_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/settings/schedules.php';
}
function igny8_help_page() {
include_once plugin_dir_path(__FILE__) . '../../modules/help/help.php';
}
// Hook into admin_menu
add_action('admin_menu', 'igny8_register_admin_menu');

View File

@@ -0,0 +1,387 @@
<?php
/**
* ==========================
* 🔐 IGNY8 FILE RULE HEADER
* ==========================
* @file : meta-boxes.php
* @location : /core/admin/meta-boxes.php
* @type : Function Library
* @scope : Global
* @allowed : Meta box registration, SEO field management
* @reusability : Globally Reusable
* @notes : SEO meta boxes for post editor
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
// === SEO Meta Box ===
add_action('add_meta_boxes', function() {
// SEO fields
add_meta_box('igny8_seo_meta', 'Igny8 SEO Fields', function($post) {
$meta_title = get_post_meta($post->ID, '_igny8_meta_title', true);
$meta_desc = get_post_meta($post->ID, '_igny8_meta_description', true);
$primary_kw = get_post_meta($post->ID, '_igny8_primary_keywords', true);
$secondary_kw = get_post_meta($post->ID, '_igny8_secondary_keywords', true);
?>
<div style="padding:8px 4px;">
<label><strong>Meta Title:</strong></label><br>
<input type="text" name="_igny8_meta_title" value="<?php echo esc_attr($meta_title); ?>" style="width:100%;"><br><br>
<label><strong>Meta Description:</strong></label><br>
<textarea name="_igny8_meta_description" rows="3" style="width:100%;"><?php echo esc_textarea($meta_desc); ?></textarea><br><br>
<label><strong>Primary Keyword:</strong></label><br>
<input type="text" name="_igny8_primary_keywords" value="<?php echo esc_attr($primary_kw); ?>" style="width:100%;"><br><br>
<label><strong>Secondary Keywords (comma-separated):</strong></label><br>
<input type="text" name="_igny8_secondary_keywords" value="<?php echo esc_attr($secondary_kw); ?>" style="width:100%;">
</div>
<?php
}, ['post','page','product'], 'normal', 'high');
});
// === Save Meta Box Data ===
add_action('save_post', function($post_id) {
// Security checks
if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
return;
}
// Save SEO fields
$fields = [
'_igny8_meta_title',
'_igny8_meta_description',
'_igny8_primary_keywords',
'_igny8_secondary_keywords',
];
foreach ($fields as $field) {
if (isset($_POST[$field])) {
update_post_meta($post_id, $field, sanitize_text_field($_POST[$field]));
}
}
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log("Igny8 Metabox: SEO fields saved for post $post_id");
}
});
// === In-Article Image Gallery Meta Box ===
add_action('add_meta_boxes', function() {
$enabled_post_types = get_option('igny8_enable_image_metabox', []);
foreach ((array) $enabled_post_types as $pt) {
add_meta_box(
'igny8_image_gallery',
'Igny8 In-Article Images',
'igny8_render_image_gallery_metabox',
$pt,
'side',
'high'
);
}
});
function igny8_render_image_gallery_metabox($post) {
wp_nonce_field('igny8_save_image_gallery', 'igny8_image_gallery_nonce');
$images = get_post_meta($post->ID, '_igny8_inarticle_images', true);
if (!is_array($images)) $images = [];
// Add CSS for grid layout and remove button
?>
<style>
.igny8-image-list {
display: flex;
flex-wrap: wrap;
list-style: none;
margin: 0;
padding: 0;
gap: 5px;
}
.igny8-image-list li {
width: 200px;
margin: 0 5px 5px 0;
box-sizing: border-box;
text-align: center;
position: relative;
border: 1px solid #eee;
padding: 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 180px;
}
.igny8-image-list li img {
display: block;
margin: 0 auto 5px auto;
}
.igny8-image-actions {
position: absolute;
bottom: 5px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 5px;
opacity: 0;
transition: opacity 0.2s ease;
z-index: 10;
}
.igny8-image-list li:hover .igny8-image-actions {
opacity: 1;
}
.igny8-remove-btn, .igny8-replace-btn {
background: #f0f0f0;
border: 1px solid #ccc;
color: #333;
font-size: 10px;
padding: 2px 6px;
cursor: pointer;
border-radius: 2px;
text-decoration: none;
white-space: nowrap;
}
.igny8-remove-btn:hover {
background: #dc3232;
color: #fff;
border-color: #dc3232;
}
.igny8-replace-btn:hover {
background: #0073aa;
color: #fff;
border-color: #0073aa;
}
.igny8-image-list li strong {
font-size: 0.8em;
word-break: break-all;
}
</style>
<?php
echo '<div id="igny8-image-gallery">';
echo '<p><label><input type="radio" name="igny8_image_type" value="desktop" checked> Desktop</label>
<label><input type="radio" name="igny8_image_type" value="mobile"> Mobile</label></p>';
echo '<button type="button" class="button button-primary" id="igny8-add-image">Add Image</button>';
echo '<ul class="igny8-image-list">';
// Sort images by device type and ID
$sorted_images = [];
foreach ($images as $label => $data) {
$sorted_images[$label] = $data;
}
// Custom sort function to order by device type (desktop first) then by ID
uksort($sorted_images, function($a, $b) {
$a_parts = explode('-', $a);
$b_parts = explode('-', $b);
$a_device = $a_parts[0];
$b_device = $b_parts[0];
// Desktop comes before mobile
if ($a_device === 'desktop' && $b_device === 'mobile') return -1;
if ($a_device === 'mobile' && $b_device === 'desktop') return 1;
// If same device, sort by ID number
if ($a_device === $b_device) {
$a_id = intval($a_parts[1]);
$b_id = intval($b_parts[1]);
return $a_id - $b_id;
}
return 0;
});
foreach ($sorted_images as $label => $data) {
echo '<li data-label="' . esc_attr($label) . '">';
echo '<strong>' . esc_html($label) . '</strong><br>';
echo wp_get_attachment_image($data['attachment_id'], 'thumbnail', false, ['style' => 'width: 150px; height: 150px; object-fit: cover;']);
echo '<div class="igny8-image-actions">';
echo '<button type="button" class="igny8-replace-btn">Replace</button>';
echo '<button type="button" class="igny8-remove-btn">Remove</button>';
echo '</div>';
echo '<input type="hidden" name="igny8_image_data[' . esc_attr($label) . '][attachment_id]" value="' . esc_attr($data['attachment_id']) . '">';
echo '<input type="hidden" name="igny8_image_data[' . esc_attr($label) . '][device]" value="' . esc_attr($data['device']) . '">';
echo '</li>';
}
echo '</ul>';
// Inline JS
?>
<script>
jQuery(document).ready(function($) {
// Function to get first available ID for a device type
function getFirstAvailableId(deviceType) {
let existingIds = [];
$('.igny8-image-list li').each(function() {
let label = $(this).data('label');
if (label && label.startsWith(deviceType + '-')) {
let id = parseInt(label.split('-')[1]);
if (!isNaN(id)) {
existingIds.push(id);
}
}
});
// Sort existing IDs and find first gap
existingIds.sort((a, b) => a - b);
for (let i = 1; i <= existingIds.length + 1; i++) {
if (!existingIds.includes(i)) {
return i;
}
}
return 1; // Fallback
}
$('#igny8-add-image').on('click', function(e) {
e.preventDefault();
let type = $('input[name="igny8_image_type"]:checked').val() || 'desktop';
let availableId = getFirstAvailableId(type);
let label = type + '-' + availableId;
const frame = wp.media({
title: 'Select Image',
button: { text: 'Use this image' },
multiple: false
});
frame.on('select', function() {
let attachment = frame.state().get('selection').first().toJSON();
let html = '<li data-label="' + label + '">' +
'<strong>' + label + '</strong><br>' +
'<img src="' + attachment.sizes.thumbnail.url + '" style="width: 150px; height: 150px; object-fit: cover;" /><br>' +
'<div class="igny8-image-actions">' +
'<button type="button" class="igny8-replace-btn">Replace</button>' +
'<button type="button" class="igny8-remove-btn">Remove</button>' +
'</div>' +
'<input type="hidden" name="igny8_image_data[' + label + '][attachment_id]" value="' + attachment.id + '">' +
'<input type="hidden" name="igny8_image_data[' + label + '][device]" value="' + type + '">' +
'</li>';
$('.igny8-image-list').append(html);
});
frame.open();
});
// Handle image removal (event delegation for dynamically added elements)
$(document).on('click', '.igny8-remove-btn', function() {
$(this).closest('li').remove();
});
// Handle image replacement (event delegation for dynamically added elements)
$(document).on('click', '.igny8-replace-btn', function() {
let $li = $(this).closest('li');
let label = $li.data('label');
let type = label.split('-')[0];
const frame = wp.media({
title: 'Replace Image',
button: { text: 'Replace this image' },
multiple: false
});
frame.on('select', function() {
let attachment = frame.state().get('selection').first().toJSON();
// Replace the entire img element to force reload
let $img = $li.find('img');
let newImg = $('<img>').attr({
'src': attachment.sizes.thumbnail.url,
'style': 'width: 150px; height: 150px; object-fit: cover;'
});
$img.replaceWith(newImg);
// Update the hidden input
$li.find('input[name*="[attachment_id]"]').val(attachment.id);
});
frame.open();
});
// Handle Convert Content to Blocks
$('#igny8-convert-to-blocks').on('click', function(e) {
e.preventDefault();
if (!confirm('This will convert the post content from HTML to WordPress blocks. Continue?')) {
return;
}
let $button = $(this);
let originalText = $button.text();
$button.prop('disabled', true).text('Converting...');
// Get post ID from the current post
let postId = $('#post_ID').val();
// Make AJAX request to convert content to blocks
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'igny8_convert_content_to_blocks',
post_id: postId,
nonce: '<?php echo wp_create_nonce('igny8_convert_to_blocks'); ?>'
},
success: function(response) {
console.log('Convert to Blocks Response:', response);
if (response.success) {
console.log('Success data:', response.data);
alert('Content converted successfully! ' + response.data.message);
location.reload();
} else {
console.error('Error data:', response.data);
alert('Error: ' + (response.data || 'Unknown error'));
}
},
error: function(xhr, status, error) {
console.error('Convert to Blocks Error:', {status, error, responseText: xhr.responseText});
alert('Error converting content. Check console for details.');
},
complete: function() {
$button.prop('disabled', false).text(originalText);
}
});
});
});
</script>
<?php
}
// SAVE HANDLER for Image Gallery
add_action('save_post', function($post_id) {
if (!isset($_POST['igny8_image_gallery_nonce']) || !wp_verify_nonce($_POST['igny8_image_gallery_nonce'], 'igny8_save_image_gallery')) return;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
$images = $_POST['igny8_image_data'] ?? [];
$filtered = [];
foreach ($images as $label => $data) {
if (!empty($data['attachment_id'])) {
$filtered[$label] = [
'label' => sanitize_text_field($label),
'attachment_id' => intval($data['attachment_id']),
'url' => wp_get_attachment_url(intval($data['attachment_id'])),
'device' => sanitize_text_field($data['device'])
];
}
}
update_post_meta($post_id, '_igny8_inarticle_images', $filtered);
if (WP_DEBUG === true) {
error_log("[IGNY8 DEBUG] Saving In-Article Images for Post ID: $post_id");
error_log(print_r($filtered, true));
}
});

View File

@@ -0,0 +1,181 @@
<?php
/**
* ==========================
* 🔐 IGNY8 FILE RULE HEADER
* ==========================
* @file : module-manager-class.php
* @location : /core/admin/module-manager-class.php
* @type : Function Library
* @scope : Global
* @allowed : Module management, class definitions, core functionality
* @reusability : Globally Reusable
* @notes : Module manager class for core functionality
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* Igny8 Module Manager - Controls which modules are active
*/
class Igny8_Module_Manager {
private static $instance = null;
private $modules = [];
public static function get_instance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_modules();
add_action('admin_init', [$this, 'register_module_settings']);
}
/**
* Initialize module definitions - main modules only
*/
private function init_modules() {
$this->modules = [
'planner' => [
'name' => 'Planner',
'description' => 'Keyword research and content planning with clusters, ideas, and mapping tools.',
'default' => true,
'icon' => 'dashicons-search',
'category' => 'main',
'cron_jobs' => [
'igny8_auto_cluster_cron',
'igny8_auto_generate_ideas_cron',
'igny8_auto_queue_cron'
]
],
'writer' => [
'name' => 'Writer',
'description' => 'AI-powered content generation with drafts and templates management.',
'default' => false,
'icon' => 'dashicons-edit',
'category' => 'main',
'cron_jobs' => [
'igny8_auto_generate_content_cron',
'igny8_auto_generate_images_cron',
'igny8_auto_publish_drafts_cron'
]
],
'analytics' => [
'name' => 'Analytics',
'description' => 'Performance tracking and data analysis with comprehensive reporting.',
'default' => false,
'icon' => 'dashicons-chart-bar',
'category' => 'admin',
'cron_jobs' => [
'igny8_process_ai_queue_cron',
'igny8_auto_recalc_cron',
'igny8_health_check_cron'
]
],
'schedules' => [
'name' => 'Schedules',
'description' => 'Content scheduling and automation with calendar management.',
'default' => false,
'icon' => 'dashicons-calendar-alt',
'category' => 'admin'
],
'thinker' => [
'name' => 'AI Thinker',
'description' => 'AI-powered content strategy, prompts, and intelligent content planning tools.',
'default' => true,
'icon' => 'dashicons-lightbulb',
'category' => 'admin'
]
];
}
/**
* Check if a module is enabled
*/
public function is_module_enabled($module) {
$settings = get_option('igny8_module_settings', []);
return isset($settings[$module]) ? (bool) $settings[$module] : (isset($this->modules[$module]) ? $this->modules[$module]['default'] : false);
}
/**
* Get all enabled modules
*/
public function get_enabled_modules() {
$enabled = [];
foreach ($this->modules as $key => $module) {
if ($this->is_module_enabled($key)) {
$enabled[$key] = $module;
}
}
return $enabled;
}
/**
* Get all modules
*/
public function get_modules() {
return $this->modules;
}
/**
* Register module settings
*/
public function register_module_settings() {
register_setting('igny8_module_settings', 'igny8_module_settings');
}
/**
* Save module settings
*/
public function save_module_settings() {
if (!isset($_POST['igny8_module_nonce']) || !wp_verify_nonce($_POST['igny8_module_nonce'], 'igny8_module_settings')) {
wp_die('Security check failed');
}
$settings = $_POST['igny8_module_settings'] ?? [];
// Initialize all modules as disabled first
$all_modules = $this->get_modules();
$final_settings = [];
foreach ($all_modules as $module_key => $module) {
$final_settings[$module_key] = false; // Default to disabled
}
// Set enabled modules to true
foreach ($settings as $key => $value) {
if (isset($final_settings[$key])) {
$final_settings[$key] = (bool) $value;
}
}
update_option('igny8_module_settings', $final_settings);
// Force page reload using JavaScript
echo '<script>window.location.reload();</script>';
exit;
}
}
// Initialize the module manager
function igny8_module_manager() {
return Igny8_Module_Manager::get_instance();
}
// Helper functions for easy access
function igny8_is_module_enabled($module) {
return igny8_module_manager()->is_module_enabled($module);
}
function igny8_get_enabled_modules() {
return igny8_module_manager()->get_enabled_modules();
}
function igny8_get_modules() {
return igny8_module_manager()->get_modules();
}