Files
seo/wordpress-plugins/rank-math-api-manager-extended.php
Kevin Bataille 8c7cd24685 Refactor SEO automation into unified CLI application
Major refactoring to create a clean, integrated CLI application:

### New Features:
- Unified CLI executable (./seo) with simple command structure
- All commands accept optional CSV file arguments
- Auto-detection of latest files when no arguments provided
- Simplified output directory structure (output/ instead of output/reports/)
- Cleaner export filename format (all_posts_YYYY-MM-DD.csv)

### Commands:
- export: Export all posts from WordPress sites
- analyze [csv]: Analyze posts with AI (optional CSV input)
- recategorize [csv]: Recategorize posts with AI
- seo_check: Check SEO quality
- categories: Manage categories across sites
- approve [files]: Review and approve recommendations
- full_pipeline: Run complete workflow
- analytics, gaps, opportunities, report, status

### Changes:
- Moved all scripts to scripts/ directory
- Created config.yaml for configuration
- Updated all scripts to use output/ directory
- Deprecated old seo-cli.py in favor of new ./seo
- Added AGENTS.md and CHANGELOG.md documentation
- Consolidated README.md with updated usage

### Technical:
- Added PyYAML dependency
- Removed hardcoded configuration values
- All scripts now properly integrated
- Better error handling and user feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-02-16 14:24:44 +01:00

246 lines
8.1 KiB
PHP

