Batch45: All in One SEO tools (guarded, net-new, read-only)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8t9GEyyLZbUQu26na1JQg
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Batch 45 — All in One SEO (AIOSEO v4) tools, read-only (reads the aioseo_posts table).
|
||||
* Net-new, GPL-2.0-or-later. See NOTICE.md. Inert unless AIOSEO (AIOSEO_VERSION) is active.
|
||||
* Read-only by design: AIOSEO caches its meta, so writes go through its own UI/API, not here.
|
||||
*/
|
||||
|
||||
namespace AskTamMCP\Extensions;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class Batch45 {
|
||||
|
||||
public static function register($registry): void {
|
||||
if (!defined('AIOSEO_VERSION')) return;
|
||||
|
||||
$def = function (string $name, string $desc, array $props, array $required, string $scope, string $method) {
|
||||
$schema = ['type' => 'object', 'properties' => $props ?: new \stdClass()];
|
||||
if ($required) $schema['required'] = $required;
|
||||
return ['name' => $name, 'description' => $desc, 'scope' => $scope,
|
||||
'handler' => 'AskTamMCP\\Extensions\\Batch45::' . $method, 'inputSchema' => $schema];
|
||||
};
|
||||
|
||||
$registry->register($def('aioseo_detect', 'Report whether All in One SEO is active and its version.', [], [], 'read', 'detect'));
|
||||
$registry->register($def('aioseo_get_meta', 'Get AIOSEO SEO meta for a post: title, description, keyphrase, canonical.',
|
||||
['post_id' => ['type' => 'integer']], ['post_id'], 'read', 'getMeta'));
|
||||
$registry->register($def('aioseo_bulk_audit', 'Audit AIOSEO posts for missing title/description (reads the aioseo_posts table).',
|
||||
['per_page' => ['type' => 'integer', 'default' => 50]], [], 'read', 'bulkAudit'));
|
||||
}
|
||||
|
||||
public static function detect(array $args): array {
|
||||
return ['active' => defined('AIOSEO_VERSION'), 'version' => defined('AIOSEO_VERSION') ? AIOSEO_VERSION : null];
|
||||
}
|
||||
|
||||
private static function tbl(): string { global $wpdb; return $wpdb->prefix . 'aioseo_posts'; }
|
||||
private static function has(): bool { global $wpdb; $t = self::tbl(); return $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $t)) === $t; }
|
||||
|
||||
public static function getMeta(array $args): array {
|
||||
global $wpdb;
|
||||
if (!self::has()) return ['supported' => false, 'note' => 'aioseo_posts table not found.'];
|
||||
$id = (int) ($args['post_id'] ?? 0);
|
||||
$t = self::tbl();
|
||||
$r = $wpdb->get_row($wpdb->prepare("SELECT title, description, keyphrases, canonical_url FROM {$t} WHERE post_id = %d", $id), ARRAY_A);
|
||||
if (!$r) return ['post_id' => $id, 'found' => false];
|
||||
return ['post_id' => $id, 'found' => true, 'title' => $r['title'], 'description' => $r['description'],
|
||||
'keyphrases' => $r['keyphrases'], 'canonical' => $r['canonical_url']];
|
||||
}
|
||||
|
||||
public static function bulkAudit(array $args): array {
|
||||
global $wpdb;
|
||||
if (!self::has()) return ['supported' => false, 'note' => 'aioseo_posts table not found.', 'issues' => []];
|
||||
$t = self::tbl();
|
||||
$per = max(1, (int) ($args['per_page'] ?? 50));
|
||||
$rows = $wpdb->get_results($wpdb->prepare("SELECT post_id, title, description FROM {$t} ORDER BY post_id DESC LIMIT %d", $per), ARRAY_A);
|
||||
$issues = [];
|
||||
foreach ((array) $rows as $r) {
|
||||
$miss = [];
|
||||
if (empty($r['title'])) $miss[] = 'title';
|
||||
if (empty($r['description'])) $miss[] = 'description';
|
||||
if ($miss) $issues[] = ['post_id' => (int) $r['post_id'], 'title' => get_the_title((int) $r['post_id']), 'missing' => $miss];
|
||||
}
|
||||
return ['supported' => true, 'checked' => count((array) $rows), 'offenders' => count($issues), 'issues' => $issues];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user