Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ entities and generates URLs that need purging based on configured routes.

## Features

- **Doctrine Event Integration**: Listens to **Doctrine** lifecycle events (`postUpdate`, `postRemove`, `postPersist`)
to automatically detect when entities are modified, created, or deleted.
- **Doctrine Event Integration**: Listens to **Doctrine** lifecycle events (`postPersist`, `postUpdate`, `preRemove`)
to automatically detect when entities are created, modified, or deleted.

- **Automatic URL Generation**: Automatically generates purge requests for relevant URLs based on the affected entities
and their associated routes.
Expand Down
47 changes: 31 additions & 16 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ It also provides a `void` purger, which can be used during development when cach
purger simply ignores all purge requests, making it ideal for non-production environments. Additionally, an `in-memory`
purger is included, specifically designed for testing purposes.

For advanced use cases, you can create [custom purgers](custom-purgers.md) to integrate with any custom or
third-party HTTP cache backend that fits your project requirements.
For advanced use cases, you can create [custom purgers](custom-purgers.md) to integrate with any custom or third-party
HTTP cache backend that fits your project requirements.

### Configuring Symfony's HTTP Cache

Expand All @@ -41,6 +41,8 @@ purgatory:
purger: symfony
```

This is a shorthand for `purger: { name: symfony }`.

### Configuring Varnish Cache

To enable Varnish to support `PURGE` requests, add the following example configuration to your VCL file. You may need to
Expand Down Expand Up @@ -123,10 +125,16 @@ bin/console messenger:consume async

## How It Works

The bundle listens to **Doctrine** lifecycle events (`postUpdate`, `postRemove`, `postPersist`) to automatically detect
when entities are modified, created, or deleted. When these changes are flushed to the database, the bundle steps in to
The bundle listens to **Doctrine** lifecycle events (`postPersist`, `postUpdate`, `preRemove`) to automatically detect
when entities are created, modified, or deleted. When these changes are flushed to the database, the bundle steps in to
process them.

By default, the bundle registers a Doctrine DBAL middleware that triggers the processing of collected purge requests
right after the database transaction is committed. This ensures purges only happen for changes that were actually
persisted. If the middleware is disabled (`doctrine_middleware: { enabled: false }`), the bundle falls back to
Doctrine's `postFlush` event instead, which runs after changes are flushed but before an eventual wrapping transaction
is committed.

The bundle uses **purge subscriptions**, which are predefined rules that associate specific entities and their
properties with corresponding routes and route parameters. These subscriptions help identify which content should be
purged based on changes to the entities.
Expand All @@ -147,8 +155,8 @@ entities and properties, giving you greater control over purging behavior in mor
Purge subscriptions can be configured using the [`#[PurgeOn]`][1] attribute. Controllers using this attribute **MUST**
be registered as services.

You can also configure purge subscriptions [using YAML](purge-subscriptions-using-yaml.md). This is particularly
useful if you have routes without an associated controller or action.
You can also configure purge subscriptions [using YAML](purge-subscriptions-using-yaml.md). This is particularly useful
if you have routes without an associated controller or action.

### Basic Example

