Skip to content

Commit 4be188e

Browse files
authored
Merge pull request #160 from amimoto-ami/devin/1754013787-add-path-adjustment-hooks
Add 3 new path adjustment hooks for CloudFront invalidation
2 parents 0e2492b + db2e3b9 commit 4be188e

File tree

7 files changed

+695
-8
lines changed

7 files changed

+695
-8
lines changed

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,37 @@ add_filter( 'c3_invalidation_items', function( $items, $post ) {
7676
}, 10, 2 );
7777
```
7878

79+
### New Path Adjustment Hooks (v7.2.0+)
80+
81+
For more specific control over path invalidation, use these new hooks:
82+
83+
#### Customize home path for single post invalidation
84+
```php
85+
add_filter( 'c3_invalidation_post_batch_home_path', function( $home_path, $post ) {
86+
if ( $post && $post->post_type === 'product' ) {
87+
return '/shop/'; // Invalidate shop page instead of home
88+
}
89+
return $home_path;
90+
}, 10, 2 );
91+
```
92+
93+
#### Customize home path for multiple posts invalidation
94+
```php
95+
add_filter( 'c3_invalidation_posts_batch_home_path', function( $home_path, $posts ) {
96+
if ( count( $posts ) > 5 ) {
97+
return '/'; // Use root path for large bulk operations
98+
}
99+
return $home_path;
100+
}, 10, 2 );
101+
```
102+
103+
#### Customize path for manual "clear all" operations
104+
```php
105+
add_filter( 'c3_invalidation_manual_batch_all_path', function( $all_path ) {
106+
return '/content/*'; // Only clear content directories
107+
});
108+
```
109+
79110
### Custom Implementation
80111

81112
This plugin now uses a custom AWS CloudFront implementation instead of the official AWS SDK to reduce dependencies and improve performance.

classes/AWS/Invalidation_Batch_Service.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ public function put_post_invalidation_batch( Invalidation_Batch $invalidation_ba
107107
*/
108108
public function create_batch_by_post( string $home_url, string $distribution_id, ?\WP_Post $post = null ) {
109109
$invalidation_batch = new Invalidation_Batch();
110-
$invalidation_batch->put_invalidation_path( $home_url );
110+
$home_path = $this->hook_service->apply_filters( 'c3_invalidation_post_batch_home_path', $home_url, $post );
111+
$invalidation_batch->put_invalidation_path( $home_path );
111112
$invalidation_batch = $this->put_post_invalidation_batch( $invalidation_batch, $post );
112113
return $invalidation_batch->get_invalidation_request_parameter( $distribution_id );
113114
}
@@ -121,7 +122,8 @@ public function create_batch_by_post( string $home_url, string $distribution_id,
121122
*/
122123
public function create_batch_by_posts( string $home_url, string $distribution_id, array $posts = array() ) {
123124
$invalidation_batch = new Invalidation_Batch();
124-
$invalidation_batch->put_invalidation_path( $home_url );
125+
$home_path = $this->hook_service->apply_filters( 'c3_invalidation_posts_batch_home_path', $home_url, $posts );
126+
$invalidation_batch->put_invalidation_path( $home_path );
125127
foreach ( $posts as $post ) {
126128
$invalidation_batch = $this->put_post_invalidation_batch( $invalidation_batch, $post );
127129
}
@@ -136,7 +138,8 @@ public function create_batch_by_posts( string $home_url, string $distribution_id
136138
*/
137139
public function create_batch_for_all( string $distribution_id ) {
138140
$invalidation_batch = new Invalidation_Batch();
139-
$invalidation_batch->put_invalidation_path( '/*' );
141+
$all_path = $this->hook_service->apply_filters( 'c3_invalidation_manual_batch_all_path', '/*' );
142+
$invalidation_batch->put_invalidation_path( $all_path );
140143
return $invalidation_batch->get_invalidation_request_parameter( $distribution_id );
141144
}
142145
}

classes/WP/Hooks.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ class Hooks {
2525
*
2626
* @param string $name Hook name.
2727
* @param mixed $value Hooked value.
28+
* @param mixed ...$args Additional arguments to pass to the filter.
2829
*/
29-
public function apply_filters( string $name, $value ) {
30-
return apply_filters( $name, $value );
30+
public function apply_filters( string $name, $value, ...$args ) {
31+
return apply_filters( $name, $value, ...$args );
3132
}
3233

3334
/**

docs/development/filters.md

Lines changed: 206 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,100 @@ add_filter('c3_invalidation_items', function($items, $post) {
4343
}, 10, 2);
4444
```
4545

