- Furter refinement of the API, adding functionality for refreshing documents and returning Token expiration time when retrieving token

- Implementation of a first version of a Wordpress plugin
- Adding api service to nginx.conf
This commit is contained in:
Josako
2024-09-11 16:31:13 +02:00
parent 76cb825660
commit 9e14824249
17 changed files with 997 additions and 19 deletions

View File

@@ -0,0 +1,83 @@
# EveAI Sync WordPress Plugin
## Description
EveAI Sync is a WordPress plugin that synchronizes your WordPress content (posts and pages) with the EveAI platform. It allows for seamless integration between your WordPress site and EveAI, ensuring that your content is always up-to-date on both platforms.
## Features
- Automatic synchronization of posts and pages with EveAI
- Support for excluding specific categories or individual posts/pages from syncing
- Bulk synchronization of existing content
- Custom metadata synchronization
- Easy-to-use admin interface for configuration
## Installation
1. Download the plugin zip file.
2. Log in to your WordPress admin panel.
3. Go to Plugins > Add New.
4. Click on the "Upload Plugin" button.
5. Select the downloaded zip file and click "Install Now".
6. After installation, click "Activate Plugin".
## Configuration
1. Go to Settings > EveAI Sync in your WordPress admin panel.
2. Enter your EveAI API URL, Tenant ID, and API Key.
3. Configure any additional settings as needed.
4. Click "Save Changes".
## Usage
- New posts and pages will automatically sync to EveAI when published.
- Existing content can be synced using the "Bulk Sync" option in the settings.
- To exclude a post or page from syncing, use the "Exclude from EveAI sync" checkbox in the post editor.
- Categories can be excluded from syncing in the plugin settings.
## Action Scheduler Dependency
This plugin uses Action Scheduler for efficient background processing of synchronization tasks. Action Scheduler is typically included with WooCommerce, but the plugin can also function without it.
### With Action Scheduler
If Action Scheduler is available (either through WooCommerce or included with this plugin), EveAI Sync will use it for more reliable and efficient scheduling of synchronization tasks.
### Without Action Scheduler
If Action Scheduler is not available, the plugin will automatically fall back to using WordPress cron for scheduling tasks. This fallback ensures that the plugin remains functional, although with potentially less precise timing for background tasks.
No additional configuration is needed; the plugin will automatically detect the presence or absence of Action Scheduler and adjust its behavior accordingly.
## Versions
### 1.0.x - Bugfixing Releases
### 1.0.0 - Initial Release
## Frequently Asked Questions
**Q: How often does the plugin sync content?**
A: The plugin syncs content immediately when a post or page is published or updated. For bulk syncs or when Action Scheduler is not available, the timing may vary based on WordPress cron execution.
**Q: Can I sync only certain types of content?**
A: By default, the plugin syncs all posts and pages. You can exclude specific categories or individual posts/pages from syncing.
**Q: What happens if the sync fails?**
A: The plugin will log any sync failures and attempt to retry. You can view sync status in the plugin's admin interface.
**Q: Do I need to install Action Scheduler separately?**
A: No, the plugin will work with or without Action Scheduler. If you have WooCommerce installed, Action Scheduler will be available automatically.
## Support
For support, please open an issue on our GitHub repository or contact our support team at support@eveai.com.
## Contributing
We welcome contributions to the EveAI Sync plugin. Please feel free to submit pull requests or open issues on our GitHub repository.
## License
This plugin is licensed under the GPL v2 or later.

View File

