WPZylos Framework Rules
Compatibility Targets
- PHP: 8.1+ minimum
- WordPress: 6.0+ minimum
Dependency Graph (enforced, no cycles)
core ← nothing
container ← psr/container
hooks, security, config, i18n, database, cli-core ← core
http ← core + security
routing ← core + http + container
validation, views ← core + i18n
migrations ← core + database
wp-cli ← core + migrations (WP_CLI only)
cli-devtool ← cli-core + symfony/console
Architecture Rules
1. No Global Framework Constants
All identity via PluginContext. No define() in framework packages.
2. ContextInterface Pattern
- Framework depends on
ContextInterface - Plugin owns
PluginContextimplementation - Survives PHP-Scoper namespace rewriting
3. Hook Prefixing
wpAction/wpFilter: WordPress core hooks, NEVER prefixedaction/filter/doAction/applyFilter: Custom hooks, ALWAYS prefixed
4. Localization
- All user-facing strings via
$context->textDomain() - No hardcoded text domains in packages
5. Security Requirements
Every state-changing action requires:
- Capability check first (
current_user_can()) - Nonce verification second (
wp_verify_nonce())
Sanitization:
- Sanitize input per field (not blanket)
- Escape output by default (
e,ea,eu,kses)
6. Database Safety
- All queries via
$wpdb->prepare() - Table names via
$context->tableName()(site/network aware)
7. Rewrite Rules
- Flush ONLY on activation/deactivation
- NEVER at runtime
8. PHP-Scoper Safety
- No hardcoded framework namespaces
- Entry file uses plugin-owned classes only
- Framework accessed via container or interface contracts
9. No Hidden Globals
- No global singletons
- Bind everything in container
Gated Dispatch Rules
Dispatch frontend routes only when ALL conditions met:
!is_admin()!wp_doing_cron()!wp_doing_ajax()!(defined('REST_REQUEST') && REST_REQUEST)- Router match found
Override via filter:
apply_filters($context->hook('should_dispatch'), true, $request)
Activation Rules
Activation MAY load:
PluginContextWPAdapter(for rewrite registration)- Route callable (to extract patterns)
Activation MUST NOT boot:
- Container
- Service providers
- Config/Views/Validation/etc.
Escaping Enforcement
- PHP templates: output ONLY through
e()/ea()/eu()/kses() - Twig:
autoescape: 'html'ON by default - Raw output: explicitly marked, strongly discouraged
Multisite Rules
- Migration state:
wp_options(site) orwp_sitemeta(network) - Table naming:
$context->tableName($name, 'site'|'network') - Uninstall: check activation mode, clean correct storage
Plugin Header Requirements
/**
* Plugin Name: My Plugin
* Version: 1.0.0
* Requires at least: 6.0
* Requires PHP: 8.1
* Text Domain: my-plugin
* Domain Path: /resources/lang
*/