Expand Down Expand Up @@ -455,7 +463,18 @@ when@test:
```

To write tests, use the `InteractsWithPurgatory` trait in your test class, which provides helper methods to verify
purged URLs and clear the in-memory purger:
purged URLs and clear the in-memory purger.

The following example assumes a `post_details` route with a `{slug}` parameter, where the slug is generated from the
post's title:

```php
#[Route('/post/{slug}', name: 'post_details', methods: 'GET')]
#[PurgeOn(Post::class, routeParams: ['slug' => 'slug'])]
public function detailsAction(Post $post)
{
}
```

```php
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
Expand All @@ -465,17 +484,17 @@ class PurgeTest extends KernelTestCase
{
use InteractsWithPurgatory;

// ...

public function testPurgePost()
{
$entityManager = self::getContainer()->get('doctrine.orm.entity_manager');

// Create and persist a new Post entity
$post = new Post();
$post->title = 'Title';
$post->text = 'Text';

$this->entityManager->persist($post);
$this->entityManager->flush();
$entityManager->persist($post);
$entityManager->flush();

// Assert that the URL for the post has been purged
self::assertUrlIsPurged('/post/title');
Expand All @@ -486,7 +505,7 @@ class PurgeTest extends KernelTestCase
// Update the Post entity and flush the changes
$post->title = 'Title New';

$this->entityManager->flush();
$entityManager->flush();

// Assert that both the old and new URLs have been purged
self::assertUrlIsPurged('/post/title');
Expand Down Expand Up @@ -518,11 +537,7 @@ This command provides insights into which routes and parameters are associated w
- [Custom Expression Language Functions](custom-expression-language-functions.md)

[0]: https://github.com/sofascore/purgatory-bundle/blob/1.x/src/Purger/PurgerInterface.php

[1]: https://github.com/sofascore/purgatory-bundle/blob/1.x/src/Attribute/PurgeOn.php

[2]: https://github.com/sofascore/purgatory-bundle/blob/1.x/src/Attribute/TargetedProperties.php

[3]: https://github.com/sofascore/purgatory-bundle/blob/1.x/src/Listener/Enum/Action.php

[4]: https://github.com/sofascore/purgatory-bundle/blob/1.x/src/Test/InteractsWithPurgatory.php
7 changes: 3 additions & 4 deletions docs/complex-route-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ elements within the collections are purged:

```php
#[Route('/posts/{tag}/{commentId<\d+>}', name: 'posts_list', methods: 'GET')]
#[PurgeOn(Post::class, routeParams: ['tag' => 'tags[*].id', 'commentId' => 'comments[*].id'])]
#[PurgeOn(Post::class, routeParams: ['tag' => 'tags[*].name', 'commentId' => 'comments[*].id'])]
public function listAction(string $tag, Comment $comment)
{
}
Expand Down Expand Up @@ -134,9 +134,8 @@ public function listAction()
}
```

By default, the entire entity being purged is passed to the route parameter service.
If your service only needs a specific part of the entity, you can limit what is passed by providing a second argument to
`DynamicValues`.
By default, the entire entity being purged is passed to the route parameter service. If your service only needs a
specific part of the entity, you can limit what is passed by providing a second argument to `DynamicValues`.

This argument is a **Symfony PropertyAccess property path** and will be resolved against the entity before being passed
to the service:
Expand Down
14 changes: 14 additions & 0 deletions docs/custom-expression-language-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ public function detailsAction(Post $post)
}
```

When used in an `if` expression, the function's return value determines whether the purge occurs, so it should return a
boolean. When used in an `ExpressionValues` expression, it should return the value (or an array of values) to use for
the route parameter:

```php
use Sofascore\PurgatoryBundle\Attribute\RouteParamValue\ExpressionValues;

#[Route('/posts-by-author/{full_name}', name: 'posts_list_by_author', methods: 'GET')]
#[PurgeOn(Author::class, routeParams: ['full_name' => new ExpressionValues('author_full_name(obj)')])]
public function listAction(Author $author)
{
}
```

To enable this functionality, make sure your service is tagged correctly in the service configuration:

```yaml
Expand Down
2 changes: 1 addition & 1 deletion docs/custom-purgers.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class CloudflarePurger implements PurgerInterface
}
```

### Enabling Your Custom Purger
## Enabling Your Custom Purger

To enable your custom purger, update your configuration file with the alias you specified:

Expand Down
17 changes: 8 additions & 9 deletions docs/custom-route-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ To create a custom route provider, implement the [`RouteProviderInterface`][0].
[`PurgeRoute`][1] to define route names and their parameters. You can implement custom logic to determine the
appropriate routes based on the action, the entity, and any changes detected in the entity's properties.

### Example
## Example

Here's an example of a custom route provider for handling `Post` entities:

Expand All @@ -20,6 +20,12 @@ use Sofascore\PurgatoryBundle\RouteProvider\RouteProviderInterface;

class MyPostRouteProvider implements RouteProviderInterface
{
public function supports(Action $action, object $entity): bool
{
// Define the conditions under which this provider should be used
return $entity instanceof Post;
}

public function provideRoutesFor(Action $action, object $entity, array $entityChangeSet): iterable
{
// Custom logic to determine routes based on the action, entity, and changes
Expand All @@ -31,16 +37,10 @@ class MyPostRouteProvider implements RouteProviderInterface
]
);
}

public function supports(Action $action, object $entity): bool
{
// Define the conditions under which this provider should be used
return $entity instanceof Post;
}
}
```

### Registering Your Custom Route Provider
## Registering Your Custom Route Provider

If you're not using
Symfony's [autoconfigure](https://symfony.com/doc/current/service_container.html#the-autoconfigure-option) feature, you
Expand All @@ -57,5 +57,4 @@ By tagging it with `purgatory.route_provider`, the bundle will automatically rec
provider when processing purge requests.

[0]: https://github.com/sofascore/purgatory-bundle/blob/1.x/src/RouteProvider/RouteProviderInterface.php

[1]: https://github.com/sofascore/purgatory-bundle/blob/1.x/src/RouteProvider/PurgeRoute.php
4 changes: 4 additions & 0 deletions docs/purge-subscriptions-using-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Purge subscriptions can also be configured using YAML. This is particularly useful if you have routes without an
associated controller or action.

Each top-level key is the **route name** the subscription applies to. YAML files placed in `config/purgatory/` are
loaded automatically. To load definitions from other files or directories, list them under the `mapping_paths`
Comment thread
Brajk19 marked this conversation as resolved.
configuration option.

To get started, create a YAML file in `config/purgatory/`, for example:

```yaml
Expand Down