@@ -0,0 +1,70 @@
.eveai-admin-wrap {
max-width: 800px;
margin: 20px auto;
}
.eveai-admin-header {
background-color: #fff;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 20px;
}
.eveai-admin-header h1 {
margin: 0;
color: #23282d;
}
.eveai-admin-content {
background-color: #fff;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
}
.eveai-form-group {
margin-bottom: 15px;
}
.eveai-form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.eveai-form-group input[type="text"],
.eveai-form-group input[type="password"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.eveai-button {
background-color: #0085ba;
border-color: #0073aa #006799 #006799;
color: #fff;
text-decoration: none;
text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
display: inline-block;
padding: 8px 12px;
border-radius: 3px;
cursor: pointer;
}
.eveai-button:hover {
background-color: #008ec2;
}
.eveai-category-list {
margin-top: 20px;
}
.eveai-category-item {
margin-bottom: 10px;
}
.eveai-category-item label {
font-weight: normal;
}

View File

@@ -0,0 +1,49 @@
jQuery(document).ready(function($) {
// Handle bulk sync button click
$('#eveai-bulk-sync').on('click', function(e) {
e.preventDefault();
if (confirm('Are you sure you want to start a bulk sync? This may take a while.')) {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'eveai_bulk_sync',
nonce: eveai_admin.nonce
},
success: function(response) {
alert(response.data.message);
},
error: function() {
alert('An error occurred. Please try again.');
}
});
}
});
// Handle category exclusion checkboxes
$('.eveai-category-exclude').on('change', function() {
var categoryId = $(this).val();
var isExcluded = $(this).is(':checked');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'eveai_toggle_category_exclusion',
category_id: categoryId,
is_excluded: isExcluded ? 1 : 0,
nonce: eveai_admin.nonce
},
success: function(response) {
if (response.success) {
console.log('Category exclusion updated');
} else {
alert('Failed to update category exclusion');
}
},
error: function() {
alert('An error occurred. Please try again.');
}
});
});
});

View File

