cacheName = 'schema'; parent::__construct(); $this->registry = SchemaBuilder::getInstance(); } /** * Register REST routes */ public function registerRoutes(): void { Route::for('seo') ->post([$this, 'handleSEO']) ->auth('admin') ->args([ 'action' => 'string|required|enum:save,reset,preview', 'context'=> 'string|required' ]) ->rateLimit(30) ->register(); Route::for('seo/fields') ->get([$this, 'getFields']) ->auth('admin') ->args([ 'type'=>'string|required' ]) ->register(); } /** * Main SEO handler - routes to appropriate action */ public function handleSEO(WP_REST_Request $request): WP_REST_Response { $action = $request->get_param('action') ?? 'save'; $context = $request->get_param('context'); // Verify context is valid if (!$this->isValidContext($context)) { return $this->validationError([ 'context' => "Invalid context: {$context}" ]); } return match($action) { 'save' => $this->saveSEO($request), 'reset' => $this->resetSEO($request), 'preview' => $this->previewSchema($request), default => $this->validationError(['action' => 'Invalid action']) }; } /** * Save SEO configuration */ protected function saveSEO(WP_REST_Request $request): WP_REST_Response { $context = $request->get_param('context'); $data = $request->get_json_params(); // Remove action and context from data unset($data['action'], $data['context']); // Handle site-wide settings if (in_array($context, ['site', 'business'])) { return $this->saveSiteSettings($context, $data); } // Handle content/taxonomy/user type settings return $this->saveTypeSettings($context, $data); } /** * Save site-wide settings (WebSite or Organization) */ protected function saveSiteSettings(string $context, array $data): WP_REST_Response { $errors = []; $config = ConfigManager::for($context); $result = $config->updateConfig($data); if (is_wp_error($result)) { $errors[$context] = [ 'message' => $result->get_error_message(), 'errors' => $result->get_error_data() ]; } if (!empty($errors)) { return $this->validationError($errors); } // Invalidate cache $this->cache->flush(); return$this->success(['message'=>ucfirst($context).' settings saved successfully']); } /** * Save content/taxonomy/user type settings */ protected function saveTypeSettings(string $type, array $data): WP_REST_Response { $config = ConfigManager::for($type); // Separate meta and schema data if needed $meta = $data['meta'] ?? []; $schema = $data['schema'] ?? $data; // If no separation, treat all as schema $errors = []; // Save meta configuration if (!empty($meta)) { $metaResult = $config->updateMeta($meta); if (is_wp_error($metaResult)) { $errors['meta'] = [ 'message' => $metaResult->get_error_message(), 'errors' => $metaResult->get_error_data() ]; } } // Save schema configuration if (!empty($schema)) { $schemaResult = $config->updateConfig($schema); if (is_wp_error($schemaResult)) { $errors['schema'] = [ 'message' => $schemaResult->get_error_message(), 'errors' => $schemaResult->get_error_data() ]; } } if (!empty($errors)) { return $this->validationError($errors); } // Invalidate cache $this->cache->flush(); return $this->success(['status'=> 'completed', 'message' => 'Configuration saved successfully']); } /** * Reset SEO configuration to defaults */ protected function resetSEO(WP_REST_Request $request): WP_REST_Response { $context = $request->get_param('context'); $data = $request->get_json_params(); $resetMeta = $data['resetMeta'] ?? false; $resetSchema = $data['resetSchema'] ?? false; $config = ConfigManager::for($context); // Reset based on what was requested if ($resetMeta) { $config->resetMeta(); } if ($resetSchema) { $config->resetConfig(); } if (!$resetMeta && !$resetSchema) { // Default: reset everything $config->resetAll(); } // Invalidate cache $this->cache->flush(); return $this->success([ 'status' => 'completed', 'message' => 'Reset to defaults successfully', 'meta' => $config->meta(), 'schema' => $config->schema() ]); } /** * Preview schema output */ protected function previewSchema(WP_REST_Request $request): WP_REST_Response { $data = $request->get_json_params(); $schemaType = $data['type'] ?? 'Thing'; // Get field definitions from registry $fieldDefinitions = $this->registry->getMetaConfigForType($schemaType); // Build schema with actual form values $schema = [ '@type' => $schemaType, '@id' => get_home_url() . '/#' . strtolower($schemaType), ]; // Add fields with their actual values foreach ($data['fields'] ?? [] as $fieldName => $value) { if (empty($value)) { continue; } $schema[$fieldName] = $value; } return $this->success([ 'schema' => $schema ]); } /** * Get fields for a schema type * Used for dynamic type switching */ public function getFields(WP_REST_Request $request): WP_REST_Response { $type = $request->get_param('type'); // Get Meta field definitions from registry $fields = $this->registry->getMetaConfigForType($type); return $this->success($fields); } /** * Validate context is a valid type */ protected function isValidContext(string $context): bool { // Site-wide contexts if (in_array($context, ['site', 'business'])) { return true; } // Check if it's a valid content/taxonomy/user type return $this->checkContent($context, true); } }