Skip to content

Commit

Permalink
Merge pull request #18 from pimcore/add-interceptor-to-1.x
Browse files Browse the repository at this point in the history
Add intercepter proxy
  • Loading branch information
herbertroth authored Oct 19, 2023
2 parents 9df8f01 + 6055643 commit 7a85296
Show file tree
Hide file tree
Showing 25 changed files with 38,116 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/qodana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,7 @@ jobs:

- name: 'Qodana Scan'
uses: JetBrains/[email protected]
with:
args: --baseline,qodana.sarif.json
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ Static Resolver Bundle is designed to encapsulate the usage of static calls with
## Documentation Overview
- [Installation](doc/01_Installation.md)
- [Resolver Service Usage](doc/02_Resolver_Service_Usage.md)
- [Event Proxy Service Usage](doc/03_Event_Proxy_Service_Usage.md)
- [Event Proxy Service Usage (deprecated)](doc/03_Event_Proxy_Service_Usage.md)
- [Interceptor Proxy Service Usage](doc/03_Interceptor_Proxy_Service_Usage.md)
- [Proxy Service Usage](doc/04_Proxy_Service_Usage.md)
188 changes: 188 additions & 0 deletions doc/03_Interceptor_Proxy_Service_Usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@

# Event Proxy Service Usage

## Overview

`EventProxyService` is a service class that provides functionality to wrap an object's instance with `pre` and `post` method interceptors. These interceptors are triggered right before or after the invocation of the specified methods.

When an interceptor is triggered, an event is dispatched using the `EventDispatcher`. The event name is composed of the lowercase fully-qualified class name of the original object (with backslashes replaced by dots), the lowercase method name, and the prefix (`.pre` or `.post`).

For example, for a pre-interceptor on the `save` method of a class named `App\Entity\User`, the event name will be `app.entity.user.save.pre`.

## `getEventDispatcherProxy()` Method


This method creates a proxy of the given instance and binds `pre` and `post` method interceptors to it.

```php
public function getEventDispatcherProxy(
object $instance,
array $preInterceptors = [],
array $postInterceptors = []
): object;
```

**Parameters:**

- `$instance`: The object instance that needs to be proxied.
- `$preInterceptors` (optional): An array of method names that should be intercepted before their invocation.
- `$postInterceptors` (optional): An array of method names that should be intercepted after their invocation.
- `$customEventName` (optional): A custom event name that will be used in addition to the default one. (`.pre` and `.post` will be added)

**Returns:**

- A proxy of the given `$instance`.

:::info

Final classes can't be proxied.

:::

---

## Example Usage With Symfony's Dependency Injection

### Configuration (`services.yaml`)

```yaml
services:
# ... [other service definitions]

App\EventListener\InterceptorListener:
tags:
- { name: kernel.event_listener, event: 'app.entity.user.save.pre', method: 'onUserSavePre' }
- { name: kernel.event_listener, event: 'app.entity.user.save.post', method: 'onUserSavePost' }
```
### Listener Example
To respond to the dispatched events when interceptors are triggered, you can set up listeners. Here's an example of a listener for the `pre` interceptor of the `save` method on the `App\Entity\User` class:

```php
namespace App\EventListener;
use Pimcore\Bundle\StaticResolverBundle\Proxy\Events\ProxyPostInterceptor;
use Pimcore\Bundle\StaticResolverBundle\Proxy\Events\ProxyPreInterceptor;
use Pimcore\Model\User;
class InterceptorListener
{
public function onUserSavePre(ProxyPreInterceptor $event)
{
/** @var User $userInstance */
$userInstance = $event->getSubject();
/**
* get the called method
* e.g. 'save'
*/
$calledMethod = $event->getMethodName();
/**
* in a post interceptor you can get the return value of the original method.
* E.g use it for caching.
*/
$returnValue = $event->getReturnValue();
/**
* get the used argumetns as associative array
* E.g. ['id' => 12]
*/
$paramters = $event->getMethodArguments()
/**
* get the used argument by name
*/
$id = $event->getMethodArgument('id');
/**
* set the respone that will be returned by the proxy.
* return false if response is locked.
* the original method will not be called. E.g retun cache value. *
*/
$event->setResponse($userInstance);
/**
* disable future setting of the response.
*/
$event->lockResponse();
/**
* bool if the response is locked.
*/
$this->isResponseLocked();
// Your custom logic here. For instance:
// Logging, caching or modifying data before save, etc.
}
public function onUserSavePost(ProxyPostInterceptor $event)
{
/**
* get the called method
* e.g. 'save'
*/
$calledMethod = $event->getMethodName();
/**
* get the called class
* e.g. 'App\Entity\User'
*/
$istanceClass = $event->getSubjectClass();
/**
* get the return value of the original method.
* E.g use it for caching.
*/
$returnValue = $event->getReturnValue();
/**
* get the used arguments as associative array
* E.g. ['id' => 12] use it for caching, etc.
*/
$paramters = $event->getMethodArguments()
/**
* get the used argument by name
*/
$id = $event->getMethodArgument('id');
// Your custom logic here. For instance:
// Logging, caching data after save, etc.
}
}
```

### Using `EventProxyService` in a Controller

```php
use Pimcore\Bundle\StaticResolverBundle\Proxy\Exceptions\EventProxyService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Entity\User;
class YourController extends AbstractController
{
public function someAction(EventProxyService $eventProxyService)
{
$originalObject = new User::getById('12');
$proxyObject = $eventProxyService->getEventDispatcherProxy(
$originalObject,
['save'], // Assuming 'save' is the method we want to pre-intercept
['save'] // Assuming 'save' is the method we want to post-intercept
);
$proxyObject->setLastname('Doe');
$proxyObject->save(); // This will trigger the interceptor(s) for the save method
// Your remaining code
}
}
```

:::info

When the pre-interceptor for the `save` method is triggered, the `onUserSavePre` method in the `InterceptorListener` class will be executed, and you can handle the event as needed.

:::
Loading

0 comments on commit 7a85296

Please sign in to comment.