Skip to main content
Glama

wordpress_plugin_readiness

Analyzes WordPress plugins for security vulnerabilities, coding standards, performance issues, and WordPress.org submission requirements to ensure compliance and readiness.

Instructions

Comprehensive WordPress plugin readiness check for security, best practices, and WordPress.org submission

WORKFLOW: Perfect for understanding complex code, identifying issues, and technical debt assessment TIP: Use Desktop Commander to read files, then pass content here for analysis SAVES: Claude context for strategic decisions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
analysisDepthNoLevel of analysis detailcomprehensive
includeStepsNoSpecific analysis steps to include
maxDepthNoMaximum directory depth for file discovery (1-5)
maxFilesNoMaximum number of PHP files to analyze
phpVersionNoTarget PHP version for compatibility8.0
projectPathYesPath to WordPress plugin root directory
wpVersionNoTarget WordPress version for compatibility6.4

Implementation Reference

  • Main handler function that executes the WordPress plugin readiness analysis tool logic, including validation, file discovery, analysis, prompt generation, and LLM execution.
    async execute(params: any, llmClient: any) { return await withSecurity(this, params, llmClient, async (secureParams) => { try { // 1. Validate parameters ParameterValidator.validateProjectPath(secureParams); ParameterValidator.validateDepth(secureParams); ParameterValidator.validateEnum(secureParams, 'analysisDepth', ['basic', 'detailed', 'comprehensive']); // 2. Setup model const { model, contextLength } = await ModelSetup.getReadyModel(llmClient); // 3. Discover PHP files in the plugin const phpFiles = await this.discoverPHPFiles( secureParams.projectPath, secureParams.maxDepth, secureParams.maxFiles ); // 4. Analyze the plugin structure const analysisResult = await this.performPluginAnalysis( phpFiles, secureParams, model, contextLength ); // 5. Generate comprehensive prompt const promptStages = this.getPromptStages({ ...secureParams, analysisResult, fileCount: phpFiles.length }); // 6. Execute with chunking (always needed for comprehensive analysis) 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, 'wordpress_plugin_readiness', 'multifile' ); } catch (error: any) { return ErrorHandler.createExecutionError('wordpress_plugin_readiness', error); } }); }
  • Schema definition for the tool's input parameters including project path, analysis depth, WordPress/PHP versions, and file limits.
    parameters = { // Primary parameter - WordPress plugin directory projectPath: { type: 'string' as const, description: 'Path to WordPress plugin root directory', required: true }, // Analysis configuration analysisDepth: { type: 'string' as const, description: 'Level of analysis detail', enum: ['basic', 'detailed', 'comprehensive'], default: 'comprehensive', required: false }, includeSteps: { type: 'array' as const, description: 'Specific analysis steps to include', required: false, default: ['structure', 'security', 'database', 'quality', 'standards', 'performance'], items: { type: 'string' as const } }, // WordPress configuration wpVersion: { type: 'string' as const, description: 'Target WordPress version for compatibility', required: false, default: '6.4' }, phpVersion: { type: 'string' as const, description: 'Target PHP version for compatibility', required: false, default: '8.0' }, // File analysis limits maxDepth: { type: 'number' as const, description: 'Maximum directory depth for file discovery (1-5)', required: false, default: 3 }, maxFiles: { type: 'number' as const, description: 'Maximum number of PHP files to analyze', required: false, default: 50 } };
  • Tool class registration defining the tool name 'wordpress_plugin_readiness', category 'analyze', and description.
    export class WordPressPluginReadiness extends BasePlugin implements IPromptPlugin { name = 'wordpress_plugin_readiness'; category = 'analyze' as const; description = 'Comprehensive WordPress plugin readiness check for security, best practices, and WordPress.org submission';
  • Helper function to discover PHP files and critical files in the WordPress plugin directory.
    private async discoverPHPFiles( projectPath: string, maxDepth: number, maxFiles: number ): Promise<string[]> { const phpFiles: string[] = []; const scanDirectory = async (dir: string, depth: number = 0) => { if (depth > maxDepth || phpFiles.length >= maxFiles) return; try { const items = await readdir(dir); for (const item of items) { if (phpFiles.length >= maxFiles) break; const fullPath = join(dir, item); const itemStat = await stat(fullPath); if (itemStat.isDirectory()) { // Skip common non-code directories if (!item.startsWith('.') && item !== 'node_modules' && item !== 'vendor' && item !== 'tests' && item !== '.git') { await scanDirectory(fullPath, depth + 1); } } else if (item.endsWith('.php')) { phpFiles.push(fullPath); } } } catch (error) { // Continue scanning even if one directory fails } }; await scanDirectory(projectPath); // Also check for critical WordPress files in root const criticalFiles = ['readme.txt', 'license.txt', 'LICENSE']; for (const file of criticalFiles) { const fullPath = join(projectPath, file); try { await stat(fullPath); phpFiles.push(fullPath); // Include these for completeness check } catch { // File doesn't exist, will be flagged in analysis } } return phpFiles; }
  • Helper function to analyze individual PHP files for security, database, and standards issues.
    private async analyzeFile(file: string, content: string, params: any): Promise<any> { const analysis: any = { filePath: relative(params.projectPath, file), fileName: basename(file), size: content.length, lines: content.split('\n').length, security: [], database: [], standards: [] }; // Check for plugin header (main plugin file) if (content.includes('Plugin Name:') && content.includes('*/')) { analysis.isMainPluginFile = true; analysis.pluginHeaders = this.extractPluginHeaders(content); } // Security checks if (content.match(/\$_(GET|POST|REQUEST|SERVER|COOKIE)\[/)) { analysis.security.push({ type: 'INPUT_VALIDATION', pattern: 'Direct superglobal usage without sanitization' }); } if (content.includes('$wpdb->query') && !content.includes('$wpdb->prepare')) { analysis.security.push({ type: 'SQL_INJECTION', pattern: 'Database query without prepare statement' }); } if (content.match(/wp_ajax_\w+/) && !content.includes('check_ajax_referer')) { analysis.security.push({ type: 'NONCE_MISSING', pattern: 'AJAX handler without nonce verification' }); } if (content.includes('add_menu_page') && !content.includes('current_user_can')) { analysis.security.push({ type: 'CAPABILITY_CHECK', pattern: 'Admin page without capability check' }); } // Database patterns if (content.includes('$wpdb')) { const queries = content.match(/\$wpdb->(query|get_results|get_var|get_row)/g); if (queries) { analysis.database = queries.map(q => ({ type: q.replace('$wpdb->', ''), hasPrepare: content.includes('$wpdb->prepare') })); } } // Standards checks if (content.match(/function [A-Z]/)) { analysis.standards.push({ type: 'NAMING_CONVENTION', pattern: 'Function name starts with uppercase (should be lowercase)' }); } if (!content.includes('defined') && !content.includes('ABSPATH')) { analysis.standards.push({ type: 'DIRECT_ACCESS', pattern: 'Missing direct file access prevention' }); } return analysis; }

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