# Skill: WordPress PHP Integration

## Identity
- **Skill ID**: `wordpress-php-integration`
- **Domain**: WordPress Plugin PHP Development
- **Technologies**: PHP 8.0+, WordPress Hooks API
- **Source Agent**: `frontend-php-expert.md`

## When to Load This Skill
- Task involves PHP templates or WordPress integration
- Working with hooks (actions, filters)
- Creating service registration
- Working with translation job handlers
- Files matching: `includes/**/*.php`, `templates/**/*.php`

## Core Patterns

### Required File Header
```php
<?php
declare(strict_types=1);

namespace InternationalPressZone\[Subpackage];

if (!defined('ABSPATH')) {
    exit;
}
```

### Output Escaping (MANDATORY)
```php
// Every output MUST be escaped
echo esc_html($text);              // Plain text
echo esc_attr($value);             // HTML attributes
echo esc_url($url);                // URLs
echo wp_kses_post($html);          // HTML with allowed tags

// In HTML context
<h3><?php echo esc_html__('Title', 'international-press-zone'); ?></h3>
```

### Nonce Verification
```php
$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
if (!wp_verify_nonce($nonce, 'presszone_international_nonce')) {
    wp_send_json_error(['message' => esc_html__('Security check failed.', 'international-press-zone')]);
}
```

### Input Sanitization
```php
// Always sanitize + unslash POST data
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
$content = isset($_POST['content']) ? sanitize_textarea_field(wp_unslash($_POST['content'])) : '';
$key = isset($_POST['key']) ? sanitize_key($_POST['key']) : '';
```

### Template Rendering
```php
function presszone_international_render_template($template_name, $args = []) {
    $allowed_templates = ['language-switcher', 'translation-status', 'admin-settings'];
    if (!in_array($template_name, $allowed_templates, true)) {
        return;
    }

    $args = array_map('sanitize_text_field', $args);
    extract($args);
    include PRESSZONE_INTERNATIONAL_PATH . "templates/{$template_name}.php";
}
```

## Anti-Patterns (Forbidden)

| Mistake | Fix |
|---------|-----|
| Missing `defined('ABSPATH')` | Always add `if (!defined('ABSPATH')) exit;` |
| Echo without escaping | Always use `esc_html()`, `esc_attr()`, etc. |
| Hardcoded URLs | Use `admin_url()`, `home_url()`, `plugins_url()` |
| Missing text domain | Add `'international-press-zone'` to all strings |
| Raw SQL queries | Use `$wpdb->prepare()` |
| Not using `wp_unslash()` | Always unslash `$_POST`/`$_GET` before sanitizing |
| Using `is_admin()` for security | Use `current_user_can()` for capability checks |

## WordPress.org Compliance

### Naming Requirements
- **Namespace**: `InternationalPressZone`
- **Function prefix**: `presszone_international_` (4+ chars)
- **Text domain**: `'international-press-zone'`
- **Option names**: `presszone_international_*`

### Translation Functions
```php
__('Text', 'international-press-zone')
_e('Text', 'international-press-zone')
esc_html__('Text', 'international-press-zone')
esc_attr__('Text', 'international-press-zone')
sprintf(__('Hello %s', 'international-press-zone'), $name)
```

## Integration with Other Skills
- **Often combined with**: `database-operations`, `wordpress-security`
- **For templates with JS**: Load `frontend-javascript`
- **For templates with styling**: Load `frontend-styling-scss`

## Quick Reference

### Hook Registration
```php
add_action('init', [$this, 'register_post_types']);
add_filter('the_content', [$this, 'filter_content'], 10, 1);
add_action('wp_ajax_presszone_international_action', [$this, 'handle_ajax']);
add_action('wp_ajax_nopriv_presszone_international_action', [$this, 'handle_public_ajax']);
```

### AJAX Response Format
```php
// Success
wp_send_json_success([
    'message' => esc_html__('Operation completed.', 'international-press-zone'),
    'data' => $sanitized_data
]);

// Error
wp_send_json_error([
    'message' => esc_html__('Operation failed.', 'international-press-zone'),
    'code' => 'error_code'
]);
```

## Validation Checklist
- [ ] File starts with `if (!defined('ABSPATH')) exit;`
- [ ] All strings use text domain `'international-press-zone'`
- [ ] All output escaped (`esc_html`, `esc_attr`, `esc_url`)
- [ ] All input sanitized (`sanitize_*` functions)
- [ ] Nonces verified for POST/AJAX actions
- [ ] Capability checks with `current_user_can()`
- [ ] No hardcoded URLs or paths