46+
### `c3_invalidation_post_batch_home_path`
47+
48+
Customize the home path when invalidating a single post.
49+
50+
**Hook Type:** Filter
51+
**Since:** 7.2.0
52+
**Parameters:**
53+
- `$home_path` (string): The home URL/path to be invalidated
54+
- `$post` (WP_Post|null): The post object that triggered the invalidation
55+
56+
**Return:** `string` - Modified home path
57+
58+
**Examples:**
59+
60+
```php
61+
// Use different home path for specific post types
62+
add_filter('c3_invalidation_post_batch_home_path', function($home_path, $post) {
63+
if ($post && $post->post_type === 'product') {
64+
return '/shop/'; // Invalidate shop page instead of home
65+
}
66+
return $home_path;
67+
}, 10, 2);
68+
69+
// Skip home invalidation for draft posts
70+
add_filter('c3_invalidation_post_batch_home_path', function($home_path, $post) {
71+
if ($post && $post->post_status === 'draft') {
72+
return null; // Skip home invalidation
73+
}
74+
return $home_path;
75+
}, 10, 2);
76+
```
77+
78+
### `c3_invalidation_posts_batch_home_path`
79+
80+
Customize the home path when invalidating multiple posts.
81+
82+
**Hook Type:** Filter
83+
**Since:** 7.2.0
84+
**Parameters:**
85+
- `$home_path` (string): The home URL/path to be invalidated
86+
- `$posts` (array): Array of WP_Post objects being invalidated
87+
88+
**Return:** `string` - Modified home path
89+
90+
**Examples:**
91+
92+
```php
93+
// Use different home path for bulk operations
94+
add_filter('c3_invalidation_posts_batch_home_path', function($home_path, $posts) {
95+
if (count($posts) > 5) {
96+
return '/'; // Use root path for large bulk operations
97+
}
98+
return $home_path;
99+
}, 10, 2);
100+
101+
// Custom path based on post types in batch
102+
add_filter('c3_invalidation_posts_batch_home_path', function($home_path, $posts) {
103+
$post_types = array_unique(array_column($posts, 'post_type'));
104+
if (in_array('product', $post_types)) {
105+
return '/shop/';
106+
}
107+
return $home_path;
108+
}, 10, 2);
109+
```
110+
111+
### `c3_invalidation_manual_batch_all_path`
112+
113+
Customize the path for manual "clear all cache" operations.
114+
115+
**Hook Type:** Filter
116+
**Since:** 7.2.0
117+
**Parameters:**
118+
- `$all_path` (string): The path pattern for clearing all cache (default: '/*')
119+
120+
**Return:** `string` - Modified path pattern
121+
122+
**Examples:**
123+
124+
```php
125+
// Use more specific path for manual clear all
126+
add_filter('c3_invalidation_manual_batch_all_path', function($all_path) {
127+
// Only clear content directories instead of everything
128+
return '/content/*';
129+
});
130+
131+
// Environment-specific clear all behavior
132+
add_filter('c3_invalidation_manual_batch_all_path', function($all_path) {
133+
if (wp_get_environment_type() === 'staging') {
134+
return '/staging/*';
135+
}
136+
return $all_path;
137+
});
138+
```
139+
46140
### `c3_credential`
47141

