- 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:
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