The loud-mouthed mechanic your WordPress site desperately needs.
Roko is a comprehensive WordPress optimization and health monitoring plugin that diagnoses performance bottlenecks, security vulnerabilities, plugin conflicts, and maintenance issues. Built with Domain-Driven Design (DDD) architectural patterns to demonstrate clean code practices in WordPress development.
Roko demonstrates clean architecture principles with strict separation of concerns across four distinct layers. This example shows the Security domain - similar patterns are applied across Performance, Monitoring, and other domains:
graph TD
subgraph "🌐 Presentation Layer"
REST["SecurityJsonService<br/>REST API Endpoints"]
end
subgraph "🎯 Application Layer"
APP["SecurityApplicationService<br/>Translates Business Codes"]
INTRF["SecurityTranslationProviderInterface<br/>Infrastructure Contracts"]
end
subgraph "🏛️ Domain Layer"
AGG["SecurityAggregate<br/>Emits Business Codes"]
CHECKS["SecurityKeysChecks<br/>Pure Business Logic"]
ENTITIES["Domain Entities<br/>SecurityKeys, Check, etc."]
end
subgraph "🔌 Infrastructure Layer"
WP_TRANS["WpSecurityTranslationProvider<br/>WordPress Implementation"]
WP_REPO["WpSecurityKeysProvider<br/>WordPress Data Access"]
I18N["SecurityKeysChecksI18n<br/>Translation Strings"]
end
REST --> APP
APP --> AGG
AGG --> CHECKS
CHECKS --> ENTITIES
WP_TRANS -.->|implements| INTRF
WP_REPO --> AGG
WP_TRANS --> I18N
classDef presentation fill:#e1f5fe
classDef application fill:#f3e5f5
classDef domain fill:#e8f5e8
classDef infrastructure fill:#fff3e0
class REST presentation
class APP,INTRF application
class AGG,CHECKS,ENTITIES domain
class WP_TRANS,WP_REPO,I18N infrastructure
| Layer | May Import/Depend On | Never Imports | Example Classes |
|---|---|---|---|
| 🌐 Presentation | Application DTOs/Commands | Domain or Infrastructure directly | SecurityJsonService |
| 🎯 Application | Domain abstractions, owns interfaces | Infrastructure concretes | SecurityApplicationService |
| 🏛️ Domain | Nothing (pure) | Infrastructure, frameworks, UI | SecurityAggregate, SecurityKeysChecks |
| 🔌 Infrastructure | Domain types, Application interfaces | Nothing above it | WpSecurityTranslationProvider |
graph LR
PRES[🌐 Presentation] --> APP[🎯 Application]
APP --> DOM[🏛️ Domain]
INFRA[🔌 Infrastructure] --> APP
INFRA --> DOM
DOM -.->|"❌ Never depends on"| INFRA
APP -.->|"❌ Never imports"| INFRA
classDef presentation fill:#e1f5fe
classDef application fill:#f3e5f5
classDef domain fill:#e8f5e8
classDef infrastructure fill:#fff3e0
class PRES presentation
class APP application
class DOM domain
class INFRA infrastructure
This shows the Security domain as an example - similar patterns are used for Performance, Monitoring, and other domains:
src/
├── 🏛️ Domain/
│ ├── Security/ # Security Domain (shown as example)
│ │ ├── SecurityAggregate.php # Aggregate Root
│ │ ├── Checks/
│ │ │ ├── SecurityKeysChecks.php # Domain Service
│ │ │ └── ValueObject/
│ │ │ ├── Check.php # Value Object
│ │ │ ├── CheckStatus.php # Enum-like Value Object
│ │ │ └── Severity.php # Enum-like Value Object
│ │ └── SecurityKeys/
│ │ ├── Entity/
│ │ │ └── SecurityKeys.php # Domain Entity
│ │ └── ValueObject/
│ │ └── SecurityKey.php # Value Object
│ ├── Performance/ # Performance Domain (similar structure)
│ ├── Monitoring/ # Monitoring Domain (similar structure)
│ └── ... # Other domains follow same patterns
├── 🎯 Application/
│ └── Security/ # Application layer for Security domain
│ ├── SecurityApplicationService.php # Use Case Orchestrator
│ └── Provider/
│ └── SecurityTranslationProviderInterface.php # Contract
└── 🔌 Infrastructure/
└── WordPress/ # WordPress details, hooks, $wpdb, get_post, i18, etc
├── Plugin.php # DI Container & Bootstrap
└── Security/ # Infrastructure for Security domain
├── SecurityJsonService.php # REST Controller
├── WpSecurityKeysProvider.php # Data Access
├── Provider/
│ └── WpSecurityTranslationProvider.php
└── I18n/
└── SecurityKeysChecksI18n.php
Domain entities emit business codes - Application layer handles translation:
// ✅ Domain emits business codes, never handles i18n
class SecurityKeysChecks {
public static function fromSecurityKeys(SecurityKeys $securityKeys): self {
// Pure business logic
$recommendationCode = $strength . '_' . $source; // Business code: "weak_constant"
return new Check(
$id, $label, $status, $severity, $description, $evidence,
$recommendationCode, // Domain emits codes like "SEC_KEY_WEAK"
'roko'
);
}
}
// ✅ Application translates business codes to human text
class SecurityApplicationService {
public function getSecuritySnapshot() {
$domainSnapshot = $this->securityAggregate->snapshot(); // Gets business codes
return $this->translateBusinessCodes($domainSnapshot); // Converts to human text
}
}Each application service focuses on one specific use case:
// ✅ Focused, single-responsibility service
class SecurityApplicationService {
public function getSecuritySnapshot() {
// Get translations from infrastructure
$recommendations = $this->translationProvider->getAllSecurityKeyRecommendations();
// Let domain handle its own serialization
return $this->securityAggregate->snapshot($recommendations);
}
}Clean contracts between layers:
// ✅ Application defines what it needs
interface SecurityTranslationProviderInterface {
public function getAllSecurityKeyRecommendations();
}
// ✅ Infrastructure provides WordPress-specific implementation
class WpSecurityTranslationProvider implements SecurityTranslationProviderInterface {
public function getAllSecurityKeyRecommendations() {
// WordPress-specific translation logic
}
}Infrastructure implements interfaces defined by Application layer:
// ✅ Application defines the contract
interface SecurityTranslationProviderInterface {
public function getAllSecurityKeyRecommendations();
}
// ✅ Infrastructure implements the contract
class WpSecurityTranslationProvider implements SecurityTranslationProviderInterface {
public function getAllSecurityKeyRecommendations() {
// WordPress-specific implementation.
// Hooks lives here as well.
}
}
// ✅ Application depends on abstraction, not concrete
class SecurityApplicationService {
public function __construct(
SecurityAggregate $securityAggregate,
SecurityTranslationProviderInterface $provider // ← Interface, not concrete
) {
// Infrastructure implementation injected at runtime
}
}All dependencies wired at the application entry point:
// ✅ Clean dependency injection
class Plugin {
public function init() {
// Domain layer - pure business logic
$securityAggregate = new SecurityAggregate(/*...*/);
// Infrastructure providers (implement Application interfaces)
$translationProvider = new WpSecurityTranslationProvider();
// Application layer - receives Infrastructure via interfaces
$securityApplicationService = new SecurityApplicationService(
$securityAggregate,
$translationProvider // ← Concrete injected, but Application sees interface
);
// Presentation layer - REST API endpoints
new SecurityJsonService($securityApplicationService);
}
}Once you have bulletproof patterns, adding new features becomes predictable and "boring" - exactly as it should be. Creative solutions introduce bugs. Not on this system.
Every security feature follows the exact same ceremony. No exceptions. No shortcuts. No "clever" workarounds.
❌ "Let me just bypass the repository this one time..."
❌ "I'll handle this edge case differently..."
❌ "This feature is simple, no need for the full pattern..."
❌ "I know a clever way to do this..."
✅ Repository pattern? ALWAYS.
✅ Domain service? ALWAYS.
✅ Translation abstraction? ALWAYS.
✅ Business codes? ALWAYS.
When adding any new security feature, just follow the existing pattern:
// Add your entities, value objects, and domain service
src/Domain/Security/SshKeys/
├── Entity/SshKeyCollection.php # Your business data
├── ValueObject/SshKey.php # Immutable values
└── ../../Checks/SshKeyChecks.php # Transform into Check objects
class SshKeyChecks {
public static function fromSshKeyCollection(SshKeyCollection $collection): self {
// Pure business logic - emit business codes, never translate
return new Check($id, $label, $status, $severity, $description, $evidence, 'ssh_key_weak', 'roko');
}
}// Add repository and translation implementation
src/Infrastructure/WordPress/
├── Repository/WpSshKeyRepository.php # Data access
└── Security/I18n/SshKeyChecksI18n.php # Business code translations
class SshKeyChecksI18n {
public static function recommendation($businessCode) {
return ['ssh_key_weak' => __('Fix SSH keys...', 'roko')][$businessCode] ?? '';
}
}// Just copy what SecurityKeysChecks, FileSecurityChecks, etc. already do:
// Add to SecurityAggregate.php (follow existing pattern):
$sshKeyChecks = SshKeyChecks::fromSshKeyCollection($this->sshKeyRepository->getCollection());
$snapshot['sections'][] = ['id' => 'ssh_keys', 'checks' => $sshKeyChecks->toArray()];
// Add to WpSecurityTranslationProvider.php (follow existing pattern):
public function getSshKeyRecommendation($code) { return SshKeyChecksI18n::recommendation($code); }
// Add to SecurityApplicationService.php (follow existing pattern):
if ($section['id'] === 'ssh_keys') { /* translate business codes */ }That's it. Presentation layer (REST API) and Application layer (orchestration) already handle everything automatically.
Bug Prevention
- No creative solutions means no unexpected edge cases
- Consistent patterns are easy to review and test
- Standardized flow prevents architectural mistakes
Development Speed
- No decision fatigue - follow the pattern, ship the feature
- Copy-paste architecture enables faster implementation
- Predictable debugging - issues appear in expected places
Team Efficiency
- Code reviews focus on pattern compliance
- Onboarding is simple - learn the pattern once, apply everywhere
- No architectural debates - decisions already made
The frontend JavaScript already handles your new feature automatically:
// ✅ Your new SSH key checks appear automatically
const sshSection = this.get_section('ssh_keys'); // Automatic
const failedSshChecks = this.get_checks_by_status('fail'); // Automatic
const sshCard = this.render_section_card('ssh_keys'); // Automatic// ❌ Creative Developer's Approach
if ($sshKeysVulnerable) {
wp_die('SSH problem!'); // "Quick fix"
}
// ✅ Your System's Approach
class SshKeyChecks {
public static function fromSshKeyCollection(SshKeyCollection $collection): self {
// Pure business logic
// Predictable transformation
// Consistent with all other *Checks classes
// Zero surprises
}
}After following this ceremony 4 times (SecurityKeys, FileSecurity, FileIntegrity, Vulnerabilities), you now have:
- ✅ Bulletproof patterns that prevent bugs
- ✅ Zero-decision development - just follow the steps
- ✅ Self-documenting code - every feature looks identical
- ✅ Junior-dev-proof architecture - impossible to break
- ✅ Frontend that auto-adapts to new security features
Consistent patterns produce reliable results.
Roko is your WordPress site's diagnostic tool, covering multiple areas:
- Plugin Performance Heatmap: Identifies slow plugins dragging down load times
- Database Optimization: Cleans up bloated tables and unused data
- Core Web Vitals Tracking: Monitors TTFB, LCP, CLS metrics
- Query Analysis: Spots inefficient database queries
- Security Keys Analysis: Evaluates WordPress security keys and salts
- File Integrity Monitoring: Detects unauthorized file modifications
- Vulnerability Scanning: Checks for known security issues
- File Permission Auditing: Validates proper file and directory permissions
- Plugin Conflict Detection: Isolates problematic plugin combinations
- Multi-site Dashboard: Manages multiple WordPress installations
- Health Check Scoring: Provides overall site health ratings
- Smart Action Recommendations: Suggests specific fixes for issues
- One-Click Optimizations: Database cleanup, cache purging, plugin updates
- Auto-fix Security Issues: Resolves common security misconfigurations
- Performance Tuning: Applies proven optimization techniques
- Accessibility Improvements: Suggests alt-text and other accessibility fixes
- Clone and install dependencies:
git clone https://github.com/JosephGabito/roko.git
cd roko
composer install| Command | Description |
|---|---|
composer test |
Run all tests (syntax, compatibility, coding standards, unit tests) |
composer phpunit |
Run unit tests only |
composer test-unit |
Run unit test suite |
composer phpcs |
Check WordPress Coding Standards |
composer phpcbf |
Auto-fix coding standards issues |
composer php74-compat |
Check PHP 7.4 compatibility |
composer php70-compat |
Check PHP 7.0 compatibility |
composer syntax-check |
Validate PHP syntax |
# Run all quality checks including unit tests
composer test
# Run just unit tests
composer phpunit
# Fix coding standards
composer phpcbf
# Check PHP 7.4 compatibility
composer php74-compat- Architecture: Domain-Driven Design (DDD) with clean architecture
- Code Standards: WordPress Coding Standards (WPCS)
- Compatibility: PHP 7.0+ compatibility
- Autoloading: PSR-4 autoloading
- Naming: Snake_case for methods and classes (WordPress convention)
- Testing: Unit tested with PHPUnit
- Type Safety: Strict typing where PHP version allows
Presentation → Application → Domain
↑ ↑
Infrastructure ──┘──────────────┘
Key insight: Infrastructure serves higher layers by implementing their contracts:
- Application defines interfaces → Infrastructure implements them
- Domain stays pure → Never depends on external concerns
- Domain emits business codes → Application translates to human text
- Testability → Easy to mock Infrastructure implementations
- Flexibility → Swap WordPress for Laravel/Symfony without changing Domain
Architecture principle: The Domain layer avoids outward dependencies by emitting business codes like weak_constant, strong_roko rather than translated text. This separation allows the Application layer to handle translation concerns independently from business logic.
- ✅ Maintainable: Clear separation of concerns
- ✅ Testable: Easy to unit test business logic
- ✅ Flexible: Easy to swap implementations
- ✅ Scalable: Can handle complex business requirements
- ✅ Framework-Independent: Domain logic works anywhere
- Repository Pattern: Clean data access abstraction
- Aggregate Root: Consistent domain boundaries
- Value Objects: Immutable, self-validating data
- Domain Services: Complex business logic coordination
- Application Services: Use case orchestration
- Dependency Inversion: High-level modules don't depend on low-level modules
./bin/release.sh 1.0.0