tigerstyle-heat/includes/api/class-sxg-api-client.php
Ryan Malloy 0028738e33 Initial commit: TigerStyle Heat v2.0.0
Make your WordPress site irresistible. Natural SEO attraction with:
- robots.txt management
- sitemap.xml generation
- LLMs.txt support
- Google integration (Analytics, Search Console, Tag Manager)
- Schema.org structured data
- Open Graph / Twitter Card meta tags
- AMP support
- Visual elements gallery
- Built-in backup/restore module

Includes build.sh and .distignore for WordPress-installable release ZIPs.
2026-05-27 13:41:35 -06:00

358 lines
11 KiB
PHP

<?php
/**
* SXG API Client
*
* Handles communication with external SXG API service
*
* @package TigerStyle_SEO
* @subpackage API
* @since 2.1.0
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
class TigerStyle_SEO_SXG_API_Client {
private $api_base_url;
private $api_key;
private $timeout;
private $cache_ttl;
public function __construct() {
$options = get_option('tigerstyle_heat_amp', []);
$this->api_base_url = $options['sxg_api_url'] ?? 'https://sxg-api.tigerstyle.com/v1';
$this->api_key = $options['sxg_api_key'] ?? '';
$this->timeout = 30;
$this->cache_ttl = 3600; // 1 hour
}
/**
* Check if API service is available
*/
public function is_service_available() {
$cache_key = 'tigerstyle_heat_sxg_api_status';
$cached_status = get_transient($cache_key);
if ($cached_status !== false) {
return $cached_status === 'available';
}
$response = $this->make_request('GET', '/health');
$is_available = $response && $response['status'] === 'healthy';
set_transient($cache_key, $is_available ? 'available' : 'unavailable', 300); // Cache for 5 minutes
return $is_available;
}
/**
* Register WordPress site with SXG API service
*/
public function register_site() {
$site_data = [
'domain' => parse_url(home_url(), PHP_URL_HOST),
'site_url' => home_url(),
'admin_email' => get_option('admin_email'),
'wordpress_version' => get_bloginfo('version'),
'plugin_version' => TIGERSTYLE_HEAT_VERSION,
'ssl_enabled' => is_ssl(),
'certificate_info' => $this->get_certificate_info()
];
$response = $this->make_request('POST', '/sites/register', $site_data);
if ($response && isset($response['api_key'])) {
// Store the generated API key
$options = get_option('tigerstyle_heat_amp', []);
$options['sxg_api_key'] = $response['api_key'];
$options['sxg_site_id'] = $response['site_id'];
update_option('tigerstyle_heat_amp', $options);
return $response;
}
return false;
}
/**
* Generate SXG for AMP content
*/
public function generate_sxg($url, $amp_content) {
if (!$this->api_key) {
return new WP_Error('no_api_key', 'SXG API key not configured');
}
// Check cache first
$cache_key = 'tigerstyle_heat_sxg_' . md5($url . $amp_content);
$cached_sxg = get_transient($cache_key);
if ($cached_sxg !== false) {
return $cached_sxg;
}
$sxg_data = [
'url' => $url,
'content' => $amp_content,
'timestamp' => time(),
'headers' => $this->get_sxg_headers(),
'options' => [
'max_age' => 86400, // 24 hours
'stale_while_revalidate' => 604800 // 7 days
]
];
$response = $this->make_request('POST', '/sxg/generate', $sxg_data);
if ($response && isset($response['sxg_package'])) {
// Cache the SXG package
set_transient($cache_key, $response, $this->cache_ttl);
return $response;
}
return new WP_Error('sxg_generation_failed', 'Failed to generate SXG package');
}
/**
* Validate AMP content before SXG generation
*/
public function validate_amp_content($content) {
$validation_data = [
'content' => $content,
'url' => get_permalink(),
'validation_level' => 'strict'
];
$response = $this->make_request('POST', '/amp/validate', $validation_data);
return $response;
}
/**
* Get amppackager configuration for local installation
*/
public function get_amppackager_config() {
$site_info = [
'domain' => parse_url(home_url(), PHP_URL_HOST),
'certificate_path' => '/etc/ssl/certs/' . parse_url(home_url(), PHP_URL_HOST) . '.pem',
'private_key_path' => '/etc/ssl/private/' . parse_url(home_url(), PHP_URL_HOST) . '.key',
'amp_endpoint' => home_url() . '/{path}/amp',
'sxg_endpoint' => home_url() . '/{path}/amp.sxg'
];
$response = $this->make_request('POST', '/config/amppackager', $site_info);
return $response;
}
/**
* Get certificate recommendations
*/
public function get_certificate_recommendations() {
$domain_info = [
'domain' => parse_url(home_url(), PHP_URL_HOST),
'hosting_provider' => $this->detect_hosting_provider(),
'current_certificate' => $this->get_certificate_info()
];
$response = $this->make_request('POST', '/certificates/recommendations', $domain_info);
return $response;
}
/**
* Test SXG infrastructure
*/
public function test_infrastructure() {
$test_data = [
'domain' => parse_url(home_url(), PHP_URL_HOST),
'test_url' => home_url() . '/test-amp',
'user_agent' => 'TigerStyle-SEO-SXG-Test/1.0'
];
$response = $this->make_request('POST', '/test/infrastructure', $test_data);
return $response;
}
/**
* Get SXG analytics and performance metrics
*/
public function get_sxg_analytics($days = 30) {
$params = [
'days' => $days,
'metrics' => ['requests', 'cache_hits', 'validation_errors', 'performance']
];
$response = $this->make_request('GET', '/analytics/sxg?' . http_build_query($params));
return $response;
}
/**
* Make HTTP request to SXG API
*/
private function make_request($method, $endpoint, $data = null) {
$url = rtrim($this->api_base_url, '/') . $endpoint;
$args = [
'method' => $method,
'timeout' => $this->timeout,
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'TigerStyle-SEO/' . TIGERSTYLE_HEAT_VERSION . ' WordPress/' . get_bloginfo('version'),
'Accept' => 'application/json'
]
];
// Add API key if available
if ($this->api_key) {
$args['headers']['Authorization'] = 'Bearer ' . $this->api_key;
}
// Add request data
if ($data && in_array($method, ['POST', 'PUT', 'PATCH'])) {
$args['body'] = wp_json_encode($data);
}
$response = wp_remote_request($url, $args);
if (is_wp_error($response)) {
error_log('SXG API Request Error: ' . $response->get_error_message());
return false;
}
$response_code = wp_remote_retrieve_response_code($response);
$response_body = wp_remote_retrieve_body($response);
if ($response_code >= 200 && $response_code < 300) {
return json_decode($response_body, true);
}
error_log("SXG API Error {$response_code}: {$response_body}");
return false;
}
/**
* Get certificate information
*/
private function get_certificate_info() {
if (!is_ssl()) {
return null;
}
$domain = parse_url(home_url(), PHP_URL_HOST);
// Try to get certificate info using OpenSSL
$cert_info = [];
try {
$context = stream_context_create([
'ssl' => [
'capture_peer_cert' => true,
'verify_peer' => false,
'verify_peer_name' => false
]
]);
$stream = stream_socket_client(
"ssl://{$domain}:443",
$errno,
$errstr,
10,
STREAM_CLIENT_CONNECT,
$context
);
if ($stream) {
$cert = stream_context_get_params($stream)['options']['ssl']['peer_certificate'];
$cert_data = openssl_x509_parse($cert);
if ($cert_data) {
$cert_info = [
'subject' => $cert_data['subject']['CN'] ?? $domain,
'issuer' => $cert_data['issuer']['CN'] ?? 'Unknown',
'valid_from' => date('Y-m-d H:i:s', $cert_data['validFrom_time_t']),
'valid_to' => date('Y-m-d H:i:s', $cert_data['validTo_time_t']),
'signature_algorithm' => $cert_data['signatureTypeSN'] ?? 'Unknown'
];
}
fclose($stream);
}
} catch (Exception $e) {
error_log('Certificate info extraction failed: ' . $e->getMessage());
}
return $cert_info;
}
/**
* Get SXG headers for WordPress
*/
private function get_sxg_headers() {
return [
'cache-control' => 'public, max-age=86400, stale-while-revalidate=604800',
'content-type' => 'text/html; charset=utf-8',
'vary' => 'Accept, AMP-Cache-Transform',
'amp-access-control-allow-source-origin' => home_url(),
'access-control-expose-headers' => 'AMP-Access-Control-Allow-Source-Origin'
];
}
/**
* Detect hosting provider for better recommendations
*/
private function detect_hosting_provider() {
$hosting_indicators = [
'WP Engine' => ['wpengine.com', 'WPEngine'],
'Kinsta' => ['kinsta.com', 'Kinsta'],
'Pantheon' => ['pantheonsite.io', 'Pantheon'],
'WordPress.com' => ['wordpress.com', 'Automattic'],
'SiteGround' => ['siteground.com', 'SiteGround'],
'Cloudflare' => ['cloudflare.com', 'Cloudflare'],
'DigitalOcean' => ['digitalocean.com', 'DigitalOcean'],
'AWS' => ['amazonaws.com', 'Amazon'],
'Google Cloud' => ['googleusercontent.com', 'Google']
];
$server_name = $_SERVER['SERVER_NAME'] ?? '';
$server_software = $_SERVER['SERVER_SOFTWARE'] ?? '';
$http_host = $_SERVER['HTTP_HOST'] ?? '';
foreach ($hosting_indicators as $provider => $indicators) {
foreach ($indicators as $indicator) {
if (stripos($server_name . $server_software . $http_host, $indicator) !== false) {
return $provider;
}
}
}
return 'Unknown';
}
/**
* Get API service status and capabilities
*/
public function get_service_info() {
return $this->make_request('GET', '/info');
}
/**
* Update API configuration
*/
public function update_config($config) {
$options = get_option('tigerstyle_heat_amp', []);
$options = array_merge($options, $config);
update_option('tigerstyle_heat_amp', $options);
// Update instance variables
$this->api_base_url = $options['sxg_api_url'] ?? $this->api_base_url;
$this->api_key = $options['sxg_api_key'] ?? $this->api_key;
return true;
}
}