Skip to content

Commit a8f282f

Browse files
authored
Updates
1 parent d4c6067 commit a8f282f

File tree

11 files changed

+372
-416
lines changed

11 files changed

+372
-416
lines changed

.github/copilot-instructions.md

Lines changed: 61 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2,111 +2,82 @@
22
applyTo: '**'
33
---
44

5-
# WordPress Plugin Development Standards
5+
# EngineScript Site Optimizer — Development Standards
66

7-
## 🎯 Core Principles
7+
## Project Context
88

9-
**Work Environment:** Remote GitHub Codespaces only. Never suggest local Terminal commands.
9+
- **Plugin:** EngineScript Site Optimizer — WordPress performance optimization plugin
10+
- **Text Domain:** `enginescript-site-optimizer`
11+
- **Function/Hook Prefix:** `es_optimizer_`
12+
- **Version Constant:** `ES_SITE_OPTIMIZER_VERSION`
13+
- **WordPress:** 6.5+ | **PHP:** 7.4+
14+
- **Work Environment:** GitHub Codespaces (remote). Never suggest local terminal commands.
1015

11-
**WordPress First:** Use WordPress APIs, hooks, and standards exclusively. Avoid non-WP frameworks.
16+
## Code Standards
1217

13-
**Security Critical:** Sanitize all input, escape all output, use WordPress security functions.
18+
### WordPress & PHP
1419

15-
**Thorough Analysis:** Read complete files (minimum 1500 lines) for accurate code review.
20+
- Follow [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/) for PHP, JS, CSS, HTML, and accessibility
21+
- Use WordPress APIs and hooks exclusively — no raw PHP/SQL or non-WP frameworks
22+
- Prefix all functions, classes, hooks, and globals with `es_optimizer_`
23+
- Use `wp_die()` instead of `die()` or `exit()`
24+
- Use `WP_Error` for error handling; log errors without exposing sensitive data
25+
- Use PHPDoc with `@param`, `@return`, `@since` tags on all functions
26+
- Organize code by feature; use descriptive names; remove unused code
27+
- Validate all function parameters and handle edge cases gracefully
1628

17-
## 📋 Essential Requirements
29+
### Modern PHP
1830

19-
### WordPress Compatibility
31+
- PHP 7.4+ features are required; PHP 8.x features are allowed if they degrade gracefully on 7.4
32+
- Use typed function signatures wherever possible
33+
- Before submitting changes, run `phpcs`, `phpmd`, and `phpstan` (config files present in project root)
2034

21-
- **WordPress:** 6.5+ minimum
22-
- **PHP:** 7.4+ minimum
23-
- **WooCommerce:** 5.0+ (when applicable)
24-
- Follow [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/) for PHP, JS, CSS, HTML, and accessibility
35+
## Security (Critical)
36+
37+
All code must follow OWASP Top 10 and WordPress security best practices. **Auto-identify and fix security vulnerabilities whenever found — never leave them.**
2538

26-
### Code Quality Standards
39+
**Input:**
40+
- Sanitize with `sanitize_text_field()`, `sanitize_email()`, `absint()`, or `wp_kses()` as appropriate
41+
- Validate nonces with `wp_verify_nonce()` on all form submissions and AJAX handlers
42+
- Use `$wpdb->prepare()` for every database query
2743

28-
1. **Security First:** Always sanitize input (`sanitize_*()`) and escape output (`esc_*()`)
29-
2. **WordPress APIs:** Use WP functions instead of raw PHP/SQL
30-
3. **Hook System:** Proper use of `add_action()` and `add_filter()`
31-
4. **Internationalization:** Use `__()`, `_e()`, `esc_html__()` for all strings
32-
5. **Performance:** Avoid N+1 queries, use WP caching, optimize database calls
44+
**Output:**
45+
- Escape with context-appropriate functions: `esc_html()`, `esc_attr()`, `esc_url()`, `esc_js()`, `esc_textarea()`
46+
- Use `wp_nonce_field()` for all admin forms
3347

34-
## 🔒 Security Requirements (Critical)
48+
**Access Control:**
49+
- Check `current_user_can('manage_options')` before any settings operation
50+
- Always include `if ( ! defined( 'ABSPATH' ) ) { return; }` at the top of every PHP file
51+
- Prevent SQL injection, XSS, CSRF, LFI, and path traversal at all times
3552

36-
**Input Handling:**
37-
- Use `sanitize_text_field()`, `sanitize_email()`, `wp_kses()` for user input
38-
- Validate with `is_email()`, `absint()`, `wp_verify_nonce()` for security
39-
- Use prepared statements for database queries (`$wpdb->prepare()`)
53+
## Performance
4054

