Skip to content

Commit 8264aad

Browse files
mbabkerphansys
authored andcommitted
Add an IP address provider for extensions referencing IP addresses
1 parent 5b0b8a4 commit 8264aad

File tree

7 files changed

+169
-7
lines changed

7 files changed

+169
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ a release.
1818
---
1919

2020
## [Unreleased]
21+
### Added
22+
- IP address provider for use with extensions with IP address references (#2928)
2123

2224
## [3.19.0] - 2025-02-24
2325
### Added

doc/ip_traceable.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@ $listener = new IpTraceableListener();
2323
$om->getEventManager()->addEventSubscriber($listener);
2424
```
2525

26-
Then, once your application has it available, you can set the IP address to be recorded for changes by calling
27-
the listener's `setIpValue` method.
26+
Then, once your application has it available, you can set the IP address to be recorded. The IP address can be set through
27+
either an [IP address provider service](./utils/ip-address-provider.md) or by calling the listener's `setIpValue` method.
2828

2929
```php
30+
// The $provider must be an implementation of Gedmo\Tool\IpAddressProviderInterface
31+
$listener->setIpAddressProvider($provider);
32+
3033
$listener->setIpValue('127.0.0.1');
3134
```
3235

doc/utils/ip-address-provider.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# IP Address Provider
2+
3+
The Doctrine Extensions package includes support for an "IP address provider" for extensions which use an IP address value, such as
4+
the IP traceable extension.
5+
6+
## Index
7+
8+
- [Getting Started](#getting-started)
9+
10+
## Getting Started
11+
12+
Out of the box, the library does not provide an implementation for the `Gedmo\Tool\IpAddressProviderInterface`, so you will
13+
need to create a class in your application. Below is an example of an IP address provider using Symfony's HttpFoundation component:
14+
15+
```php
16+
namespace App\Utils;
17+
18+
use Gedmo\Tool\IpAddressProviderInterface;
19+
use Symfony\Component\HttpFoundation\RequestStack;
20+
21+
final class RequestIpAddressProvider implements IpAddressProviderInterface
22+
{
23+
private RequestStack $requestStack;
24+
25+
public function __construct(RequestStack $requestStack)
26+
{
27+
$this->requestStack = $requestStack;
28+
}
29+
30+
public function getAddress(): ?string
31+
{
32+
$request = $this->requestStack->getMainRequest();
33+
34+
return $request ? $request->getClientIp() : null;
35+
}
36+
}
37+
```
38+
39+
Once you've created your IP address provider, you can inject it into the listeners for supported extensions by calling
40+
the `setIpAddressProvider` method.
41+
42+
```php
43+
/** @var Gedmo\IpTraceable\IpTraceableListener $listener */
44+
$listener->setIpAddressProvider($provider);
45+
```

src/IpTraceable/IpTraceableListener.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Gedmo\AbstractTrackingListener;
1414
use Gedmo\Exception\InvalidArgumentException;
1515
use Gedmo\IpTraceable\Mapping\Event\IpTraceableAdapter;
16+
use Gedmo\Tool\IpAddressProviderInterface;
1617

1718
/**
1819
* The IpTraceable listener handles the update of
@@ -26,13 +27,15 @@
2627
*/
2728
class IpTraceableListener extends AbstractTrackingListener
2829
{
30+
protected ?IpAddressProviderInterface $ipAddressProvider = null;
31+
2932
/**
3033
* @var string|null
3134
*/
3235
protected $ip;
3336

3437
/**
35-
* Get the ipValue value to set on a ip field
38+
* Get the IP address value to set on an IP address field
3639
*
3740
* @param ClassMetadata<object> $meta
3841
* @param string $field
@@ -42,11 +45,25 @@ class IpTraceableListener extends AbstractTrackingListener
4245
*/
4346
public function getFieldValue($meta, $field, $eventAdapter)
4447
{
48+
if ($this->ipAddressProvider instanceof IpAddressProviderInterface) {
49+
return $this->ipAddressProvider->getAddress();
50+
}
51+
4552
return $this->ip;
4653
}
4754

4855
/**
49-
* Set a ip value to return
56+
* Set an IP address provider for the IP address value.
57+
*/
58+
public function setIpAddressProvider(IpAddressProviderInterface $ipAddressProvider): void
59+
{
60+
$this->ipAddressProvider = $ipAddressProvider;
61+
}
62+
63+
/**
64+
* Set an IP address value to return.
65+
*
66+
* If an IP address provider is also provided, it will take precedence over this value.
5067
*
5168
* @param string|null $ip
5269
*
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Doctrine Behavioral Extensions package.
5+
* (c) Gediminas Morkevicius <[email protected]> http://www.gediminasm.org
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
namespace Gedmo\Tool;
11+
12+
/**
13+
* Interface for a provider for an IP address for extensions supporting IP references.
14+
*/
15+
interface IpAddressProviderInterface
16+
{
17+
public function getAddress(): ?string;
18+
}

tests/Gedmo/IpTraceable/IpTraceableTest.php

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Gedmo\Tests\IpTraceable\Fixture\Article;
2020
use Gedmo\Tests\IpTraceable\Fixture\Comment;
2121
use Gedmo\Tests\IpTraceable\Fixture\Type;
22+
use Gedmo\Tests\TestIpAddressProvider;
2223
use Gedmo\Tests\Tool\BaseTestCaseORM;
2324

2425
/**
@@ -29,16 +30,19 @@
2930
final class IpTraceableTest extends BaseTestCaseORM
3031
{
3132
private const TEST_IP = '34.234.1.10';
33+
private const TEST_PROVIDER_IP = '34.234.2.10';
34+
35+
private IpTraceableListener $listener;
3236

3337
protected function setUp(): void
3438
{
3539
parent::setUp();
3640

37-
$listener = new IpTraceableListener();
38-
$listener->setIpValue(self::TEST_IP);
41+
$this->listener = new IpTraceableListener();
42+
$this->listener->setIpValue(self::TEST_IP);
3943

4044
$evm = new EventManager();
41-
$evm->addEventSubscriber($listener);
45+
$evm->addEventSubscriber($this->listener);
4246

4347
$this->getDefaultMockSqliteEntityManager($evm);
4448
}
@@ -116,6 +120,50 @@ public function testIpTraceable(): void
116120
static::assertSame(self::TEST_IP, $sport->getPublished());
117121
}
118122

123+
public function testIpTraceableWithProvider(): void
124+
{
125+
$this->listener->setIpAddressProvider(new TestIpAddressProvider(self::TEST_PROVIDER_IP));
126+
127+
$sport = new Article();
128+
$sport->setTitle('Sport');
129+
130+
$sportComment = new Comment();
131+
$sportComment->setMessage('hello');
132+
$sportComment->setArticle($sport);
133+
$sportComment->setStatus(0);
134+
135+
$this->em->persist($sport);
136+
$this->em->persist($sportComment);
137+
$this->em->flush();
138+
$this->em->clear();
139+
140+
$sport = $this->em->getRepository(Article::class)->findOneBy(['title' => 'Sport']);
141+
static::assertSame(self::TEST_PROVIDER_IP, $sport->getCreated());
142+
static::assertSame(self::TEST_PROVIDER_IP, $sport->getUpdated());
143+
static::assertNull($sport->getPublished());
144+
145+
$sportComment = $this->em->getRepository(Comment::class)->findOneBy(['message' => 'hello']);
146+
static::assertSame(self::TEST_PROVIDER_IP, $sportComment->getModified());
147+
static::assertNull($sportComment->getClosed());
148+
149+
$sportComment->setStatus(1);
150+
$published = new Type();
151+
$published->setTitle('Published');
152+
153+
$sport->setTitle('Updated');
154+
$sport->setType($published);
155+
$this->em->persist($sport);
156+
$this->em->persist($published);
157+
$this->em->persist($sportComment);
158+
$this->em->flush();
159+
$this->em->clear();
160+
161+
$sportComment = $this->em->getRepository(Comment::class)->findOneBy(['message' => 'hello']);
162+
static::assertSame(self::TEST_PROVIDER_IP, $sportComment->getClosed());
163+
164+
static::assertSame(self::TEST_PROVIDER_IP, $sport->getPublished());
165+
}
166+
119167
public function testForcedValues(): void
120168
{
121169
$sport = new Article();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Doctrine Behavioral Extensions package.
7+
* (c) Gediminas Morkevicius <[email protected]> http://www.gediminasm.org
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Gedmo\Tests;
13+
14+
use Gedmo\Tool\IpAddressProviderInterface;
15+
16+
final class TestIpAddressProvider implements IpAddressProviderInterface
17+
{
18+
private ?string $address;
19+
20+
public function __construct(?string $address)
21+
{
22+
$this->address = $address;
23+
}
24+
25+
public function getAddress(): ?string
26+
{
27+
return $this->address;
28+
}
29+
}

0 commit comments

Comments
 (0)