Skip to main content
Glama
wordpress-theme-audit.ts22.3 kB
/** * WordPress Theme Comprehensive Auditor - Modern v4.3 * * Chains multiple analysis steps for comprehensive WordPress theme audit * Covers theme-specific security, performance, accessibility, and code quality */ import { BasePlugin } from '../../plugins/base-plugin.js'; import { IPromptPlugin } from '../shared/types.js'; import { ThreeStagePromptManager } from '../../core/ThreeStagePromptManager.js'; import { PromptStages } from '../../types/prompt-stages.js'; import { withSecurity } from '../../security/integration-helpers.js'; import { readFileContent } from '../shared/helpers.js'; import { ModelSetup, ResponseProcessor, ParameterValidator, ErrorHandler, MultiFileAnalysis, TokenCalculator } from '../../utils/plugin-utilities.js'; import { getAnalysisCache } from '../../cache/index.js'; // Common Node.js modules import { basename, dirname, extname, join, relative } from 'path'; import { readFile, stat, readdir } from 'fs/promises'; export class WordPressThemeAuditor extends BasePlugin implements IPromptPlugin { name = 'audit_wordpress_theme'; category = 'analyze' as const; description = 'Comprehensive WordPress theme audit - chains multiple analysis steps for security, performance, accessibility, SEO, and code quality'; parameters = { // Multi-file parameters (primary mode for theme audit) projectPath: { type: 'string' as const, description: 'Path to WordPress theme root directory', required: true }, // Analysis configuration auditDepth: { type: 'string' as const, description: 'Depth of audit analysis', enum: ['basic', 'detailed', 'comprehensive'], default: 'comprehensive', required: false }, auditType: { type: 'string' as const, description: 'Type of audit focus', enum: ['security', 'performance', 'accessibility', 'seo', 'quality', 'full-audit'], default: 'full-audit', required: false }, // Theme-specific analysis steps includeSteps: { type: 'array' as const, description: 'Analysis steps to include in theme audit', required: false, items: { type: 'string' as const }, default: ['structure', 'security', 'performance', 'accessibility', 'quality', 'seo'] }, maxDepth: { type: 'number' as const, description: 'Maximum directory depth for analysis (1-5)', required: false, default: 4 }, // WordPress-specific context wpVersion: { type: 'string' as const, description: 'Target WordPress version for compatibility checks', required: false, default: '6.4' }, phpVersion: { type: 'string' as const, description: 'Target PHP version for compatibility checks', required: false, default: '8.0' }, // Theme-specific options themeType: { type: 'string' as const, description: 'Type of WordPress theme', enum: ['classic', 'block', 'hybrid'], default: 'classic', required: false }, checkAccessibility: { type: 'boolean' as const, description: 'Include detailed accessibility audit', default: true, required: false } }; private analysisCache = getAnalysisCache(); private multiFileAnalysis = new MultiFileAnalysis(); constructor() { super(); } async execute(params: any, llmClient: any) { return await withSecurity(this, params, llmClient, async (secureParams) => { try { // 1. Validate WordPress theme structure this.validateWordPressTheme(secureParams); // 2. Setup model const { model, contextLength } = await ModelSetup.getReadyModel(llmClient); // 3. Execute chained theme analysis workflow return await this.executeChainedThemeAnalysis(secureParams, llmClient, model, contextLength); } catch (error: any) { return ErrorHandler.createExecutionError('audit_wordpress_theme', error); } }); } /** * Validate WordPress theme structure */ private validateWordPressTheme(params: any): void { ParameterValidator.validateProjectPath(params); ParameterValidator.validateDepth(params); ParameterValidator.validateEnum(params, 'auditType', ['security', 'performance', 'accessibility', 'seo', 'quality', 'full-audit']); ParameterValidator.validateEnum(params, 'auditDepth', ['basic', 'detailed', 'comprehensive']); ParameterValidator.validateEnum(params, 'themeType', ['classic', 'block', 'hybrid']); } /** * Execute the chained theme analysis workflow */ private async executeChainedThemeAnalysis(params: any, llmClient: any, model: any, contextLength: number) { const auditSteps = params.includeSteps || ['structure', 'security', 'performance', 'accessibility', 'quality', 'seo']; const results: Record<string, any> = {}; const stepExecutionLog: string[] = []; try { stepExecutionLog.push(`Starting WordPress theme audit with ${auditSteps.length} steps`); stepExecutionLog.push(`Theme type: ${params.themeType || 'classic'}`); // Step 1: Theme Structure Overview if (auditSteps.includes('structure')) { stepExecutionLog.push('Executing: Theme structure analysis'); results.structure = await this.runAnalysisStep('count_files', { projectPath: params.projectPath, analysisType: 'comprehensive', maxDepth: params.maxDepth }, llmClient); stepExecutionLog.push(`Structure analysis: ${results.structure.success ? 'SUCCESS' : 'FAILED'}`); } // Step 2: WordPress Theme Security Audit if (auditSteps.includes('security')) { stepExecutionLog.push('Executing: WordPress theme security analysis'); results.security = await this.runAnalysisStep('analyze_wordpress_security', { projectPath: params.projectPath, wpType: 'theme', wpVersion: params.wpVersion, analysisType: 'comprehensive', includeOwaspTop10: true }, llmClient); stepExecutionLog.push(`Security analysis: ${results.security.success ? 'SUCCESS' : 'FAILED'}`); } // Step 3: Performance Analysis (theme-specific) if (auditSteps.includes('performance')) { stepExecutionLog.push('Executing: Theme performance analysis'); results.performance = await this.runAnalysisStep('analyze_code_quality', { projectPath: params.projectPath, analysisType: 'performance', language: 'php', context: { projectType: 'wordpress-theme', themeType: params.themeType, focusAreas: ['performance', 'optimization'] } }, llmClient); stepExecutionLog.push(`Performance analysis: ${results.performance.success ? 'SUCCESS' : 'FAILED'}`); } // Step 4: Accessibility Audit if (auditSteps.includes('accessibility') && params.checkAccessibility) { stepExecutionLog.push('Executing: Accessibility analysis'); results.accessibility = await this.runAnalysisStep('analyze_single_file', { projectPath: params.projectPath, analysisType: 'comprehensive', context: { projectType: 'wordpress-theme', focusAreas: ['accessibility', 'wcag', 'semantic-html'], standards: ['WCAG 2.1 AA', 'Section 508'] } }, llmClient); stepExecutionLog.push(`Accessibility analysis: ${results.accessibility.success ? 'SUCCESS' : 'FAILED'}`); } // Step 5: Code Quality Assessment if (auditSteps.includes('quality')) { stepExecutionLog.push('Executing: Code quality analysis'); results.quality = await this.runAnalysisStep('analyze_code_quality', { projectPath: params.projectPath, analysisType: 'comprehensive', language: 'php', context: { projectType: 'wordpress-theme' } }, llmClient); stepExecutionLog.push(`Quality analysis: ${results.quality.success ? 'SUCCESS' : 'FAILED'}`); } // Step 6: SEO Analysis if (auditSteps.includes('seo')) { stepExecutionLog.push('Executing: SEO structure analysis'); results.seo = await this.runAnalysisStep('analyze_single_file', { projectPath: params.projectPath, analysisType: 'comprehensive', context: { projectType: 'wordpress-theme', focusAreas: ['seo', 'structured-data', 'meta-tags', 'performance'] } }, llmClient); stepExecutionLog.push(`SEO analysis: ${results.seo.success ? 'SUCCESS' : 'FAILED'}`); } // Step 7: Database Query Analysis (if applicable) if (auditSteps.includes('database')) { stepExecutionLog.push('Executing: Database query analysis'); results.database = await this.runAnalysisStep('analyze_database_queries', { projectPath: params.projectPath, analysisType: 'comprehensive', context: { projectType: 'wordpress-theme' } }, llmClient); stepExecutionLog.push(`Database analysis: ${results.database.success ? 'SUCCESS' : 'FAILED'}`); } // Step 8: Synthesize all results stepExecutionLog.push('Synthesizing comprehensive theme audit report'); const synthesizedResults = await this.synthesizeThemeAuditResults({ ...results, executionLog: stepExecutionLog, completedSteps: auditSteps.filter(step => results[step]?.success), failedSteps: auditSteps.filter(step => results[step]?.success === false) }, params, model, contextLength); stepExecutionLog.push('Theme audit synthesis: COMPLETED'); return synthesizedResults; } catch (error: any) { stepExecutionLog.push(`Theme audit failed: ${error.message}`); return ErrorHandler.createExecutionError('audit_wordpress_theme', error); } } /** * Run individual analysis step by calling other MCP functions */ private async runAnalysisStep(functionName: string, stepParams: any, llmClient: any): Promise<any> { try { // Check cache first const cacheKey = this.analysisCache.generateKey(functionName, stepParams, []); const cached = await this.analysisCache.get(cacheKey); if (cached) return cached; // Import the plugin loader to call other MCP functions const { PluginRegistry } = await import('../../plugins/index.js'); const pluginLoader = PluginRegistry.getInstance(); // Execute the specific analysis function let result; try { result = await pluginLoader.executePlugin(functionName, stepParams, llmClient); // Wrap successful results const wrappedResult = { stepName: functionName, parameters: stepParams, status: 'completed', timestamp: new Date().toISOString(), data: result.data || result, summary: `Completed ${functionName} analysis`, success: true }; // Cache the result await this.analysisCache.cacheAnalysis(cacheKey, wrappedResult, { modelUsed: result.modelUsed || 'unknown', executionTime: result.executionTimeMs || 0, timestamp: new Date().toISOString() }); return wrappedResult; } catch (pluginError: any) { // If the plugin doesn't exist or fails, return error result const errorResult = { stepName: functionName, status: 'failed', error: pluginError.message, timestamp: new Date().toISOString(), summary: `Failed ${functionName} analysis`, success: false }; return errorResult; } } catch (error: any) { return { stepName: functionName, status: 'system-error', error: error.message, timestamp: new Date().toISOString(), summary: 'System error during analysis', success: false }; } } /** * Synthesize all theme audit results into comprehensive report */ private async synthesizeThemeAuditResults(results: Record<string, any>, params: any, model: any, contextLength: number) { // Generate final synthesis prompt stages const promptStages = this.getMultiFilePromptStages({ ...params, analysisResult: results, stepCount: Object.keys(results).length }); // Always use chunking for comprehensive synthesis const promptManager = new ThreeStagePromptManager(); const chunkSize = TokenCalculator.calculateOptimalChunkSize(promptStages, contextLength); const dataChunks = promptManager.chunkDataPayload(promptStages.dataPayload, chunkSize); const conversation = promptManager.createChunkedConversation(promptStages, dataChunks); const messages = [ conversation.systemMessage, ...conversation.dataMessages, conversation.analysisMessage ]; return await ResponseProcessor.executeChunked( messages, model, contextLength, 'audit_wordpress_theme', 'multifile' ); } /** * Single-file mode not applicable for theme audit */ private getSingleFilePromptStages(params: any): PromptStages { const systemAndContext = `WordPress Theme Auditor - Single File Mode This mode is not recommended for WordPress theme audits. Use multi-file mode with projectPath parameter for comprehensive theme analysis.`; const dataPayload = `Single file analysis not supported for WordPress theme audits. Please use projectPath parameter to analyze the entire theme structure.`; const outputInstructions = `{ "error": "Single file mode not supported for WordPress theme audits", "recommendation": "Use projectPath parameter for comprehensive theme analysis" }`; return { systemAndContext, dataPayload, outputInstructions }; } /** * Multi-file prompt stages for comprehensive theme audit synthesis */ private getMultiFilePromptStages(params: any): PromptStages { const { analysisResult, auditType, auditDepth, wpVersion, phpVersion, themeType, stepCount } = params; const systemAndContext = `You are a senior WordPress theme developer and security expert with 15+ years of experience auditing enterprise WordPress themes for performance, accessibility, and security. **THEME AUDIT CONTEXT:** - Audit Type: ${auditType} - Audit Depth: ${auditDepth} - Analysis Steps Completed: ${stepCount} - Theme Type: ${themeType} - Target WordPress Version: ${wpVersion} - Target PHP Version: ${phpVersion} **YOUR EXPERTISE:** You are internationally recognized for: - WordPress theme security auditing and vulnerability assessment - Frontend performance optimization for WordPress themes - Accessibility compliance (WCAG 2.1 AA, Section 508) - SEO optimization and Core Web Vitals improvement - Theme architecture and template hierarchy mastery - WordPress.org theme repository review standards **THEME-SPECIFIC AUDIT METHODOLOGY:** 1. **Security Assessment**: Template injection, XSS, CSRF, data sanitization 2. **Performance Analysis**: Asset loading, image optimization, caching strategies 3. **Accessibility Review**: ARIA labels, keyboard navigation, screen reader support 4. **SEO Optimization**: Structured data, meta tags, page speed, mobile responsiveness 5. **Code Quality**: WordPress Coding Standards, template hierarchy compliance 6. **Architecture Review**: Child theme compatibility, customizer integration **CRITICAL THEME FOCUS AREAS:** - Template security: Proper escaping and sanitization in templates - Asset optimization: CSS/JS minification, critical path optimization - Accessibility compliance: Color contrast, focus management, semantic HTML - SEO implementation: Schema markup, Open Graph, Twitter Cards - Performance bottlenecks: Render-blocking resources, unused CSS - WordPress integration: Proper enqueueing, theme supports, customizer - Cross-browser compatibility and responsive design - Template hierarchy compliance and hook usage`; const dataPayload = `**COMPREHENSIVE THEME AUDIT RESULTS:** ${JSON.stringify(analysisResult, null, 2)}`; const outputInstructions = `**PROVIDE COMPREHENSIVE WORDPRESS THEME AUDIT REPORT:** { "executiveSummary": { "overallRating": "critical|high-risk|medium-risk|low-risk|excellent", "themeReadiness": "production-ready|needs-fixes|major-issues|not-ready", "primaryConcerns": ["concern1", "concern2", "concern3"], "strengths": ["strength1", "strength2"], "timeToFix": "immediate|1-2 days|1 week|2+ weeks", "wpOrgCompliance": "compliant|minor-issues|major-issues|non-compliant" }, "securityAssessment": { "criticalVulnerabilities": [ { "type": "XSS|CSRF|Template Injection|Data Exposure", "severity": "critical|high|medium|low", "location": "specific template and line", "description": "detailed vulnerability description", "exploit": "how this could be exploited in theme context", "fix": "specific theme security fix with code example" } ], "templateSecurity": { "escaping": "proper|inconsistent|missing", "sanitization": "proper|inconsistent|missing", "authorization": "proper|inconsistent|missing" }, "securityScore": "A|B|C|D|F" }, "performanceAssessment": { "coreWebVitals": { "lcp": "good|needs-improvement|poor", "fid": "good|needs-improvement|poor", "cls": "good|needs-improvement|poor" }, "assetOptimization": { "css": "optimized|needs-optimization|poor", "javascript": "optimized|needs-optimization|poor", "images": "optimized|needs-optimization|poor" }, "performanceIssues": [ { "type": "Render Blocking|Unused CSS|Large Images|Slow Queries", "severity": "critical|high|medium|low", "location": "specific file or template", "impact": "performance impact description", "optimization": "specific optimization recommendation" } ], "performanceScore": "A|B|C|D|F" }, "accessibilityAssessment": { "wcagCompliance": { "level": "AA|A|Non-compliant", "score": "A|B|C|D|F" }, "accessibilityIssues": [ { "type": "Color Contrast|Keyboard Navigation|Screen Reader|ARIA|Focus Management", "severity": "critical|high|medium|low", "location": "specific template or component", "wcagCriterion": "1.4.3|2.1.1|4.1.2|etc", "fix": "specific accessibility fix with code example" } ], "keyboardNavigation": "full|partial|broken", "screenReaderSupport": "excellent|good|poor" }, "seoAssessment": { "technicalSeo": { "structuredData": "implemented|partial|missing", "metaTags": "complete|incomplete|missing", "performance": "fast|average|slow" }, "seoIssues": [ { "type": "Missing Meta|No Structured Data|Slow Loading|Poor Mobile", "severity": "high|medium|low", "impact": "SEO impact description", "recommendation": "specific SEO improvement" } ], "seoScore": "A|B|C|D|F" }, "codeQualityAssessment": { "wordpressStandards": { "phpCompliance": "high|medium|low", "cssCompliance": "high|medium|low", "jsCompliance": "high|medium|low" }, "themeStructure": { "templateHierarchy": "proper|issues|broken", "childThemeSupport": "excellent|good|poor", "customizerIntegration": "complete|partial|missing" }, "qualityScore": "A|B|C|D|F" }, "actionPlan": { "immediate": [ { "priority": 1, "task": "fix critical security vulnerability", "category": "security|performance|accessibility|seo|quality", "estimatedTime": "2 hours", "risk": "critical|high|medium|low" } ], "shortTerm": [ { "priority": 2, "task": "optimize Core Web Vitals", "category": "performance", "estimatedTime": "4 hours", "risk": "medium" } ], "longTerm": [ { "priority": 3, "task": "improve accessibility compliance", "category": "accessibility", "estimatedTime": "2 days", "risk": "low" } ] }, "complianceReport": { "wordpressOrgReady": true, "accessibilityCompliant": true, "performanceOptimized": false, "issuesBlocking": ["issue1", "issue2"], "recommendationsForSubmission": ["recommendation1", "recommendation2"] } } **REQUIREMENTS:** - Provide specific template file names and line numbers for all issues - Include code examples for theme-specific fixes where applicable - Prioritize findings by user impact and compliance requirements - Focus on WordPress theme-specific best practices and standards - Ensure all recommendations are testable and implementable - Consider theme type (classic vs block) in recommendations`; return { systemAndContext, dataPayload, outputInstructions }; } /** * Backwards compatibility method */ getPromptStages(params: any): PromptStages { return this.getMultiFilePromptStages(params); } // Unused methods for theme audit workflow private async discoverRelevantFiles(projectPath: string, maxDepth: number, analysisType: string): Promise<string[]> { const extensions = ['.php', '.css', '.js', '.json', '.xml', '.txt', '.md', '.scss', '.sass']; return await this.multiFileAnalysis.discoverFiles(projectPath, extensions, maxDepth); } private async performMultiFileAnalysis(files: string[], params: any, model: any, contextLength: number): Promise<any> { return {}; } private async analyzeIndividualFile(file: string, params: any, model: any): Promise<any> { return {}; } private getFileExtensions(analysisType: string): string[] { return ['.php', '.css', '.js', '.json', '.xml', '.txt', '.md', '.scss', '.sass']; } private generateCacheKey(files: string[], params: any): string { const fileHash = files.join('|'); const paramHash = JSON.stringify(params); return `${fileHash}_${paramHash}`.substring(0, 64); } } export default WordPressThemeAuditor;

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/houtini-ai/lm'

If you have feedback or need assistance with the MCP directory API, please join our Discord server