41-
**Output Security:**
42-
- Escape all output: `esc_html()`, `esc_attr()`, `esc_url()`, `esc_js()`
43-
- Use `wp_nonce_field()` and `wp_verify_nonce()` for forms
44-
- Check permissions with `current_user_can()` before sensitive operations
55+
- Cache expensive operations with `wp_cache_*()` and transients
56+
- Avoid N+1 queries; optimize all database calls
57+
- Enqueue assets via `wp_enqueue_scripts()` / `wp_enqueue_styles()` with correct dependencies and version strings
58+
- Conditionally load admin assets only on relevant admin pages; conditionally load frontend assets only when needed
4559

46-
**Vulnerability Prevention:**
47-
- Prevent SQL injection, XSS, CSRF, Local File Inclusion (LFI), and path traversal
48-
- Follow principle of least privilege
49-
- Auto-identify and fix security issues when found
60+
## Internationalization (i18n)
5061

51-
## 📝 Documentation & Versioning
62+
- Mark all user-facing strings with `__()`, `_e()`, `esc_html__()`, or `esc_attr__()`
63+
- Always use text domain `enginescript-site-optimizer`
64+
- Update `languages/enginescript-site-optimizer.pot` whenever translatable strings are added or changed
5265

53-
**Changelog Management:**
54-
- Always update CHANGELOG.md and readme.txt when making code changes
55-
- **Sync both changelogs:** CHANGELOG.md and readme.txt changelog section
56-
- Use "Unreleased" section for ongoing changes
66+
## Documentation & Versioning
5767