@@ -0,0 +1,64 @@
<?php
/**
* Plugin Name: EveAI Sync
* Plugin URI: https://askeveai.com/
* Description: Synchronizes WordPress content with EveAI API.
* Version: 1.0.16
* Author: Josako, Pieter Laroy
* Author URI: https://askeveai.com/about/
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: eveai-sync
* Domain Path: /languages
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
// Define plugin constants
define('EVEAI_SYNC_VERSION', '1.0.0');
define('EVEAI_SYNC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('EVEAI_SYNC_PLUGIN_URL', plugin_dir_url(__FILE__));
// Include the main plugin class
require_once EVEAI_SYNC_PLUGIN_DIR . 'includes/class-eveai-sync.php';
// Initialize the plugin
function eveai_sync_init() {
$plugin = new EveAI_Sync();
$plugin->init();
}
add_action('plugins_loaded', 'eveai_sync_init');
// Set up activation and deactivation hooks
register_activation_hook(__FILE__, 'eveai_sync_activation');
register_deactivation_hook(__FILE__, 'eveai_sync_deactivation');
function eveai_sync_activation() {
// Other activation tasks...
}
function eveai_sync_deactivation() {
// Other deactivation tasks...
}
// Clean up meta when a post is permanently deleted
function eveai_delete_post_meta($post_id) {
delete_post_meta($post_id, '_eveai_document_id');
delete_post_meta($post_id, '_eveai_document_version_id');
}
add_action('before_delete_post', 'eveai_delete_post_meta');
// Display sync info in post
function eveai_display_sync_info($post) {
$document_id = get_post_meta($post->ID, '_eveai_document_id', true);
$document_version_id = get_post_meta($post->ID, '_eveai_document_version_id', true);
echo '<div class="misc-pub-section">';
echo '<h4>EveAI Sync Info:</h4>';
echo 'Document ID: ' . ($document_id ? esc_html($document_id) : 'Not set') . '<br>';
echo 'Document Version ID: ' . ($document_version_id ? esc_html($document_version_id) : 'Not set');
echo '</div>';
}
add_action('post_submitbox_misc_actions', 'eveai_display_sync_info');

View File

@@ -0,0 +1,156 @@
<?php
class EveAI_Admin {
private $api;
public function __construct($api) {
$this->api = $api;
}
public function register_settings() {
register_setting('eveai_settings', 'eveai_api_url');
register_setting('eveai_settings', 'eveai_tenant_id');
register_setting('eveai_settings', 'eveai_api_key');
register_setting('eveai_settings', 'eveai_default_language');
register_setting('eveai_settings', 'eveai_excluded_categories');
register_setting('eveai_settings', 'eveai_excluded_categories');
register_setting('eveai_settings', 'eveai_access_token');
register_setting('eveai_settings', 'eveai_token_expiry');
}
public function add_admin_menu() {
add_options_page(
'EveAI Sync Settings',
'EveAI Sync',
'manage_options',
'eveai-sync',
array($this, 'render_settings_page')
);
}
public function render_settings_page() {
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<form action="options.php" method="post">
<?php
settings_fields('eveai_settings');
do_settings_sections('eveai-sync');
?>
<table class="form-table">
<tr valign="top">
<th scope="row">API URL</th>
<td><input type="text" name="eveai_api_url" value="<?php echo esc_attr(get_option('eveai_api_url')); ?>" style="width: 100%;" /></td>
</tr>
<tr valign="top">
<th scope="row">Tenant ID</th>
<td><input type="text" name="eveai_tenant_id" value="<?php echo esc_attr(get_option('eveai_tenant_id')); ?>" style="width: 100%;" /></td>
</tr>
<tr valign="top">
<th scope="row">API Key</th>
<td><input type="text" name="eveai_api_key" value="<?php echo esc_attr(get_option('eveai_api_key')); ?>" style="width: 100%;" /></td>
</tr>
<tr valign="top">
<th scope="row">Default Language</th>
<td><input type="text" name="eveai_default_language" value="<?php echo esc_attr(get_option('eveai_default_language', 'en')); ?>" style="width: 100%;" /></td>
</tr>
<tr valign="top">
<th scope="row">Excluded Categories</th>
<td>
<input type="text" name="eveai_excluded_categories" value="<?php echo esc_attr(get_option('eveai_excluded_categories')); ?>" style="width: 100%;" />
<p class="description">Enter a comma-separated list of category names to exclude from syncing.</p>
</td>
</tr>
</table>
<?php submit_button('Save Settings'); ?>
</form>
<h2>Bulk Sync</h2>
<p>Click the button below to start a bulk sync of all posts and pages to EveAI.</p>
<form method="post" action="">
<?php wp_nonce_field('eveai_bulk_sync', 'eveai_bulk_sync_nonce'); ?>
<input type="submit" name="eveai_bulk_sync" class="button button-primary" value="Start Bulk Sync">
</form>
<div id="eveai-sync-results" style="margin-top: 20px;"></div>
</div>
<script>
jQuery(document).ready(function($) {
$('form').on('submit', function(e) {
if ($(this).find('input[name="eveai_bulk_sync"]').length) {
e.preventDefault();
var $results = $('#eveai-sync-results');
$results.html('<p>Starting bulk sync...</p>');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'eveai_bulk_sync',
nonce: '<?php echo wp_create_nonce('eveai_bulk_sync_ajax'); ?>'
},
success: function(response) {
if (response.success) {
var resultsHtml = '<h3>Sync Results:</h3><ul>';
response.data.forEach(function(item) {
resultsHtml += '<li>' + item.title + ' (' + item.type + '): ' + item.status + '</li>';
});
resultsHtml += '</ul>';
$results.html(resultsHtml);
} else {
$results.html('<p>Error: ' + response.data + '</p>');
}
},
error: function() {
$results.html('<p>An error occurred. Please try again.</p>');
}
});
}
});
});
</script>
<?php
}
public function handle_bulk_sync_ajax() {
check_ajax_referer('eveai_bulk_sync_ajax', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error('Insufficient permissions');
return;
}
$post_handler = new EveAI_Post_Handler($this->api);
$bulk_sync = new EveAI_Bulk_Sync($this->api, $post_handler);
$results = $bulk_sync->init_bulk_sync();
wp_send_json_success($results);
}
public function add_sync_meta_box() {
add_meta_box(
'eveai_sync_meta_box',
'EveAI Sync',
array($this, 'render_sync_meta_box'),
array('post', 'page'),
'side',
'default'
);
}
public function render_sync_meta_box($post) {
$excluded = get_post_meta($post->ID, '_eveai_exclude_sync', true);
wp_nonce_field('eveai_sync_meta_box', 'eveai_sync_meta_box_nonce');
?>
<label>
<input type="checkbox" name="eveai_exclude_sync" value="1" <?php checked($excluded, '1'); ?>>
Exclude from EveAI sync
</label>
<?php
}
public function handle_bulk_sync() {
$post_handler = new EveAI_Post_Handler($this->api);
$bulk_sync = new EveAI_Bulk_Sync($this->api, $post_handler);
$bulk_sync->init_bulk_sync();
add_settings_error('eveai_messages', 'eveai_message', 'Bulk sync initiated successfully.', 'updated');
}
}

View File

@@ -0,0 +1,135 @@
<?php
class EveAI_API {
private $api_url;
private $tenant_id;
private $api_key;
private $access_token;
private $token_expiry;
public function __construct() {
$this->api_url = get_option('eveai_api_url');
$this->tenant_id = get_option('eveai_tenant_id');
$this->api_key = get_option('eveai_api_key');
$this->access_token = get_option('eveai_access_token');
$this->token_expiry = get_option('eveai_token_expiry', 0);
}
private function ensure_valid_token() {
if (empty($this->access_token) || time() > $this->token_expiry) {
$this->get_new_token();
}
}
private function get_new_token() {
$response = wp_remote_post($this->api_url . '/api/v1/auth/token', [
'body' => json_encode([
'tenant_id' => $this->tenant_id,
'api_key' => $this->api_key,
]),
'headers' => [
'Content-Type' => 'application/json',
],
]);
if (is_wp_error($response)) {
throw new Exception('Failed to get token: ' . $response->get_error_message());
}
$body = wp_remote_retrieve_body($response);
// Check if the body is already an array (decoded JSON)
if (!is_array($body)) {
$body = json_decode($body, true);
}
if (empty($body['access_token'])) {
throw new Exception('Invalid token response');
}
$this->access_token = $body['access_token'];
// Use the expiration time from the API response, or default to 1 hour if not provided
$expires_in = isset($body['expires_in']) ? $body['expires_in'] : 3600;
$this->token_expiry = time() + $expires_in - 10; // Subtract 10 seconds to be safe
update_option('eveai_access_token', $this->access_token);
update_option('eveai_token_expiry', $this->token_expiry);
}
private function make_request($method, $endpoint, $data = null) {
$this->ensure_valid_token();
error_log('EveAI API Request: ' . $method . ' ' . $this->api_url . $endpoint);
$url = $this->api_url . $endpoint;
$args = array(
'method' => $method,
'headers' => array(
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $this->access_token,
)
);
if ($data !== null) {
$args['body'] = json_encode($data);
}
$response = wp_remote_request($url, $args);
if (is_wp_error($response)) {
$error_message = $response->get_error_message();
error_log('EveAI API Error: ' . $error_message);
throw new Exception('API request failed: ' . $error_message);
}
$body = wp_remote_retrieve_body($response);
$status_code = wp_remote_retrieve_response_code($response);
error_log('EveAI API Response: ' . print_r($body, true));
error_log('EveAI API Status Code: ' . $status_code);
// Check if the body is already an array (decoded JSON)
if (!is_array($body)) {
$body = json_decode($body, true);
}
if ($status_code == 401) {
// Token might have expired, try to get a new one and retry the request
error_log('Token expired, trying to get a new one...');
$this->get_new_token();
return $this->make_request($method, $endpoint, $data);
}
if ($status_code >= 400) {
$error_message = isset($body['message']) ? $body['message'] : 'Unknown error';
error_log('EveAI API Error: ' . $error_message);
throw new Exception('API error: ' . $error_message);
}
return $body;
}
public function add_url($data) {
return $this->make_request('POST', '/api/v1/documents/add_url', $data);
}
public function update_document($document_id, $data) {
return $this->make_request('PUT', "/api/v1/documents/{$document_id}", $data);
}
public function invalidate_document($document_id) {
$data = array(
'valid_to' => gmdate('Y-m-d\TH:i:s\Z') // Current UTC time in ISO 8601 format
);
return $this->make_request('PUT', "/api/v1/documents/{$document_id}", $data);
}
public function refresh_document($document_id) {
return $this->make_request('POST', "/api/v1/documents/{$document_id}/refresh");
}
public function refresh_document_with_info($document_id, $data) {
return $this->make_request('POST', "/api/v1/documents/{$document_id}/refresh_with_info", $data);
}
}

View File

@@ -0,0 +1,37 @@
<?php
class EveAI_Bulk_Sync {
private $api;
private $post_handler;
public function __construct($api, $post_handler) {
$this->api = $api;
$this->post_handler = $post_handler;
}
public function init_bulk_sync() {
$posts = get_posts(array(
'post_type' => array('post', 'page'),
'post_status' => 'publish',
'posts_per_page' => -1,
));
$sync_results = array();
foreach ($posts as $post) {
$evie_id = get_post_meta($post->ID, '_eveai_document_id', true);
$evie_version_id = get_post_meta($post->ID, '_eveai_document_version_id', true);
$is_update = ($evie_id && $evie_version_id);
$result = $this->post_handler->sync_post($post->ID, $is_update);
$sync_results[] = array(
'id' => $post->ID,
'title' => $post->post_title,
'type' => $post->post_type,
'status' => $result ? 'success' : 'failed'
);
}
return $sync_results;
}
}

View File

@@ -0,0 +1,214 @@
<?php
class EveAI_Post_Handler {
private $api;
public function __construct($api) {
$this->api = $api;
}
public function handle_post_save($post_id, $post, $update) {
// Verify if this is not an auto save routine.
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
// Check if this is a revision
if (wp_is_post_revision($post_id)) return;
// Check if post type is one we want to sync
if (!in_array($post->post_type, ['post', 'page'])) return;
// Check if post status is published
if ($post->post_status != 'publish') return;
// Verify nonce
if (!isset($_POST['eveai_sync_meta_box_nonce']) || !wp_verify_nonce($_POST['eveai_sync_meta_box_nonce'], 'eveai_sync_meta_box')) {
return;
}
// Check permissions
if ('page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id)) return;
} else {
if (!current_user_can('edit_post', $post_id)) return;
}
// Check if we should sync this post
if (!$this->should_sync_post($post_id)) return;
// Check if this is a REST API request
if (defined('REST_REQUEST') && REST_REQUEST) {
error_log("EveAI: REST API request detected for post $post_id");
}
error_log('Handling post' . $post_id . 'save event with update: ' . $update);
// Check if we've already synced this post in this request
if (get_post_meta($post_id, '_eveai_syncing', true)) {
return;
}
// Set a flag to indicate we're syncing
update_post_meta($post_id, '_eveai_syncing', true);
$this->sync_post($post_id, $update);
// Remove the flag after syncing
delete_post_meta($post_id, '_eveai_syncing');
}
public function sync_post($post_id, $is_update) {
$evie_id = get_post_meta($post_id, '_eveai_document_id', true);
try {
if ($evie_id && $is_update) {
$old_data = $this->get_old_post_data($post_id);
$new_data = $this->prepare_post_data($post_id);
if ($this->has_metadata_changed($old_data, $new_data)) {
$result = $this->refresh_document_with_info($evie_id, $new_data);
} else {
$result = $this->refresh_document($evie_id);
}
} else {
$data = $this->prepare_post_data($post_id);
$result = $this->api->add_url($data);
}
if (isset($result['document_id']) && isset($result['document_version_id'])) {
update_post_meta($post_id, '_eveai_document_id', $result['document_id']);
update_post_meta($post_id, '_eveai_document_version_id', $result['document_version_id']);
// Add debugging
error_log("EveAI: Set document_id {$result['document_id']} and document_version_id {$result['document_version_id']} for post {$post_id}");
}
return true;
} catch (Exception $e) {
error_log('EveAI Sync Error: ' . $e->getMessage());
// Optionally, you can add an admin notice here
add_action('admin_notices', function() use ($e) {
echo '<div class="notice notice-error is-dismissible">';
echo '<p>EveAI Sync Error: ' . esc_html($e->getMessage()) . '</p>';
echo '</div>';
});
return false;
}
return false;
}
private function get_old_post_data($post_id) {
$post = get_post($post_id);
return array(
'name' => $post->post_title,
'system_metadata' => json_encode([
'post_id' => $post_id,
'type' => $post->post_type,
'author' => get_the_author_meta('display_name', $post->post_author),
'categories' => $post->post_type === 'post' ? wp_get_post_categories($post_id, array('fields' => 'names')) : [],
'tags' => $post->post_type === 'post' ? wp_get_post_tags($post_id, array('fields' => 'names')) : [],
]),
);
}
private function has_metadata_changed($old_data, $new_data) {
return $old_data['name'] !== $new_data['name'] ||
$old_data['user_metadata'] !== $new_data['user_metadata'];
}
private function refresh_document_with_info($evie_id, $data) {
try {
return $this->api->refresh_document_with_info($evie_id, $data);
} catch (Exception $e) {
error_log('EveAI refresh with info error: ' . $e->getMessage());
return false;
}
}
private function refresh_document($evie_id) {
try {
return $this->api->refresh_document($evie_id);
} catch (Exception $e) {
error_log('EveAI refresh error: ' . $e->getMessage());
add_action('admin_notices', function() use ($e) {
echo '<div class="notice notice-error is-dismissible">';
echo '<p>EveAI Sync Error: ' . esc_html($e->getMessage()) . '</p>';
echo '</div>';
});
return false;
}
}
public function handle_post_delete($post_id) {
if ($evie_id) {
try {
$this->api->invalidate_document($evie_id);
} catch (Exception $e) {
error_log('EveAI invalidate error: ' . $e->getMessage());
add_action('admin_notices', function() use ($e) {
echo '<div class="notice notice-error is-dismissible">';
echo '<p>EveAI Sync Error: ' . esc_html($e->getMessage()) . '</p>';
echo '</div>';
});
}
}
}
public function process_sync_queue() {
$queue = get_option('eveai_sync_queue', array());
foreach ($queue as $key => $item) {
$this->sync_post($item['post_id'], $item['is_update']);
unset($queue[$key]);
}
update_option('eveai_sync_queue', $queue);
}
private function should_sync_post($post_id) {
if (get_post_meta($post_id, '_eveai_exclude_sync', true)) {
return false;
}
$post_type = get_post_type($post_id);
if ($post_type === 'page') {
// Pages are always synced unless individually excluded
return true;
}
if ($post_type === 'post') {
$excluded_categories_string = get_option('eveai_excluded_categories', '');
$excluded_categories = array_map('trim', explode(',', $excluded_categories_string));
$post_categories = wp_get_post_categories($post_id, array('fields' => 'names'));
$post_tags = wp_get_post_tags($post_id, array('fields' => 'names'));
// Check if any of the post's categories or tags are not in the excluded list
$all_terms = array_merge($post_categories, $post_tags);
foreach ($all_terms as $term) {
if (!in_array($term, $excluded_categories)) {
return true;
}
}
}
return false;
}
private function prepare_post_data($post_id) {
$post = get_post($post_id);
$data = array(
'url' => get_permalink($post_id),
'name' => $post->post_title,
'language' => get_option('eveai_default_language', 'en'),
'valid_from' => get_gmt_from_date($post->post_date, 'Y-m-d\TH:i:s\Z'),
'user_metadata' => json_encode([
'post_id' => $post_id,
'type' => $post->post_type,
'author' => get_the_author_meta('display_name', $post->post_author),
'categories' => $post->post_type === 'post' ? wp_get_post_categories($post_id, array('fields' => 'names')) : [],
'tags' => $post->post_type === 'post' ? wp_get_post_tags($post_id, array('fields' => 'names')) : [],
]),
);
return $data;
}
}

View File

@@ -0,0 +1,33 @@
<?php
class EveAI_Sync {
private $api;
private $post_handler;
private $admin;
public function init() {
$this->load_dependencies();
$this->setup_actions();
}
private function load_dependencies() {
require_once EVEAI_SYNC_PLUGIN_DIR . 'includes/class-eveai-api.php';
require_once EVEAI_SYNC_PLUGIN_DIR . 'includes/class-eveai-post-handler.php';
require_once EVEAI_SYNC_PLUGIN_DIR . 'includes/class-eveai-admin.php';
require_once EVEAI_SYNC_PLUGIN_DIR . 'includes/class-eveai-bulk-sync.php';
$this->api = new EveAI_API();
$this->post_handler = new EveAI_Post_Handler($this->api);
$this->admin = new EveAI_Admin($this->api);
}
private function setup_actions() {
add_action('save_post', array($this->post_handler, 'handle_post_save'), 10, 3);
add_action('before_delete_post', array($this->post_handler, 'handle_post_delete'));
add_action('admin_init', array($this->admin, 'register_settings'));
add_action('admin_menu', array($this->admin, 'add_admin_menu'));
add_action('add_meta_boxes', array($this->admin, 'add_sync_meta_box'));
add_action('eveai_sync_post', array($this->post_handler, 'sync_post'), 10, 2);
add_action('wp_ajax_eveai_bulk_sync', array($this->admin, 'handle_bulk_sync_ajax'));
}
}