- 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:
Binary file not shown.
83
integrations/Wordpress/eveai_sync/README.md
Normal file
83
integrations/Wordpress/eveai_sync/README.md
Normal 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.
|
||||
70
integrations/Wordpress/eveai_sync/admin/css/eveai-admin.css
Normal file
70
integrations/Wordpress/eveai_sync/admin/css/eveai-admin.css
Normal 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;
|
||||
}
|
||||
49
integrations/Wordpress/eveai_sync/admin/js/eveai_admin.js
Normal file
49
integrations/Wordpress/eveai_sync/admin/js/eveai_admin.js
Normal 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.');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
64
integrations/Wordpress/eveai_sync/eveai_sync.php
Normal file
64
integrations/Wordpress/eveai_sync/eveai_sync.php
Normal 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');
|
||||
156
integrations/Wordpress/eveai_sync/includes/class-eveai-admin.php
Normal file
156
integrations/Wordpress/eveai_sync/includes/class-eveai-admin.php
Normal 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');
|
||||
}
|
||||
}
|
||||
135
integrations/Wordpress/eveai_sync/includes/class-eveai-api.php
Normal file
135
integrations/Wordpress/eveai_sync/includes/class-eveai-api.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user