58-
**Version Release Process (only when instructed):**
68+
**On every code change:**
69+
- Add an entry to the `Unreleased` section of `CHANGELOG.md`
70+
- Mirror the same entry in the changelog section of `readme.txt`
71+
72+
**Version releases (only when explicitly instructed):**
5973
- Follow semantic versioning (MAJOR.MINOR.PATCH)
60-
- Update version in: plugin header, README.md, readme.txt, CHANGELOG.md, GEMINI.md, and `.pot` language files, constants section, package.json, and composer.json
61-
- Move "Unreleased" changes to new version section in both changelogs
62-
- **Never auto-update versions** - wait for explicit instruction
63-
64-
**Code Documentation:**
65-
- Use PHPDoc with `@param`, `@return`, `@since` tags
66-
- Write clear function/class descriptions
67-
- Document security considerations and hooks used
68-
69-
**Internationalization (i18n):**
70-
- Update `.pot` language files when adding or modifying translatable strings
71-
- Always use the correct text domain when dealing with translation functions
72-
- Mark all user-facing strings with `__()`, `_e()`, `esc_html__()`, `esc_attr__()`, etc.
73-
74-
## ⚡ Performance & Quality
75-
76-
**Performance Optimization:**
77-
- Use WordPress caching (`wp_cache_*()`, transients)
78-
- Optimize database queries, avoid N+1 problems
79-
- Proper asset enqueueing with `wp_enqueue_*()` functions
80-
- Focus on correctness first, then optimize
81-
82-
**Code Architecture:**
83-
- Group by feature, not by type
84-
- Use descriptive function/variable names
85-
- Remove unused code automatically
86-
- Follow feature-sliced design when applicable
87-
88-
**Error Handling:**
89-
- Use `WP_Error` for WordPress-specific errors
90-
- Log errors without exposing sensitive data
91-
- Handle edge cases gracefully
92-
- Validate all function parameters
93-
94-
## 🚀 Workflow & Automation
95-
96-
**Task Execution:**
97-
- Make changes directly to existing files (don't create duplicates)
98-
- Proceed automatically unless action is destructive
99-
- Auto-identify and fix bugs when possible
100-
- Only ask confirmation for data loss/deletion scenarios
101-
102-
**File Management:**
103-
- Edit files in place (e.g., modify `admin.php` directly)
104-
- Create new files only when truly necessary
105-
- Avoid file duplication and unnecessary rewrites
106-
- Maintain clean project structure
107-
108-
**Communication:**
109-
- Provide concise, actionable responses
110-
- Use clear formatting for readability
111-
- Never create change summaries as separate .md files
112-
- Focus on specific changes made, not verbose explanations
74+
- Update version in: plugin file header, `ES_SITE_OPTIMIZER_VERSION` constant, `README.md`, `readme.txt`, `CHANGELOG.md`, `GEMINI.md`, `composer.json`, and `languages/enginescript-site-optimizer.pot`
75+
- Move all `Unreleased` entries to the new version section in both `CHANGELOG.md` and `readme.txt`
76+
- **Never auto-bump versions** — wait for an explicit instruction to do so
77+
78+
## Workflow
79+
80+
- Edit files in place — never create duplicate files or unnecessary new files
81+
- Proceed automatically on non-destructive changes; ask before deleting files or data
82+
- Auto-fix bugs and security issues when identified
83+
- Keep responses concise and focused on what changed — no summary `.md` files

.github/workflows/continuous-integration.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
- name: Setup Node.js
4747
uses: actions/setup-node@v6
4848
with:
49-
node-version: '16'
49+
node-version: '20'
5050
# Use conditional caching based on package-lock.json existence
5151
cache: ${{ steps.check-lockfile.outputs.lockfile_exists == 'true' && 'npm' || '' }}
5252
cache-dependency-path: |
@@ -76,7 +76,7 @@ jobs:
7676
7777
- name: Lint PHP
7878
run: |
79-
if [ -f composer.json ] && ([ -f .phpcs.xml ] || [ -f phpcs.xml.dist ]); then
79+
if [ -f composer.json ] && ([ -f .phpcs.xml ] || [ -f phpcs.xml.dist ] || [ -f phpcs.xml ]); then
8080
if grep -q "\"lint:php\"" composer.json; then
8181
composer run lint:php
8282
else
@@ -115,7 +115,7 @@ jobs:
115115
- name: Setup Node.js
116116
uses: actions/setup-node@v6
117117
with:
118-
node-version: '16'
118+
node-version: '20'
119119
# Use conditional caching based on package-lock.json existence
120120
cache: ${{ steps.check-lockfile-build.outputs.lockfile_exists == 'true' && 'npm' || '' }}
121121
cache-dependency-path: |

.github/workflows/release.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ jobs:
5353
cp README.md enginescript-site-optimizer/
5454
cp CHANGELOG.md enginescript-site-optimizer/
5555
cp LICENSE enginescript-site-optimizer/ || echo "No LICENSE file found"
56+
cp readme.txt enginescript-site-optimizer/ || echo "No readme.txt found"
57+
[ -d languages ] && cp -r languages enginescript-site-optimizer/ || echo "No languages directory found"
5658
zip -r enginescript-site-optimizer-${{ steps.get_version.outputs.version }}.zip enginescript-site-optimizer
5759
5860
- name: Get changelog entry
5961
if: steps.check_release.outputs.exists == 'false'
6062
id: get_changelog
6163
run: |
62-
CHANGELOG_ENTRY=$(awk -v ver="## ${{ steps.get_version.outputs.version }}" 'BEGIN{flag=0} $0~ver{flag=1; print; next} /^## [0-9]+\.[0-9]+\.[0-9]+/{flag=0} flag{print}' CHANGELOG.md | tail -n +2)
64+
CHANGELOG_ENTRY=$(awk -v ver="\\[${{ steps.get_version.outputs.version }}\\]" 'BEGIN{flag=0} $0 ~ "^## " ver{flag=1; next} /^## \[/{flag=0} flag{print}' CHANGELOG.md)
6365
echo "changelog<<EOF" >> $GITHUB_OUTPUT
6466
echo "$CHANGELOG_ENTRY" >> $GITHUB_OUTPUT
6567
echo "EOF" >> $GITHUB_OUTPUT

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,38 @@
33
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
44
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
55

6+
## Unreleased
7+
8+
### Fixed
9+
10+
- **Critical**: Fixed License URI in plugin header and readme.txt pointing to GPL 2.0 instead of GPL 3.0
11+
- **Critical**: Fixed release workflow producing incomplete zip files missing `languages/` directory and `readme.txt`
12+
- **Bug**: Fixed changelog parser in release workflow that could not match `## [VERSION]` heading format in CHANGELOG.md, resulting in empty release bodies
13+
- **Bug**: Consolidated duplicate `msgid` entries in POT translation file and corrected license header
14+
- **Bug**: Fixed CI lint step that never ran because it checked for `.phpcs.xml` or `phpcs.xml.dist` but the actual file is `phpcs.xml`
15+
- **Bug**: Fixed README.md license text incorrectly stating GPL-2.0+ instead of GPL-3.0-or-later
16+
17+
### Added
18+
19+
- Added `uninstall.php` to properly clean up plugin options from the database when the plugin is deleted
20+
- Added section headers ("Performance Optimizations", "Header Cleanup", "Additional Features") to the settings page for better UX
21+
- Added `phpcompatibility/phpcompatibility-wp` to `composer.json` `require-dev` (required by `phpcs.xml` ruleset)
22+
- Added `scripts` section to `composer.json` with `lint:php` and `analyze` commands for CI integration
23+
24+
### Changed
25+
26+
- **Modernization**: Added PHP 7.4+ type declarations (parameter types and return types) to all functions
27+
- **Modernization**: Replaced `isset()` ternaries with null coalescing operator (`??`) in render helpers
28+
- **Code Quality**: Standardized all option-checking to use `empty()` with early-return pattern
29+
- **Code Quality**: Consolidated duplicate domain validation, rejection notice, and output functions into shared helpers (`es_optimizer_validate_domain_list()`, `es_optimizer_show_rejection_notice()`, `es_optimizer_get_validated_domains()`)
30+
- **Code Quality**: Removed unnecessary static caching in `es_optimizer_add_preconnect()` and `es_optimizer_add_dns_prefetch()` (hooks only fire once per page load; `es_optimizer_get_options()` already caches)
31+
- **Code Quality**: Replaced deprecated HTML `valign="top"` attribute with standard `<tr>` (WordPress `form-table` CSS already handles alignment)
32+
- **CI**: Updated Node.js from EOL version 16 to LTS version 20 in continuous integration workflow
33+
- **Docs**: Corrected `GEMINI.md` and `readme.txt` feature lists to only include actually implemented features (removed references to XML-RPC, REST API restriction, auto-embeds, and Gutenberg CSS)
34+
- **Docs**: Updated POT translation file with correct line references and added new translatable section header strings
35+
- **Security**: Removed `phpcs:ignore` suppression on preconnect output by using explicit `if/else` branches for the crossorigin attribute
36+
- **Security**: Replaced fragile substring crossorigin detection (`fonts.g`, `gstatic`) with exact hostname matching against `fonts.googleapis.com` and `fonts.gstatic.com`
37+
638
## [2.0.0] - 2026-02-28
739

840
### Changed

GEMINI.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ add_action( 'plugins_loaded', 'es_optimizer_init' );
8484

8585
#### Performance Optimization Features
8686

87-
- **XML-RPC Disabling:** Remove XML-RPC functionality for security and performance
88-
- **JSON REST API Control:** Disable REST API for non-logged users
8987
- **jQuery Migrate Removal:** Remove unnecessary jQuery Migrate script
90-
- **Header Meta Cleanup:** Remove unnecessary WordPress meta tags from head
91-
- **Auto-Embeds Disabling:** Disable WordPress auto-embed functionality
88+
- **Header Meta Cleanup:** Remove unnecessary WordPress meta tags from head (version, RSD, WLW, shortlinks, recent comments style)
9289
- **Emoji Support Removal:** Remove emoji scripts and styles
93-
- **Gutenberg CSS Removal:** Remove unused Gutenberg block styles
90+
- **Classic Theme Styles Removal:** Remove classic theme styles added in WordPress 6.1+
9491
- **DNS Prefetch Management:** User-configurable DNS prefetch for external domains
92+
- **Preconnect Management:** User-configurable preconnect for critical external domains
93+
- **Jetpack Ads Disabling:** Remove Jetpack advertisements and promotions
94+
- **Post via Email Disabling:** Disable WordPress post via email functionality
9595

9696
#### Settings Management
9797

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ Contributions are welcome! Please feel free to submit a Pull Request.
153153

154154
## License
155155

156-
This project is licensed under the GPL-2.0+ License - see the [LICENSE](LICENSE) file for details.
156+
This project is licensed under the GPL-3.0-or-later License - see the [LICENSE](LICENSE) file for details.
157157

158158
## Changelog
159159

composer.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@
2020
"dealerdirect/phpcodesniffer-composer-installer": "^1.0.0",
2121
"php-stubs/wordpress-stubs": "^6.8",
2222
"szepeviktor/phpstan-wordpress": "^1.3",
23-
"phpstan/phpstan": "^1.0"
23+
"phpstan/phpstan": "^1.0",
24+
"phpcompatibility/phpcompatibility-wp": "^2.1"
2425
},
2526
"config": {
2627
"allow-plugins": {
2728
"dealerdirect/phpcodesniffer-composer-installer": true
2829
}
30+
},
31+
"scripts": {
32+
"lint:php": "phpcs",
33+
"analyze": "phpstan analyse"
2934
}
3035
}

0 commit comments

Comments
 (0)