<?php
/**
* Plugin Name: Rank Math API Manager Extended
* Plugin URI: https://github.com/devora-as/rank-math-api-manager
* Description: Extended version - Exposes REST API endpoints to READ and UPDATE Rank Math SEO metadata
* Version: 2.0
* Author: Extended by SEO Automation
* License: GPL2
*
* This is an extension of the original Rank Math API Manager plugin.
* It adds GET endpoints to read Rank Math SEO metadata, which are missing from the original.
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
class Rank_Math_API_Manager_Extended {
public function __construct() {
add_action('rest_api_init', array($this, 'register_routes'));
add_action('rest_api_init', array($this, 'register_meta_fields'));
}
/**
* Register REST API routes for GET operations
*/
public function register_routes() {
// GET: Retrieve meta for single post
register_rest_route('rank-math-api/v2', '/get-meta/(?P<post_id>\d+)', array(
'methods' => 'GET',
'callback' => array($this, 'get_post_meta'),
'permission_callback' => array($this, 'check_read_permission'),
'args' => array(
'post_id' => array(
'validate_callback' => function($param) {
return is_numeric($param);
},
),
),
));
// GET: Retrieve all posts with their Rank Math meta
register_rest_route('rank-math-api/v2', '/posts', array(
'methods' => 'GET',
'callback' => array($this, 'get_all_posts_with_meta'),
'permission_callback' => array($this, 'check_read_permission'),
'args' => array(
'per_page' => array(
'type' => 'integer',
'default' => 100,
'minimum' => 1,
'maximum' => 100,
),
'page' => array(
'type' => 'integer',
'default' => 1,
'minimum' => 1,
),
'status' => array(
'type' => 'string',
'default' => 'publish',
'enum' => array('publish', 'draft', 'pending', 'trash'),
),
),
));
// POST: Update meta (original endpoint, kept for compatibility)
register_rest_route('rank-math-api/v2', '/update-meta', array(
'methods' => 'POST',
'callback' => array($this, 'update_post_meta'),
'permission_callback' => array($this, 'check_edit_permission'),
));
}
/**
* Register meta fields in REST API for easier access
*/
public function register_meta_fields() {
$meta_fields = array(
'rank_math_description',
'rank_math_title',
'rank_math_focus_keyword',
'rank_math_canonical_url',
);
foreach ($meta_fields as $field) {
register_rest_field('post', $field, array(
'get_callback' => function($post) use ($field) {
return get_post_meta($post['id'], $field, true);
},
'update_callback' => function($value, $post) use ($field) {
return update_post_meta($post->ID, $field, $value);
},
'schema' => array(
'description' => 'Rank Math ' . str_replace('rank_math_', '', $field),
'type' => 'string',
),
));
}
}
/**
* GET: Retrieve meta for a single post
*/
public function get_post_meta($request) {
$post_id = $request['post_id'];
// Verify post exists
if (!get_post($post_id)) {
return new WP_Error('post_not_found', 'Post not found', array('status' => 404));
}
// Get all Rank Math meta fields
$meta_data = array(
'post_id' => $post_id,
'post_title' => get_the_title($post_id),
'post_url' => get_permalink($post_id),
'rank_math_title' => get_post_meta($post_id, 'rank_math_title', true),
'rank_math_description' => get_post_meta($post_id, 'rank_math_description', true),
'rank_math_focus_keyword' => get_post_meta($post_id, 'rank_math_focus_keyword', true),
'rank_math_canonical_url' => get_post_meta($post_id, 'rank_math_canonical_url', true),
);
return rest_ensure_response($meta_data);
}
/**
* GET: Retrieve all posts with their Rank Math meta (paginated)
*/
public function get_all_posts_with_meta($request) {
$per_page = $request['per_page'];
$page = $request['page'];
$status = $request['status'];
// Calculate offset
$offset = ($page - 1) * $per_page;
// Get posts
$posts = get_posts(array(
'numberposts' => $per_page,
'offset' => $offset,
'post_status' => $status,
'post_type' => 'post',
'orderby' => 'ID',
'order' => 'ASC',
));
// Build response with meta
$posts_with_meta = array();
foreach ($posts as $post) {
$posts_with_meta[] = array(
'id' => $post->ID,
'title' => $post->post_title,
'slug' => $post->post_name,
'url' => get_permalink($post->ID),
'status' => $post->post_status,
'rank_math_title' => get_post_meta($post->ID, 'rank_math_title', true),
'rank_math_description' => get_post_meta($post->ID, 'rank_math_description', true),
'rank_math_focus_keyword' => get_post_meta($post->ID, 'rank_math_focus_keyword', true),
'rank_math_canonical_url' => get_post_meta($post->ID, 'rank_math_canonical_url', true),
);
}
// Get total posts for pagination
$total = count(get_posts(array(
'numberposts' => -1,
'post_status' => $status,
'post_type' => 'post',
'fields' => 'ids',
)));
$response = rest_ensure_response($posts_with_meta);
$response->header('X-WP-Total', $total);
$response->header('X-WP-TotalPages', ceil($total / $per_page));
return $response;
}
/**
* POST: Update Rank Math meta (original functionality)
*/
public function update_post_meta($request) {
$post_id = $request['post_id'];
$params = $request->get_json_params();
// Verify post exists
if (!get_post($post_id)) {
return new WP_Error('post_not_found', 'Post not found', array('status' => 404));
}
$updatable_fields = array(
'rank_math_title',
'rank_math_description',
'rank_math_focus_keyword',
'rank_math_canonical_url',
);
$updated = array();
foreach ($updatable_fields as $field) {
if (isset($params[$field])) {
update_post_meta($post_id, $field, $params[$field]);
$updated[$field] = $params[$field];
}
}
return rest_ensure_response(array(
'success' => true,
'post_id' => $post_id,
'updated_fields' => $updated,
));
}
/**
* Check if user can read post meta
*/
public function check_read_permission($request) {
return current_user_can('read_posts');
}
/**
* Check if user can edit post meta
*/
public function check_edit_permission($request) {
return current_user_can('edit_posts');
}
}
// Initialize the plugin
new Rank_Math_API_Manager_Extended();
// Register activation hook to ensure compatibility
register_activation_hook(__FILE__, function() {
if (!function_exists('get_plugins')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
error_log('Rank Math API Manager Extended activated. Available endpoints:');
error_log('- GET /wp-json/rank-math-api/v2/get-meta/{post_id}');
error_log('- GET /wp-json/rank-math-api/v2/posts');
error_log('- POST /wp-json/rank-math-api/v2/update-meta');
});
?>