Skip to content

Commit 2414af3

Browse files
Merge pull request #758 from stellarwp/feature/KAD-4362/performance-optimizer
[KAD-4362]: Performance optimizer
2 parents db4e430 + 543d544 commit 2414af3

202 files changed

Lines changed: 26834 additions & 1130 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
---
2+
description: Kadence Blocks WordPress plugin development standards and conventions
3+
globs: **/*.php
4+
alwaysApply: false
5+
---
6+
7+
# Kadence Blocks - PHP Cursor Rules
8+
9+
## Project Overview
10+
This is a WordPress plugin project (Kadence Blocks) that provides Gutenberg blocks for page building. The codebase follows WordPress VIP-Go coding standards, uses modern PHP 7.4+ features, and includes comprehensive testing with Codeception.
11+
12+
## File Structure & Naming Conventions
13+
14+
### PHP Files
15+
- Use `<?php declare( strict_types=1 );` at the start of all PHP files
16+
- Follow PSR-4 autoloading: `KadenceWP\KadenceBlocks\` namespace maps to `includes/resources/`
17+
- Test files use `Tests\` namespace mapping to `tests/`
18+
- Class names use Snake_Case, file names match class names
19+
- REST controllers end with `_Rest_Controller` (underscore convention for WordPress)
20+
- Response classes use PascalCase without underscores
21+
22+
### Directory Structure
23+
```
24+
includes/resources/ # Main application code (PSR-4: KadenceWP\KadenceBlocks\)
25+
├── Optimizer/ # Performance optimization features
26+
│ ├── assets/ # Frontend assets specific to this feature
27+
│ ├── Response/ # Data transfer objects
28+
│ ├── Rest/ # REST API controllers
29+
│ └── Store/ # Data persistence layer
30+
tests/wpunit/ # WordPress unit tests
31+
├── Resources/ # Mirror of includes/resources structure
32+
src/ # Frontend JavaScript/CSS source
33+
```
34+
35+
## PHP Coding Standards
36+
37+
### General PHP
38+
- Use strict typing: `declare( strict_types=1 );`
39+
- Use typed properties and return types
40+
- Prefer `final` classes unless inheritance is intended
41+
- Use short array syntax `[]` instead of `array()`
42+
- Use static anonymous functions: `static fn( $value ) => (int) $value`
43+
44+
### WordPress Integration
45+
- Follow WordPress VIP-Go coding standards
46+
- Use WordPress coding conventions for hooks, filters, and function names
47+
- Prefix custom capabilities and error codes with plugin identifier
48+
- Use `current_user_can()` for permission checks
49+
- Use `WP_Error` for error handling in REST APIs
50+
51+
### REST API Controllers
52+
- Extend `WP_REST_Controller`
53+
- Use public constants for parameter names: `public const POST_ID = 'post_id';`
54+
- Implement permission callbacks for all endpoints
55+
- Use appropriate HTTP status codes from `WP_Http` class
56+
- Sanitize parameters with callbacks: `'sanitize_callback' => static fn( $value ) => (int) $value`
57+
58+
### Error Handling
59+
- Use descriptive error codes with plugin prefix: `rest_kb_`
60+
- Include relevant context in error data (e.g., `post_id`)
61+
- Use appropriate HTTP status codes
62+
- Provide user-friendly error messages with `__()` for i18n
63+
64+
## Testing Conventions
65+
66+
### Test Structure
67+
- Use Codeception with WordPress integration (`wpunit` suite)
68+
- Extend `Tests\Support\Classes\TestCase` for dependency injection support
69+
- Use `final class` for test classes
70+
- Test classes always use PascalCase
71+
- Test file names always use PascalCase and end with `Test.php`
72+
73+
### Test Setup & Teardown
74+
```php
75+
protected function setUp(): void {
76+
parent::setUp();
77+
78+
// Get dependencies from container
79+
$this->store = $this->container->get( Store::class );
80+
81+
// Create test data using factories
82+
$this->post_id = $this->factory()->post->create([
83+
'post_title' => 'Test Post',
84+
'post_status' => 'publish',
85+
]);
86+
87+
// Initialize REST server
88+
global $wp_rest_server;
89+
$this->rest_server = new WP_REST_Server();
90+
$wp_rest_server = $this->rest_server;
91+
do_action( 'rest_api_init' );
92+
}
93+
94+
protected function tearDown(): void {
95+
// Clean up test data
96+
$this->store->delete( $this->post_id );
97+
wp_set_current_user( 0 );
98+
99+
// Reset global REST server
100+
global $wp_rest_server;
101+
$wp_rest_server = null;
102+
103+
parent::tearDown();
104+
}
105+
```
106+
107+
### Test Naming & Organization
108+
- Use descriptive test method names: `testCreateItemPermissionDeniedForSubscriber`
109+
- Test both success and failure scenarios
110+
- Test different user roles and permissions
111+
- Use constants for parameter names: `Optimize_Rest_Controller::POST_ID`
112+
113+
### Test Patterns
114+
- Use `wp_set_current_user()` to test different user contexts
115+
- Use `$this->factory()` for creating test data
116+
- Use `$this->fixture()` for loading test fixtures
117+
- Test parameter sanitization through REST API dispatch
118+
- Verify both response structure and stored data
119+
120+
### Assertions
121+
- Use specific assertions: `$this->assertInstanceOf()`, `$this->assertEquals()`
122+
- Test HTTP status codes using `WP_Http` constants
123+
- Verify error codes and messages
124+
- Check data integrity after operations
125+
- Use `$this->assertNotInstanceOf( WP_Error::class, $response )` for success cases
126+
127+
## Dependencies & Architecture
128+
129+
### Dependency Injection
130+
- Use `lucatume/di52` container
131+
- Access dependencies via `$this->container->get( Class::class )`
132+
- Register services in provider classes
133+
134+
### Data Layer
135+
- Use contracts/interfaces where appropriate
136+
- Implement repository pattern for data access
137+
- Use typed response objects for API data
138+
139+
## Code Style Preferences
140+
141+
### Comments
142+
- End all comments with periods for consistency
143+
- Use PHPDoc blocks for methods and classes
144+
- Inline comments should be concise and end with periods
145+
146+
### Formatting
147+
- Use tabs for indentation (WordPress standard)
148+
- Align assignments and array elements
149+
- Put opening braces on same line for methods
150+
- Use trailing commas in multi-line arrays
151+
152+
### Modern PHP Features
153+
- Use typed properties and parameters
154+
- Use arrow functions for simple callbacks
155+
- Use null coalescing operator `??` when appropriate
156+
- Use match expressions over switch when suitable
157+
158+
## WordPress Specific
159+
160+
### Hooks & Filters
161+
- Use descriptive hook names with plugin prefix
162+
- Document hook parameters and expected values
163+
- Use priority 10 unless specific ordering needed
164+
165+
### Internationalization
166+
- Wrap user-facing strings in `__()` or `_e()`
167+
- Use 'kadence-blocks' text domain consistently
168+
- Provide context with `_x()` when needed
169+
170+
### Security
171+
- Sanitize all input data
172+
- Validate user permissions before operations
173+
- Use nonces for form submissions
174+
- Escape output data appropriately
175+
176+
## Build & Development
177+
178+
### Asset Management
179+
- Source files in `src/` directory
180+
- Built assets in `includes/assets/`
181+
- Use webpack for JavaScript bundling
182+
- Use Gulp for additional build tasks
183+
184+
### Code Quality
185+
- Run PHPCS with project's phpcs.xml configuration
186+
- Use PHP 7.4+ compatibility checks
187+
- Follow WordPress VIP-Go standards
188+
- Use Prettier for JavaScript formatting
189+
190+
## Testing Commands
191+
- `slic run wpunit` - Run all WordPress unit/integration tests
192+
- `slic run wpunit <path/to/TestClass>` - Run specific test class using **file system path from tests/wpunit/** (without .php extension)
193+
- `slic run wpunit <path/to/TestClass::testMethod>` - Run specific test method
194+
- `slic run acceptance` - Run all WordPress acceptance suite tests
195+
196+
### Test Path Examples:
197+
- For test file `tests/wpunit/Resources/Optimizer/RequestAnonymizerTest.php`:
198+
- Command: `slic run wpunit Resources/Optimizer/RequestAnonymizerTest`
199+
- For test file `tests/wpunit/Blocks/SomeBlockTest.php`:
200+
- Command: `slic run wpunit Blocks/SomeBlockTest`
201+
- For specific method in test:
202+
- Command: `slic run wpunit Resources/Optimizer/RequestAnonymizerTest::testSpecificMethod`
203+
- For a test in a different suite:
204+
- Command: `slic run acceptance AdvancedFormCest`
205+
206+
**Important**: Use the file system path from the `tests/$suite/` directory, NOT the full namespace or file path with extension.
207+
208+
## Key Principles
209+
1. **Type Safety**: Use strict typing throughout
210+
2. **WordPress Integration**: Follow WordPress conventions and standards
211+
3. **Test Coverage**: Write comprehensive tests for all functionality
212+
4. **Error Handling**: Provide clear, actionable error messages
213+
5. **Security**: Always validate permissions and sanitize data
214+
6. **Performance**: Consider caching and optimization in data operations
215+
7. **Maintainability**: Use clear naming and consistent patterns

.distignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/src
66
/node_modules
77
/tests
8+
/.cursor
89

910
.distignore
1011
.gitignore
@@ -31,3 +32,5 @@ codeception.slic.yml
3132
.gitattributes
3233
.gitmodules
3334
.wordpress-org/
35+
.npmrc
36+
bunfig.toml

.eslintrc.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ const eslintConfig = {
1010
webpack: {
1111
config: path.join(__dirname, '/webpack.config.js'),
1212
},
13+
alias: [
14+
['@kadence-bundled/admin-notices', './src/extension/admin-notices'],
15+
['@kadence/optimizer', './includes/resources/Optimizer/assets/js/optimizer'],
16+
],
1317
},
1418
},
1519
globals: {
@@ -58,6 +62,8 @@ const eslintConfig = {
5862
Image: 'readable',
5963
Masonry: 'readable',
6064
IntersectionObserver: 'readable',
65+
requestAnimationFrame: 'readable',
66+
requestIdleCallback: 'readable',
6167
getComputedStyle: 'readable',
6268
ScrollMagic: 'readable',
6369
kadence_pro_video_pop: 'readable',

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ composer.lock text -diff
2020
/codeception.dist.yml export-ignore
2121
/codeception.slic.yml export-ignore
2222
/tests export-ignore
23+
/.cursor export-ignore

.github/workflows/compatibility.yml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,6 @@ jobs:
2727
extensions: mbstring, intl
2828
coverage: none
2929

30-
- name: Get Composer Cache Directory
31-
id: composer-cache
32-
run: |
33-
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
34-
35-
- uses: actions/cache@v4
36-
with:
37-
path: ${{ steps.composer-cache.outputs.dir }}
38-
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
39-
restore-keys: |
40-
${{ runner.os }}-composer-
41-
4230
- uses: ramsey/composer-install@v3
4331
with:
4432
dependency-versions: highest

.github/workflows/deploy-on-release.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,14 @@ jobs:
5151
- name: Configure Composer token
5252
run: composer config -g github-oauth.github.com ${{ secrets.COMPOSER_TOKEN }}
5353

54+
- name: Setup node
55+
uses: actions/setup-node@v4
56+
with:
57+
registry-url: 'https://npm.pkg.github.com'
58+
5459
- name: Build
60+
env:
61+
NODE_AUTH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
5562
run: |
5663
composer install --no-dev --no-scripts
5764
composer run strauss-release

.github/workflows/eslint.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
uses: actions/checkout@v4
1414

1515
- name: Install Bun
16-
uses: oven-sh/setup-bun@v1
16+
uses: oven-sh/setup-bun@v2
1717
with:
1818
bun-version: latest
1919

@@ -28,6 +28,8 @@ jobs:
2828
# ESLint and Prettier must be in `package.json`
2929
- name: Install dependencies
3030
run: bun install --frozen-lockfile
31+
env:
32+
BUN_AUTH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
3133

3234
- name: Run linters
3335
uses: wearerequired/lint-action@v2

.github/workflows/ghost-inspector.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@ jobs:
2121
- name: Setup Composer
2222
run: composer config -g github-oauth.github.com ${{ secrets.COMPOSER_TOKEN }}
2323

24+
- name: Setup node
25+
uses: actions/setup-node@v4
26+
with:
27+
registry-url: 'https://npm.pkg.github.com'
28+
2429
- name: Build plugin
30+
env:
31+
NODE_AUTH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
2532
run: |
2633
composer install --no-dev --no-scripts
2734
composer run strauss-release

.github/workflows/google-fonts.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ jobs:
1515
- name: Setup Node.js
1616
uses: actions/setup-node@v4
1717
with:
18+
registry-url: 'https://npm.pkg.github.com'
1819
node-version: '20'
1920

2021
- name: Install dependencies
2122
run: npm install --no-save @octokit/rest axios --legacy-peer-deps
23+
env:
24+
NODE_AUTH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
2225

2326
- name: Update fonts data
2427
env:

.github/workflows/plugin-check.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ jobs:
1616
with:
1717
submodules: 'true'
1818

19+
- name: Setup node
20+
uses: actions/setup-node@v4
21+
with:
22+
registry-url: 'https://npm.pkg.github.com'
23+
1924
- name: Install dependencies
25+
env:
26+
NODE_AUTH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
2027
run: |
2128
composer install --no-dev --no-scripts
2229
composer run strauss-release

0 commit comments

Comments
 (0)