48142
Override AWS credentials programmatically.
@@ -272,6 +366,117 @@ add_action('c3_invalidation_failed', function($paths, $error, $post_id) {
272366
}, 10, 3);
273367
```
274368

369+
## WordPress Subdirectory Installation Support
370+
371+
The new path adjustment hooks (`c3_invalidation_post_batch_home_path`, `c3_invalidation_posts_batch_home_path`, and `c3_invalidation_manual_batch_all_path`) fully support WordPress installations in subdirectories.
372+
373+
### How Subdirectory Support Works
374+
375+
When WordPress is installed in a subdirectory (e.g., `https://example.com/blog/`), the plugin automatically handles subdirectory paths through WordPress's standard `home_url()` function:
376+
377+
**Normal Installation:**
378+
```
379+
WordPress URL: https://example.com/
380+
home_url('/') → https://example.com/
381+
```
382+
383+
**Subdirectory Installation:**
384+
```
385+
WordPress URL: https://example.com/blog/
386+
home_url('/') → https://example.com/blog/
387+
```
388+
389+
### Path Generation Logic
390+
391+
The plugin uses `parse_url()` to extract path components from URLs, which automatically includes subdirectory paths:
392+
393+
```php
394+
// In Invalidation_Batch.php
395+
public function make_invalidate_path( $url ) {
396+
$parse_url = parse_url( $url );
397+
return isset( $parse_url['path'] )
398+
? $parse_url['path'] // Includes subdirectory
399+
: preg_replace( array( '#^https?://[^/]*#', '#\?.*$#' ), '', $url );
400+
}
401+
```
402+
403+
### Subdirectory Examples
404+
405+
#### Example 1: Custom Home Path for Subdirectory Installation
406+
407+
```php
408+
// WordPress installed at https://example.com/blog/
409+
add_filter('c3_invalidation_post_batch_home_path', function($home_path, $post) {
410+
// $home_path automatically contains "/blog/"
411+
412+
if ($post && $post->post_type === 'product') {
413+
return '/blog/shop/'; // Subdirectory + custom path
414+
}
415+
return $home_path; // Default: /blog/
416+
}, 10, 2);
417+
```
418+
419+
#### Example 2: Manual Clear All with Subdirectory Restriction
420+
421+
```php
422+
// Only clear cache within the WordPress subdirectory
423+
add_filter('c3_invalidation_manual_batch_all_path', function($all_path) {
424+
// Restrict clearing to subdirectory only
425+
return '/blog/*'; // Only invalidate /blog/* paths
426+
});
427+
```
428+
429+
#### Example 3: Environment-Specific Subdirectory Handling
430+
431+
```php
432+
add_filter('c3_invalidation_posts_batch_home_path', function($home_path, $posts) {
433+
// Handle different subdirectories per environment
434+
$environment = wp_get_environment_type();
435+
436+
switch ($environment) {
437+
case 'staging':
438+
return '/staging/blog/';
439+
case 'development':
440+
return '/dev/blog/';
441+
default:
442+
return $home_path; // Production subdirectory
443+
}
444+
}, 10, 2);
445+
```
446+
447+
### Testing Subdirectory Support
448+
449+
To test subdirectory functionality, you can simulate a subdirectory installation:
450+
451+
```php
452+
// Test case for subdirectory support
453+
public function test_subdirectory_installation_support() {
454+
// Mock subdirectory home URL
455+
add_filter('home_url', function($url) {
456+
return 'https://example.com/blog/';
457+
});
458+
459+
add_filter('c3_invalidation_post_batch_home_path', function($home_path, $post) {
460+
// Verify subdirectory path is included
461+
return $home_path; // Should be /blog/
462+
}, 10, 2);
463+
464+
$post = $this->factory->post->create_and_get();
465+
$target = new AWS\Invalidation_Batch_Service();
466+
$result = $target->create_batch_by_post('https://example.com/blog/', 'EXXXX', $post);
467+
468+
// Assert subdirectory path is present
469+
$this->assertContains('/blog/', $result['InvalidationBatch']['Paths']['Items']);
470+
}
471+
```
472+
473+
### Key Benefits for Subdirectory Installations
474+
475+
1. **Automatic Path Detection**: No manual configuration needed
476+
2. **Flexible Customization**: Hooks allow fine-tuned control over subdirectory paths
477+
3. **Environment Compatibility**: Works seamlessly across different deployment scenarios
478+
4. **Backward Compatibility**: Existing `c3_invalidation_items` filter continues to work
479+
275480
## Best Practices
276481

277482
### 1. Performance Considerations
@@ -371,4 +576,4 @@ add_action('c3_before_invalidation', function($paths, $post_id) {
371576
}, 10, 2);
372577
```
373578

374-
This comprehensive reference provides all the tools you need to customize C3 CloudFront Cache Controller for your specific use case.
579+
This comprehensive reference provides all the tools you need to customize C3 CloudFront Cache Controller for your specific use case.

0 commit comments

Comments
 (0)